Skip to content

Commit 8953ee6

Browse files
sefluehamidi-dev
authored andcommitted
feat: make goto and fold keymaps configurable
Goto closes the agenda and opens the file at the headline position in the previous window, like default org-agenda. - Add configurable goto keymap (default: gf) to open file in previous window - Add fold_or_action keymap (default: Tab) with configurable fold_item_action (default: 'preview', also supports 'goto') - Make edit keymap configurable (default: CR) - Guard goto against popup_mode (no previous window available) - Extract goto_headline() as reusable function for both keymaps - Update help menu (g?) and vimdoc with new config keys
1 parent 5c99e1a commit 8953ee6

5 files changed

Lines changed: 146 additions & 32 deletions

File tree

doc/org-super-agenda.txt

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,12 @@ Press the keymap defined for a TODO state to filter by it and
2323
`oa` to reset the filter. Use `cs` to reschedule, `cd` to set a
2424
deadline, `t` to cycle TODO state, `s` to set state directly,
2525
and `r` to refresh the agenda from disk. Press `K` to preview
26-
the current headline and `q` to close the preview. Press <Tab> on
27-
a group header to toggle collapse/expand.
26+
the current headline and `q` to close the preview. Press `<CR>`
27+
to edit a headline in the float, `gf` to go to the selected headline —
28+
closes the agenda and opens the file at the headline position in the
29+
previous window. Press <Tab> on a group header
30+
to toggle collapse/expand; on an item line it runs `fold_item_action`
31+
(default: preview).
2832

