Repository navigation
Expand file tree
/
Copy pathhelp.lua
More file actions
139 lines (133 loc) · 4.61 KB
/
Copy pathhelp.lua
File metadata and controls
139 lines (133 loc) · 4.61 KB
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
local M = {}
local ns = vim.api.nvim_create_namespace('OpencodeSessionDiffHelp')
local action_order = {
activate = 1,
toggle_range = 2,
mark_from = 3,
mark_to = 4,
show_message_preview = 5,
toggle_view = 6,
hide_message_preview = 7,
close = 8,
toggle_help = 9,
add_comment = 10,
delete_comment = 11,
next_comment = 12,
prev_comment = 13,
submit_comment = 14,
cancel_comment = 15,
next_file = 16,
prev_file = 17,
select = 18,
open_file = 19,
}
---@class OpencodeSessionDiffHelpSection
---@field title string
---@field entries {key: string, action: string, label: string}[]
---@field width integer
---@param title string
---@param mappings OpencodeSessionDiffMappings
---@return OpencodeSessionDiffHelpSection
local function section(title, mappings)
local entries = {}
for key, entry in pairs(mappings) do
if entry ~= false then
local action = type(entry[1]) == 'string' and entry[1] or 'Custom callback'
entries[#entries + 1] = { key = key, action = action, label = entry.desc or action }
end
end
table.sort(entries, function(a, b)
local left, right = action_order[a.action] or 10, action_order[b.action] or 10
return left == right and a.key < b.key or left < right
end)
local width = vim.fn.strdisplaywidth(' ' .. title)
for _, entry in ipairs(entries) do
width = math.max(width, vim.fn.strdisplaywidth((' %-8s %s'):format(entry.key, entry.label)))
end
return { title = title, entries = entries, width = width }
end
---@param keymaps OpencodeSessionDiffKeymaps
---@return integer, integer, integer
function M.create(keymaps)
local sections = {
section('FILES', keymaps.list),
section('MESSAGES', keymaps.messages),
section('DIFF PREVIEW', keymaps.preview),
section('MESSAGE PREVIEW', keymaps.message_preview),
section('REVIEW COMMENT', keymaps.comment),
}
local columns = math.max(sections[1].width, sections[3].width) + math.max(sections[2].width, sections[4].width) + 3
<= vim.o.columns - 8
and 2
or 1
local lines = {}
---@type {row: integer, start: integer, finish: integer, group: string}[]
local marks = {}
local function mark(row, start, finish, group)
marks[#marks + 1] = { row = row, start = start, finish = finish, group = group }
end
for group_index = 1, #sections, columns do
if #lines > 0 then
lines[#lines + 1] = ''
end
local left = sections[group_index] --[[@as OpencodeSessionDiffHelpSection]]
local right = columns == 2 and sections[group_index + 1] or nil
local left_width = columns == 2 and math.max(sections[1].width, sections[3].width) or left.width
local count = math.max(#left.entries, right and #right.entries or 0)
for row = 0, count do
local function cell(current)
if not current then
return '', 0, nil
end
if row == 0 then
return ' ' .. current.title, #current.title, 'Title'
end
local entry = current.entries[row]
if not entry then
return '', 0, nil
end
return (' %-8s %s'):format(entry.key, entry.label), #entry.key, 'Special'
end
local left_text, left_key, left_group = cell(left)
local right_text, right_key, right_group = cell(right)
local padding = right and string.rep(' ', left_width - vim.fn.strdisplaywidth(left_text) + 3) or ''
lines[#lines + 1] = left_text .. padding .. right_text
if left_group then
mark(#lines - 1, 2, 2 + left_key, left_group)
end
if right_group then
local start = #left_text + #padding + 2
mark(#lines - 1, start, start + right_key, right_group)
end
end
end
local close_keys = {}
for key, entry in pairs(keymaps.help) do
if entry ~= false and entry[1] == 'toggle_help' then
close_keys[#close_keys + 1] = key
end
end
table.sort(close_keys)
lines[#lines + 1] = ''
local footer = ' ' .. table.concat(close_keys, ' · ') .. ' close'
lines[#lines + 1] = footer
mark(#lines - 1, 2, #footer, 'Comment')
local width = 1
for _, line in ipairs(lines) do
width = math.max(width, vim.fn.strdisplaywidth(line))
end
width = math.min(width + 2, math.max(1, vim.o.columns - 4))
local height = math.min(#lines, math.max(1, vim.o.lines - 4))
local buf = vim.api.nvim_create_buf(false, true)
vim.bo[buf].bufhidden = 'wipe'
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
vim.bo[buf].modifiable = false
for _, highlight in ipairs(marks) do
vim.api.nvim_buf_set_extmark(buf, ns, highlight.row, highlight.start, {
end_col = highlight.finish,
hl_group = highlight.group,
})
end
return buf, width, height
end
return M