summaryrefslogtreecommitdiffstats
path: root/lua/inbox/utils.lua
blob: c5954a88e28d4abf2c2454fe5b5368d5241873d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
local M = {}

---@class inbox.TextChunk
---@field [1] string text
---@field [2] string hl

---@param text string
---@param length nil|integer
---@return string
function M.rpad(text, length)
	if not length then
		return text
	end

	if text:len() <= length then
		return text .. string.rep(" ", length - text:len())
	else
		return string.sub(text, 1, length - 3) .. "..."
	end
end

---@param cols (string | inbox.TextChunk)[]
---@param col_widths integer[]
---@return string
---@return any[][] List of highlights {group, col_start, col_end}
function M.render_row(cols, col_widths)
	local pieces = {}
	local highlights = {}

	local col = 0
	for i, chunk in ipairs(cols) do
		local text, hl
		if type(chunk) == "table" then
			text, hl = unpack(chunk) --[[@as string]]
		else
			text = chunk --[[@as string]]
		end
		text = M.rpad(text, col_widths[i])
		table.insert(pieces, text)
		local col_end = col + text:len() + 1
		if hl then
			table.insert(highlights, { hl, col, col_end })
		end
		col = col_end
	end

	return table.concat(pieces, " "), highlights
end

---@param rows (string | inbox.TextChunk)[][]
---@param col_widths integer[]
---@return string[]
---@return any[][] List of highlights {group, lnum, col_start, col_end}
function M.render_table(rows, col_widths)
	local lines = {}
	local highlights = {}

	for lnum, cols in ipairs(rows) do
		local line, line_hls = M.render_row(cols, col_widths)
		table.insert(lines, line)

		for _, hl in pairs(line_hls) do
			local group, col_start, col_end = unpack(hl)
			table.insert(highlights, { group, lnum, col_start, col_end })
		end
	end

	return lines, highlights
end

---@param winid integer
---@param cols (string | inbox.TextChunk)[]
---@param col_widths integer[]
function M.render_winbar(winid, cols, col_widths)
	local winbar = M.render_row(cols, col_widths)
	local offset = vim.fn.getwininfo(winid)[1].textoff + 1
	vim.api.nvim_set_option_value("winbar", string.rep(" ", offset) .. winbar, { scope = "local", win = winid })
end

---@param name string
---@return string sign_name
function M.sign_name(name)
	return "Inbox" .. name:gsub("^%l", string.upper)
end

---@param bufnr integer
---@param highlights any[][] List of highlights { group, lnum, col_start, col_end }
M.set_highlights = function(bufnr, highlights)
	local ns = vim.api.nvim_create_namespace("Oil")
	vim.api.nvim_buf_clear_namespace(bufnr, ns, 0, -1)
	for _, hl in ipairs(highlights) do
		vim.api.nvim_buf_add_highlight(bufnr, ns, unpack(hl))
	end
end

---@param bufnr integer
---@param signs any[][] List of signs { name, lnum }
function M.set_signs(bufnr, signs)
	local notified = {}

	for _, sign_lnum in pairs(signs) do
		local sign, lnum = unpack(sign_lnum)
		local name = M.sign_name(sign)

		if #vim.fn.sign_getdefined(name) > 0 then
			vim.fn.sign_place(0, "inbox", name, bufnr, { lnum = lnum })
		elseif not notified[name] then
			vim.notify(("Missing sign definition for sign: %s"):format(name), vim.log.levels.ERROR)
			notified[name] = true
		end
	end
end

---@param json string
---@return table data
function M.json_decode(json)
	local results = {}
	if json and json ~= "" then
		results = vim.json.decode(json) or {}
	end
	return results
end

---@param bufnr integer
---@return string? maildir maildir name
---@return string? id entry id
function M.parse_scheme(bufnr)
	local bufname = vim.api.nvim_buf_get_name(bufnr or 0)

	local _, init, maildir = bufname:find("maildir://([^:]+)")
	local _, _, id = bufname:find(":(.*)", init)

	return maildir, id
end

function M.stateful_iter(table, wrap)
	local k
	local s_k, s_v = next(table)
	return function()
		local v
		k, v = next(table, k)
		if k == nil and wrap then
			k, v = s_k, s_v
		end
		return k, v
	end
end

return M