Skip to content

Commit c326140

Browse files
committed
feat(#3): add help popup (?) and improve sidebar action feedback
1 parent c130830 commit c326140

4 files changed

Lines changed: 269 additions & 40 deletions

File tree

lua/dbab/ui/help.lua

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
local config = require("dbab.config")
2+
3+
local M = {}
4+
5+
local ns = vim.api.nvim_create_namespace("dbab_help")
6+
7+
---@param key string|string[]
8+
---@return string
9+
local function format_key(key)
10+
if type(key) == "table" then
11+
return table.concat(key, " / ")
12+
end
13+
return key
14+
end
15+
16+
---@class HelpEntry
17+
---@field key string
18+
---@field label string
19+
---@field category string
20+
21+
---@param title string
22+
---@param sections table<string, HelpEntry[]>
23+
local function show_float(title, sections)
24+
local lines = {}
25+
local highlights = {}
26+
local max_key_len = 0
27+
28+
for _, entries in pairs(sections) do
29+
for _, entry in ipairs(entries) do
30+
local klen = vim.fn.strdisplaywidth(entry.key)
31+
if klen > max_key_len then
32+
max_key_len = klen
33+
end
34+
end
35+
end
36+
37+
local section_order = { "Actions", "Navigation", "Global" }
38+
39+
for _, section_name in ipairs(section_order) do
40+
local entries = sections[section_name]
41+
if entries and #entries > 0 then
42+
if #lines > 0 then
43+
table.insert(lines, "")
44+
end
45+
table.insert(lines, " " .. section_name)
46+
table.insert(highlights, { line = #lines - 1, col = 2, len = #section_name, hl = "DbabHistoryHeader" })
47+
48+
for _, entry in ipairs(entries) do
49+
local klen = vim.fn.strdisplaywidth(entry.key)
50+
local padding = string.rep(" ", max_key_len - klen + 3)
51+
local line = " " .. entry.key .. padding .. entry.label
52+
table.insert(lines, line)
53+
table.insert(highlights, { line = #lines - 1, col = 4, len = #entry.key, hl = "DbabKey" })
54+
end
55+
end
56+
end
57+
58+
table.insert(lines, "")
59+
table.insert(lines, " Press ? or q to close")
60+
table.insert(highlights, { line = #lines - 1, col = 2, len = 22, hl = "Comment" })
61+
62+
local width = 0
63+
for _, line in ipairs(lines) do
64+
local w = vim.fn.strdisplaywidth(line)
65+
if w > width then
66+
width = w
67+
end
68+
end
69+
width = width + 4
70+
71+
local height = #lines
72+
local row = math.floor((vim.o.lines - height) / 2)
73+
local col = math.floor((vim.o.columns - width) / 2)
74+
75+
local buf = vim.api.nvim_create_buf(false, true)
76+
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
77+
vim.bo[buf].modifiable = false
78+
vim.bo[buf].bufhidden = "wipe"
79+
80+
for _, hl in ipairs(highlights) do
81+
local line_len = #lines[hl.line + 1]
82+
local end_col = math.min(hl.col + hl.len, line_len)
83+
if hl.col < line_len then
84+
vim.api.nvim_buf_set_extmark(buf, ns, hl.line, hl.col, {
85+
end_col = end_col,
86+
hl_group = hl.hl,
87+
})
88+
end
89+
end
90+
91+
local win = vim.api.nvim_open_win(buf, true, {
92+
relative = "editor",
93+
row = row,
94+
col = col,
95+
width = width,
96+
height = height,
97+
style = "minimal",
98+
border = "rounded",
99+
title = " " .. title .. " Help ",
100+
title_pos = "center",
101+
})
102+
103+
vim.wo[win].cursorline = false
104+
vim.wo[win].wrap = false
105+
106+
local close = function()
107+
if vim.api.nvim_win_is_valid(win) then
108+
vim.api.nvim_win_close(win, true)
109+
end
110+
end
111+
112+
vim.keymap.set("n", "q", close, { buffer = buf, nowait = true })
113+
vim.keymap.set("n", "?", close, { buffer = buf, nowait = true })
114+
vim.keymap.set("n", "<Esc>", close, { buffer = buf, nowait = true })
115+
end
116+
117+
---@param keymaps table
118+
---@param action string
119+
---@param label string
120+
---@param category string
121+
---@param entries HelpEntry[]
122+
local function add_entry(keymaps, action, label, category, entries)
123+
local key = keymaps[action]
124+
if key then
125+
table.insert(entries, { key = format_key(key), label = label, category = category })
126+
end
127+
end
128+
129+
---@param entries HelpEntry[]
130+
---@return table<string, HelpEntry[]>
131+
local function group_by_category(entries)
132+
local grouped = {}
133+
for _, entry in ipairs(entries) do
134+
if not grouped[entry.category] then
135+
grouped[entry.category] = {}
136+
end
137+
table.insert(grouped[entry.category], entry)
138+
end
139+
return grouped
140+
end
141+
142+
function M.show_sidebar()
143+
local cfg = config.get()
144+
local km = cfg.keymaps.sidebar
145+
local entries = {}
146+
147+
add_entry(km, "toggle_expand", "Toggle expand", "Actions", entries)
148+
add_entry(km, "refresh", "Refresh", "Actions", entries)
149+
add_entry(km, "new_query", "New query", "Actions", entries)
150+
add_entry(km, "rename", "Rename query", "Actions", entries)
151+
add_entry(km, "delete", "Delete", "Actions", entries)
152+
add_entry(km, "insert_template", "Insert SELECT query", "Actions", entries)
153+
add_entry(km, "copy_name", "Copy name", "Actions", entries)
154+
add_entry(km, "copy_query", "Copy query content", "Actions", entries)
155+
add_entry(km, "paste_query", "Paste as new query", "Actions", entries)
156+
157+
add_entry(km, "to_editor", "Go to editor", "Navigation", entries)
158+
add_entry(km, "to_history", "Go to history", "Navigation", entries)
159+
160+
table.insert(entries, { key = format_key(cfg.keymaps.close), label = "Close dbab", category = "Global" })
161+
162+
show_float("Sidebar", group_by_category(entries))
163+
end
164+
165+
function M.show_editor()
166+
local cfg = config.get()
167+
local km = cfg.keymaps.editor
168+
local entries = {}
169+
170+
table.insert(entries, { key = format_key(cfg.keymaps.execute), label = "Execute query", category = "Actions" })
171+
add_entry(km, "execute_insert", "Execute (insert mode)", "Actions", entries)
172+
add_entry(km, "execute_leader", "Execute (leader)", "Actions", entries)
173+
add_entry(km, "save", "Save query", "Actions", entries)
174+
add_entry(km, "next_tab", "Next tab", "Actions", entries)
175+
add_entry(km, "prev_tab", "Previous tab", "Actions", entries)
176+
add_entry(km, "close_tab", "Close tab", "Actions", entries)
177+
178+
add_entry(km, "to_result", "Go to result", "Navigation", entries)
179+
add_entry(km, "to_sidebar", "Go to sidebar", "Navigation", entries)
180+
181+
table.insert(entries, { key = format_key(cfg.keymaps.close), label = "Close dbab", category = "Global" })
182+
183+
show_float("Editor", group_by_category(entries))
184+
end
185+
186+
function M.show_history()
187+
local cfg = config.get()
188+
local km = cfg.keymaps.history
189+
local entries = {}
190+
191+
add_entry(km, "select", "Open in editor", "Actions", entries)
192+
add_entry(km, "execute", "Re-execute", "Actions", entries)
193+
add_entry(km, "copy", "Copy query", "Actions", entries)
194+
add_entry(km, "delete", "Delete entry", "Actions", entries)
195+
add_entry(km, "clear", "Clear all", "Actions", entries)
196+
197+
add_entry(km, "to_sidebar", "Go to sidebar", "Navigation", entries)
198+
add_entry(km, "to_result", "Go to result", "Navigation", entries)
199+
200+
table.insert(entries, { key = format_key(cfg.keymaps.close), label = "Close dbab", category = "Global" })
201+
202+
show_float("History", group_by_category(entries))
203+
end
204+
205+
function M.show_result()
206+
local cfg = config.get()
207+
local km = cfg.keymaps.result
208+
local entries = {}
209+
210+
add_entry(km, "yank_row", "Yank row as JSON", "Actions", entries)
211+
add_entry(km, "yank_all", "Yank all as JSON", "Actions", entries)
212+
213+
add_entry(km, "to_sidebar", "Go to sidebar", "Navigation", entries)
214+
add_entry(km, "to_editor", "Go to editor", "Navigation", entries)
215+
216+
table.insert(entries, { key = format_key(cfg.keymaps.close), label = "Close dbab", category = "Global" })
217+
218+
show_float("Result", group_by_category(entries))
219+
end
220+
221+
return M

lua/dbab/ui/history.lua

Lines changed: 32 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -274,16 +274,13 @@ local function render_compact(entries, win_width, cfg)
274274
if where_col then
275275
local value_start = #result + 1
276276
result = result .. " " .. where_col
277-
table.insert(
278-
positions,
279-
{
280-
hint = "where",
281-
symbol_start = symbol_start,
282-
symbol_end = symbol_end,
283-
value_start = value_start,
284-
value_end = #result,
285-
}
286-
)
277+
table.insert(positions, {
278+
hint = "where",
279+
symbol_start = symbol_start,
280+
symbol_end = symbol_end,
281+
value_start = value_start,
282+
value_end = #result,
283+
})
287284
else
288285
table.insert(positions, { hint = "where", symbol_start = symbol_start, symbol_end = symbol_end })
289286
end
@@ -299,16 +296,13 @@ local function render_compact(entries, win_width, cfg)
299296
if join_table then
300297
local value_start = #result + 1
301298
result = result .. " " .. join_table
302-
table.insert(
303-
positions,
304-
{
305-
hint = "join",
306-
symbol_start = symbol_start,
307-
symbol_end = symbol_end,
308-
value_start = value_start,
309-
value_end = #result,
310-
}
311-
)
299+
table.insert(positions, {
300+
hint = "join",
301+
symbol_start = symbol_start,
302+
symbol_end = symbol_end,
303+
value_start = value_start,
304+
value_end = #result,
305+
})
312306
else
313307
table.insert(positions, { hint = "join", symbol_start = symbol_start, symbol_end = symbol_end })
314308
end
@@ -327,16 +321,13 @@ local function render_compact(entries, win_width, cfg)
327321
local symbol_end = #result
328322
local value_start = #result + 1
329323
result = result .. " " .. order_col
330-
table.insert(
331-
positions,
332-
{
333-
hint = "order",
334-
symbol_start = symbol_start,
335-
symbol_end = symbol_end,
336-
value_start = value_start,
337-
value_end = #result,
338-
}
339-
)
324+
table.insert(positions, {
325+
hint = "order",
326+
symbol_start = symbol_start,
327+
symbol_end = symbol_end,
328+
value_start = value_start,
329+
value_end = #result,
330+
})
340331
end
341332
end
342333

@@ -352,16 +343,13 @@ local function render_compact(entries, win_width, cfg)
352343
local symbol_end = #result
353344
local value_start = #result + 1
354345
result = result .. " " .. group_col
355-
table.insert(
356-
positions,
357-
{
358-
hint = "group",
359-
symbol_start = symbol_start,
360-
symbol_end = symbol_end,
361-
value_start = value_start,
362-
value_end = #result,
363-
}
364-
)
346+
table.insert(positions, {
347+
hint = "group",
348+
symbol_start = symbol_start,
349+
symbol_end = symbol_end,
350+
value_start = value_start,
351+
value_end = #result,
352+
})
365353
end
366354
end
367355

@@ -935,6 +923,10 @@ function M.setup_keymaps(buf)
935923
vim.api.nvim_set_current_win(workbench.result_win)
936924
end
937925
end, opts)
926+
927+
vim.keymap.set("n", "?", function()
928+
require("dbab.ui.help").show_history()
929+
end, opts)
938930
end
939931

940932
--- Handle entry selection (load or execute based on config)

lua/dbab/ui/keymaps.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ function M.setup_result_keymaps()
4141
vim.keymap.set("n", config.get().keymaps.close, function()
4242
workbench.close()
4343
end, result_opts)
44+
45+
vim.keymap.set("n", "?", function()
46+
require("dbab.ui.help").show_result()
47+
end, result_opts)
4448
end
4549

4650
---@param buf number
@@ -102,6 +106,10 @@ function M.setup_editor_keymaps(buf)
102106
vim.keymap.set("n", config.get().keymaps.close, function()
103107
workbench.close()
104108
end, opts)
109+
110+
vim.keymap.set("n", "?", function()
111+
require("dbab.ui.help").show_editor()
112+
end, opts)
105113
end
106114

107115
function M.setup_keymaps()

lua/dbab/ui/sidebar.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,8 @@ function M.setup_keymaps()
820820
local query = M.insert_table_query()
821821
if query then
822822
workbench.open_editor_with_query(query)
823+
else
824+
vim.notify("[dbab] Select a table or view to insert query", vim.log.levels.WARN)
823825
end
824826
end)
825827

@@ -860,6 +862,8 @@ function M.setup_keymaps()
860862
}
861863
vim.notify("[dbab] Copied: " .. node.name, vim.log.levels.INFO)
862864
end
865+
else
866+
vim.notify("[dbab] Select a saved query to copy", vim.log.levels.WARN)
863867
end
864868
end
865869
end)
@@ -912,6 +916,10 @@ function M.setup_keymaps()
912916
vim.api.nvim_set_current_win(workbench.history_win)
913917
end
914918
end)
919+
920+
map("?", function()
921+
require("dbab.ui.help").show_sidebar()
922+
end)
915923
end
916924

917925
function M.cleanup()

0 commit comments

Comments
 (0)