2933
```
3034
Additional useful keys:
@@ -205,7 +209,17 @@ Group headers show item counts in this format:
205209
Use `<Tab>` on a group header to collapse/expand that group.
206210
Use `zM` to fold all groups and `zR` to unfold all groups.
207211

208-
When cursor is on a normal item line, `<Tab>` behaves like preview (`K`).
212+
When cursor is on a normal item line, `<Tab>` runs the action configured
213+
via `fold_item_action`:
214+
215+
'preview' Show item in preview popup (default)
216+
'goto' Close agenda and open file at headline in previous
217+
window
218+
219+
`gf` always goes to the headline in the previous window, regardless
220+
of `fold_item_action`. To match org-agenda `<Tab>` behavior, set
221+
`fold_item_action = 'goto'`.
222+
Note: `goto` is not available in |org-super-agenda-popup| mode.
209223

210224
==============================================================================
211225
FILTERS & QUERY *org-super-agenda-query*
@@ -418,6 +432,9 @@ M.defaults = {
418432
toggle_duplicates = 'D',
419433
cycle_view = 'ov',
420434
open_view = 'V',
435+
['goto'] = 'gf',
436+
fold_or_action = '<Tab>',
437+
edit = '<CR>',
421438
},
422439

423440
todo_states = {
@@ -498,6 +515,7 @@ M.defaults = {
498515
show_filename = true,
499516
heading_max_length = 70,
500517
persist_hidden = false,
518+
fold_item_action = 'preview', -- 'preview' or 'goto'
501519
view_mode = 'classic',
502520
classic = { heading_order = { 'filename', 'todo', 'priority', 'headline' }, short_date_labels = false, inline_dates = true },
503521
compact = { filename_min_width = 10, label_min_width = 12 },

lua/org-super-agenda/adapters/neovim/actions.lua

Lines changed: 77 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -807,26 +807,73 @@ function A.set_keymaps(buf, win, line_map, reopen)
807807
vim.keymap.set('n', k, wipe, { buffer = buf, silent = true })
808808
end
809809

810-
-- open file
811-
vim.keymap.set('n', '<CR>', function()
810+
-- edit file in floating window (configurable keymap, default Enter)
811+
if cfg.keymaps.edit and cfg.keymaps.edit ~= '' then
812+
vim.keymap.set('n', cfg.keymaps.edit, function()
813+
with_headline(line_map, function(cur, hl)
814+
local agendabuf = vim.api.nvim_get_current_buf()
815+
vim.cmd('edit ' .. vim.fn.fnameescape(hl.file.filename))
816+
vim.api.nvim_win_set_cursor(0, { hl.position.start_line, 0 })
817+
local filebuf = vim.api.nvim_get_current_buf()
818+
pcall(vim.api.nvim_buf_delete, agendabuf, { force = true })
819+
820+
-- Add q/Esc keymaps to file buffer for consistent close behavior
821+
local function close_file()
822+
if vim.api.nvim_buf_is_valid(filebuf) then
823+
pcall(vim.api.nvim_buf_delete, filebuf, { force = false })
824+
end
825+
end
826+
for _, k in ipairs({ 'q', '<Esc>' }) do
827+
vim.keymap.set('n', k, close_file, { buffer = filebuf, silent = true })
828+
end
829+
830+
vim.api.nvim_create_autocmd('BufWinLeave', {
831+
buffer = filebuf,
832+
once = true,
833+
callback = function()
834+
vim.schedule(function()
835+
pcall(vim.api.nvim_buf_delete, filebuf, { force = true })
836+
reopen(cur)
837+
end)
838+
end,
839+
})
840+
end)
841+
end, { buffer = buf, silent = true })
842+
end
843+
844+
-- goto: close float and open file in previous window
845+
local function goto_headline()
846+
local popup = cfg.popup_mode
847+
if popup and popup.enabled then
848+
vim.notify('goto not available in popup mode', vim.log.levels.WARN)
849+
return
850+
end
851+
812852
with_headline(line_map, function(cur, hl)
813-
local agendabuf = vim.api.nvim_get_current_buf()
853+
local ViewPort = require('org-super-agenda.adapters.neovim.view_float')
854+
local prev_win = ViewPort.prev_win()
855+
856+
-- Close the floating window
857+
if vim.api.nvim_win_is_valid(win) then
858+
pcall(vim.api.nvim_win_close, win, true)
859+
end
860+
if vim.api.nvim_buf_is_valid(buf) then
861+
pcall(vim.api.nvim_buf_delete, buf, { force = true })
862+
end
863+
require('org-super-agenda').on_close()
864+
865+
-- Switch to previous window and open file
866+
if prev_win and vim.api.nvim_win_is_valid(prev_win) then
867+
vim.api.nvim_set_current_win(prev_win)
868+
end
814869
vim.cmd('edit ' .. vim.fn.fnameescape(hl.file.filename))
815870
vim.api.nvim_win_set_cursor(0, { hl.position.start_line, 0 })
816-
local filebuf = vim.api.nvim_get_current_buf()
817-
pcall(vim.api.nvim_buf_delete, agendabuf, { force = true })
818-
vim.api.nvim_create_autocmd('BufWinLeave', {
819-
buffer = filebuf,
820-
once = true,
821-
callback = function()
822-
vim.schedule(function()
823-
pcall(vim.api.nvim_buf_delete, filebuf, { force = true })
824-
reopen(cur)
825-
end)
826-
end,
827-
})
828871
end)
829-
end, { buffer = buf, silent = true })
872+
end
873+
874+
if cfg.keymaps['goto'] and cfg.keymaps['goto'] ~= '' then
875+
vim.keymap.set('n', cfg.keymaps['goto'], goto_headline, { buffer = buf, silent = true })
876+
end
830877

831878
-- reschedule / deadline (unchanged but undo-aware)
832879
vim.keymap.set('n', cfg.keymaps.reschedule, function()
@@ -1097,12 +1144,21 @@ function A.set_keymaps(buf, win, line_map, reopen)
10971144
end, { buffer = buf, silent = true })
10981145
end
10991146

1100-
-- <Tab>: toggle group fold on group header, otherwise preview item
1101-
vim.keymap.set('n', '<Tab>', function()
1102-
if not toggle_group_on_cursor(line_map) then
1147+
-- fold + fallback: toggle group fold on group header, otherwise run fold_item_action
1148+
local fold_actions = {
1149+
['goto'] = goto_headline,
1150+
preview = function()
11031151
preview_headline(line_map)
1104-
end
1105-
end, { buffer = buf, silent = true })
1152+
end,
1153+
}
1154+
if cfg.keymaps.fold_or_action and cfg.keymaps.fold_or_action ~= '' then
1155+
vim.keymap.set('n', cfg.keymaps.fold_or_action, function()
1156+
if not toggle_group_on_cursor(line_map) then
1157+
local action = fold_actions[cfg.fold_item_action] or fold_actions['preview']
1158+
action()
1159+
end
1160+
end, { buffer = buf, silent = true })
1161+
end
11061162

11071163
if cfg.keymaps.fold_all and cfg.keymaps.fold_all ~= '' then
11081164
vim.keymap.set('n', cfg.keymaps.fold_all, function()

lua/org-super-agenda/adapters/neovim/utils.lua

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,12 @@ function U.show_help()
6565
end
6666

6767
vim.list_extend(lines, {
68+
'Navigation:',
69+
fmt(km.edit, 'Edit headline (float)'),
70+
fmt(km['goto'], 'Goto headline (prev window)'),
71+
fmt(km.fold_or_action, 'Fold group / ' .. (cfg.fold_item_action or 'preview') .. ' item'),
72+
'',
6873
'Misc:',
69-
fmt('<CR>', 'Open headline'),
70-
fmt('<Tab>', 'Toggle fold on group header'),
7174
fmt(km.reload, 'Reload agenda'),
7275
fmt(km.clock_in, 'Clock in'),
7376
fmt(km.clock_out, 'Clock out'),

lua/org-super-agenda/adapters/neovim/view_float.lua

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
local hi = require('org-super-agenda.adapters.neovim.highlight')
33
local get_cfg = require('org-super-agenda.config').get
44

5-
local V = { _buf = nil, _win = nil, _line_map = {}, _ns = vim.api.nvim_create_namespace('OrgSuperAgenda') }
5+
local V = { _buf = nil, _win = nil, _prev_win = nil, _line_map = {}, _ns = vim.api.nvim_create_namespace('OrgSuperAgenda') }
66

77
local function active_clock_status()
88
local ok, org = pcall(require, 'orgmode')
@@ -27,6 +27,9 @@ end
2727
function V.line_map()
2828
return V._line_map
2929
end
30+
function V.prev_win()
31+
return V._prev_win
32+
end
3033

3134
local function add_hl(buf, row, col_start, col_end, entry)
3235
if entry.field == 'mark' then
@@ -173,6 +176,8 @@ function V.render(producer, cursor, _mode, opts)
173176
vim.api.nvim_win_set_buf(win, buf)
174177
vim.api.nvim_set_current_win(win)
175178
else
179+
-- Store current window before creating floating window (for Tab keymap)
180+
V._prev_win = vim.api.nvim_get_current_win()
176181
win = vim.api.nvim_open_win(buf, true, {
177182
relative = 'editor',
178183
style = 'minimal',

lua/org-super-agenda/config.lua

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,40 @@ M.defaults = {
4141
bulk_reselect = 'gv',
4242
bulk_action = 'B',
4343
open_view = 'V',
44+
['goto'] = 'gf',
45+
fold_or_action = '<Tab>',
46+
edit = '<CR>',
4447
},
4548

4649
todo_states = {
47-
{ name = 'TODO', keymap = 'ot', color = '#FF5555', strike_through = false, fields = { 'filename', 'todo', 'headline', 'priority', 'date', 'tags' } },
48-
{ name = 'PROGRESS', keymap = 'op', color = '#FFAA00', strike_through = false, fields = { 'filename', 'todo', 'headline', 'priority', 'date', 'tags' } },
49-
{ name = 'WAITING', keymap = 'ow', color = '#BD93F9', strike_through = false, fields = { 'filename', 'todo', 'headline', 'priority', 'date', 'tags' } },
50-
{ name = 'DONE', keymap = 'od', color = '#50FA7B', strike_through = true, fields = { 'filename', 'todo', 'headline', 'priority', 'date', 'tags' } },
50+
{
51+
name = 'TODO',
52+
keymap = 'ot',
53+
color = '#FF5555',
54+
strike_through = false,
55+
fields = { 'filename', 'todo', 'headline', 'priority', 'date', 'tags' },
56+
},
57+
{
58+
name = 'PROGRESS',
59+
keymap = 'op',
60+
color = '#FFAA00',
61+
strike_through = false,
62+
fields = { 'filename', 'todo', 'headline', 'priority', 'date', 'tags' },
63+
},
64+
{
65+
name = 'WAITING',
66+
keymap = 'ow',
67+
color = '#BD93F9',
68+
strike_through = false,
69+
fields = { 'filename', 'todo', 'headline', 'priority', 'date', 'tags' },
70+
},
71+
{
72+
name = 'DONE',
73+
keymap = 'od',
74+
color = '#50FA7B',
75+
strike_through = true,
76+
fields = { 'filename', 'todo', 'headline', 'priority', 'date', 'tags' },
77+
},
5178
},
5279

5380
-- You can add per-group { sort = { by='deadline'|'scheduled'|'priority'|'todo'|'filename'|'headline'|'date_nearest', order='asc'|'desc' } }
@@ -135,8 +162,13 @@ M.defaults = {
135162
show_filename = true,
136163
heading_max_length = 70,
137164
persist_hidden = false,
165+
fold_item_action = 'preview',
138166
view_mode = 'classic',
139-
classic = { heading_order = { 'filename', 'todo', 'priority', 'headline' }, short_date_labels = false, inline_dates = true },
167+
classic = {
168+
heading_order = { 'filename', 'todo', 'priority', 'headline' },
169+
short_date_labels = false,
170+
inline_dates = true,
171+
},
140172
compact = { filename_min_width = 10, label_min_width = 12 },
141173

142174
-- Global fallback sort for groups that don't specify their own `sort`

0 commit comments

Comments
 (0)