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
|