-
Notifications
You must be signed in to change notification settings - Fork 35
feat(config): modern keymap format + mode support #52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(config): modern keymap format + mode support #52
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really great PR.
I only added some small comments about the format and about splitting input_window and output_window keymaps and using editor instead of global (the editor part is just to make it easier to transition). this should really simplify old format detection and keymap applying.
We could support custom function as well so users can plug whatever they want in there :)
I know the format changed a little bit since the last PR.. But I want to be sure we make it right and future-proof and also make it easy to maintain.
But for the rest this is a really great PR and it tackle a really core aspect of the plugin in a elegant way :).
With this last round of fixes it will be ready to merge
Thanks for your effort on this. It's really appreciated
Here is a recap of the updated format that I think we should go with
keymap = {
editor = {
['<leader>og'] = { 'toggle' }, -- I don't think we really need to support just string, it makes things more complex for nothing
['<leader>oi'] = { 'open_input' },
['<leader>oI'] = { 'open_input_new_session' },
['<leader>oo'] = { 'open_output' },
['<leader>ot'] = { 'toggle_focus' },
['<leader>oq'] = { 'close' },
['<leader>os'] = { 'select_session' },
['<leader>op'] = { 'configure_provider' },
['<leader>od'] = { 'diff_open' },
['<leader>o]'] = { 'diff_next' },
['<leader>o['] = { 'diff_prev' },
['<leader>oc'] = { 'diff_close' },
['<leader>ora'] = { 'diff_revert_all_last_prompt' },
['<leader>ort'] = { 'diff_revert_this_last_prompt' },
['<leader>orA'] = { 'diff_revert_all' },
['<leader>orT'] = { 'diff_revert_this' },
['<leader>orr'] = { 'diff_restore_snapshot_file' },
['<leader>orR'] = { 'diff_restore_snapshot_all' },
['<leader>oC'] = { 'open_configuration_file' },
['<leader>ox'] = { 'swap_position' },
['<leader>opa'] = { 'permission_accept' },
['<leader>opA'] = { 'permission_accept_all' },
['<leader>opd'] = { 'permission_deny' },
},
output_window = {
['<leader>something'] = {function ()
-- custom code
end},
['<esc>'] = { 'close' },
['<C-c>'] = { 'stop' },
[']]'] = { 'next_message' },
['[['] = { 'prev_message' },
['<tab>'] = { 'toggle_pane', mode = { 'n', 'i' } },
['<C-i>'] = { 'focus_input' },
['<leader>oS'] = { 'select_child_session' },
['<leader>oD'] = { 'debug_message' },
['<leader>oO'] = { 'debug_output' },
['<leader>ods'] = { 'debug_session' },
},
input_window = {
['<cr>'] = { 'submit_input_prompt', mode = { 'n', 'i' } },
['<esc>'] = { 'close' },
['<C-c>'] = { 'stop' },
['~'] = { 'mention_file', mode = 'i' },
['@'] = { 'mention', mode = 'i' },
['/'] = { 'slash_commands', mode = 'i' },
['<tab>'] = { 'toggle_pane', mode = { 'n', 'i' } },
['<up>'] = { 'prev_prompt_history', mode = { 'n', 'i' } },
['<down>'] = { 'next_prompt_history', mode = { 'n', 'i' } },
['<M-m>'] = { 'switch_mode' },
['<leader>oS'] = { 'select_child_session' },
['<leader>oD'] = { 'debug_message' },
['<leader>oO'] = { 'debug_output' },
['<leader>ods'] = { 'debug_session' },
},
permission = {
accept = 'a',
accept_all = 'A',
deny = 'd',
},
|
Thanks for all of the comments. Totally agree on getting the format right now so it's worth extra effort to get it there. I also had the same thought about the need to support functions in keymaps (I want my submit keymap, , to also exit insert mode). I also wondered if it made sense to split input / output keymaps but wasn't sure... seeing it now, it's definitely much cleaner! I'll take a look at all of the comments later today. |
Support keymaps with custom functions. Deprecate global keymap section in favor of editor. Show global permission keymap if Opencode isn't focused.
|
@sudo-tee Ok, I think I incorporated all of the feedback. Let me know if there's anything else I should change. |
Don't rely on table ordering
|
Oh yeah, a few notes:
|
This is a legacy option you can remove it.
Also legacy stuff I forgot to remove
This one puzzled me. It comes from another PR I merged, they can be removed they are not used.
Also comes from a PR I merged without noticing.. It can be removed also |
You should filter them by using the function name from the new config. so only the relevant keymaps are applied to the window. Now both window receives all the keymaps. you can get the function names with a function like this --- Get function names from keymap config
local function get_function_names(keymap_config)
local names = {}
for _, config in pairs(keymap_config) do
if type(config) == 'table' and config[1] then
table.insert(names, config[1])
end
end
return names
end
local function normalize_keymap(legacy_config, filter_functions)
local converted = {}
for func_name, key in pairs(legacy_config) do
local api_name = func_name == 'submit' and 'submit_input_prompt' or func_name
if not filter_functions or vim.tbl_contains(filter_functions, api_name) then
converted[key] = { api_name }
end
end
return converted
endand apply them like this if opts.keymap.window then
opts.keymap.input_window = normalize_keymap(opts.keymap.window, get_function_names(values.keymap.input_window))
opts.keymap.output_window = normalize_keymap(opts.keymap.window, get_function_names(values.keymap.output_window))
endA part from that I'm ready to merge after this tiny fix. Thanks again :) |
Only apply keymaps that are meant for each window
Also remove olds providers, custom_commands fields
|
Amazing work I fixed a small error I was getting when migrating the old format. I just merged the PR |
This is a complete overhaul of the keymaps,
The old config should still work but with a warning for migration
The new format shoud now be:
```lua
keymap = {
editor = {
['<leader>og'] = { 'toggle' }, -- I don't think we really need to support just string, it makes things more complex for nothing
['<leader>oi'] = { 'open_input' },
['<leader>oI'] = { 'open_input_new_session' },
['<leader>oo'] = { 'open_output' },
['<leader>ot'] = { 'toggle_focus' },
['<leader>oq'] = { 'close' },
['<leader>os'] = { 'select_session' },
['<leader>op'] = { 'configure_provider' },
['<leader>od'] = { 'diff_open' },
['<leader>o]'] = { 'diff_next' },
['<leader>o['] = { 'diff_prev' },
['<leader>oc'] = { 'diff_close' },
['<leader>ora'] = { 'diff_revert_all_last_prompt' },
['<leader>ort'] = { 'diff_revert_this_last_prompt' },
['<leader>orA'] = { 'diff_revert_all' },
['<leader>orT'] = { 'diff_revert_this' },
['<leader>orr'] = { 'diff_restore_snapshot_file' },
['<leader>orR'] = { 'diff_restore_snapshot_all' },
['<leader>oC'] = { 'open_configuration_file' },
['<leader>ox'] = { 'swap_position' },
['<leader>opa'] = { 'permission_accept' },
['<leader>opA'] = { 'permission_accept_all' },
['<leader>opd'] = { 'permission_deny' },
},
output_window = {
['<leader>something'] = {function ()
-- custom code
end},
['<esc>'] = { 'close' },
['<C-c>'] = { 'stop' },
[']]'] = { 'next_message' },
['[['] = { 'prev_message' },
['<tab>'] = { 'toggle_pane', mode = { 'n', 'i' } },
['<C-i>'] = { 'focus_input' },
['<leader>oS'] = { 'select_child_session' },
['<leader>oD'] = { 'debug_message' },
['<leader>oO'] = { 'debug_output' },
['<leader>ods'] = { 'debug_session' },
},
input_window = {
['<cr>'] = { 'submit_input_prompt', mode = { 'n', 'i' } },
['<esc>'] = { 'close' },
['<C-c>'] = { 'stop' },
['~'] = { 'mention_file', mode = 'i' },
['@'] = { 'mention', mode = 'i' },
['/'] = { 'slash_commands', mode = 'i' },
['<tab>'] = { 'toggle_pane', mode = { 'n', 'i' } },
['<up>'] = { 'prev_prompt_history', mode = { 'n', 'i' } },
['<down>'] = { 'next_prompt_history', mode = { 'n', 'i' } },
['<M-m>'] = { 'switch_mode' },
['<leader>oS'] = { 'select_child_session' },
['<leader>oD'] = { 'debug_message' },
['<leader>oO'] = { 'debug_output' },
['<leader>ods'] = { 'debug_session' },
},
permission = {
accept = 'a',
accept_all = 'A',
deny = 'd',
},
```
commit 601cc82 Author: Cameron Ring <cameron@cs.stanford.edu> Date: Thu Oct 9 15:52:47 2025 -0700 fix(config): add config metatable (sudo-tee#59) Fixes sudo-tee#58 Makes config access less error prone and more ergonomic commit ca0ff90 Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 9 09:50:28 2025 -0400 chore: update .luarc.json for better support of emmylua_ls commit a82b08c Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 9 09:49:28 2025 -0400 fix: prefix replacement not working properly commit 9d949e7 Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 9 08:43:57 2025 -0400 feat: add a keymap_prefix to configure the default `<leader>o` commit 8c65d9b Author: Cameron Ring <cameron@cs.stanford.edu> Date: Thu Oct 9 03:29:02 2025 -0700 feat(config)!: modern keymap format + mode support (sudo-tee#52) This is a complete overhaul of the keymaps, The old config should still work but with a warning for migration The new format shoud now be: ```lua keymap = { editor = { ['<leader>og'] = { 'toggle' }, -- I don't think we really need to support just string, it makes things more complex for nothing ['<leader>oi'] = { 'open_input' }, ['<leader>oI'] = { 'open_input_new_session' }, ['<leader>oo'] = { 'open_output' }, ['<leader>ot'] = { 'toggle_focus' }, ['<leader>oq'] = { 'close' }, ['<leader>os'] = { 'select_session' }, ['<leader>op'] = { 'configure_provider' }, ['<leader>od'] = { 'diff_open' }, ['<leader>o]'] = { 'diff_next' }, ['<leader>o['] = { 'diff_prev' }, ['<leader>oc'] = { 'diff_close' }, ['<leader>ora'] = { 'diff_revert_all_last_prompt' }, ['<leader>ort'] = { 'diff_revert_this_last_prompt' }, ['<leader>orA'] = { 'diff_revert_all' }, ['<leader>orT'] = { 'diff_revert_this' }, ['<leader>orr'] = { 'diff_restore_snapshot_file' }, ['<leader>orR'] = { 'diff_restore_snapshot_all' }, ['<leader>oC'] = { 'open_configuration_file' }, ['<leader>ox'] = { 'swap_position' }, ['<leader>opa'] = { 'permission_accept' }, ['<leader>opA'] = { 'permission_accept_all' }, ['<leader>opd'] = { 'permission_deny' }, }, output_window = { ['<leader>something'] = {function () -- custom code end}, ['<esc>'] = { 'close' }, ['<C-c>'] = { 'stop' }, [']]'] = { 'next_message' }, ['[['] = { 'prev_message' }, ['<tab>'] = { 'toggle_pane', mode = { 'n', 'i' } }, ['<C-i>'] = { 'focus_input' }, ['<leader>oS'] = { 'select_child_session' }, ['<leader>oD'] = { 'debug_message' }, ['<leader>oO'] = { 'debug_output' }, ['<leader>ods'] = { 'debug_session' }, }, input_window = { ['<cr>'] = { 'submit_input_prompt', mode = { 'n', 'i' } }, ['<esc>'] = { 'close' }, ['<C-c>'] = { 'stop' }, ['~'] = { 'mention_file', mode = 'i' }, ['@'] = { 'mention', mode = 'i' }, ['/'] = { 'slash_commands', mode = 'i' }, ['<tab>'] = { 'toggle_pane', mode = { 'n', 'i' } }, ['<up>'] = { 'prev_prompt_history', mode = { 'n', 'i' } }, ['<down>'] = { 'next_prompt_history', mode = { 'n', 'i' } }, ['<M-m>'] = { 'switch_mode' }, ['<leader>oS'] = { 'select_child_session' }, ['<leader>oD'] = { 'debug_message' }, ['<leader>oO'] = { 'debug_output' }, ['<leader>ods'] = { 'debug_session' }, }, permission = { accept = 'a', accept_all = 'A', deny = 'd', }, ``` commit fb33ce6 Author: Francis Belanger <francis.belanger@gmail.com> Date: Tue Oct 7 10:22:36 2025 -0400 refactor: simplify keymaps by having a corresponding api function commit fa31457 Author: Francis Belanger <francis.belanger@gmail.com> Date: Tue Oct 7 13:23:32 2025 -0400 feat: restore mentions when navigating history commit 123d62b Author: Francis Belanger <francis.belanger@gmail.com> Date: Tue Oct 7 12:53:11 2025 -0400 fix: permission not displaying for subagents commit 8a54af6 Author: Francis Belanger <francis.belanger@gmail.com> Date: Tue Oct 7 10:41:09 2025 -0400 feat: display edit tool preview when asking for permission commit a17400c Author: Michael <osajehmichael@gmail.com> Date: Tue Oct 7 13:20:10 2025 +0100 fix: use consistent window positioning commands for splits (sudo-tee#50) commit 2357f86 Author: Francis Belanger <francis.belanger@gmail.com> Date: Tue Oct 7 08:06:14 2025 -0400 feat: support arguments for commands after completion commit 13b9e88 Author: Francis Belanger <francis.belanger@gmail.com> Date: Tue Oct 7 07:11:49 2025 -0400 feat: allow arguments passing to user commands commit 4eab392 Author: Francis Belanger <francis.belanger@gmail.com> Date: Fri Oct 3 15:57:45 2025 -0400 chore: remove dead code commit 42490ec Author: Francis Belanger <francis.belanger@gmail.com> Date: Mon Oct 6 07:02:50 2025 -0400 feat: implement basic permissions worflow
commit 7653234 Author: Guillaume BOEHM <github@mail.gboehm.com> Date: Wed Oct 29 10:27:47 2025 +0000 feat: add prompt_guard callback mechanism (sudo-tee#78) This PR adds a plugin option to run a callback before sending promts to the LLM or before opening the opencode window. In my use case I want to be able to exclude some directories of my computer with sensitive information in order to not mistakenly send them to the LLM. I've mostly vibe-coded this and then went back on the code to check what it did, I'm not super well versed in lua so I might have missed things. Implementation details: Add prompt_guard configuration option (function that returns boolean) Check guard before sending prompts (ERROR notification if denied) Check guard before opening buffer first time (WARN notification if denied) Add util.check_prompt_allowed() helper functions Guard has no parameters, users can access vim state directly Proper error handling for guard callback failures Co-authored-by: Guillaume BOEHM <git@mail.gboehm.com> commit 0dc254b Author: Francis Belanger <francis.belanger@gmail.com> Date: Tue Oct 28 12:01:42 2025 -0400 fix(run): context args not passed in run new session commit 6eb7354 Author: Francis Belanger <francis.belanger@gmail.com> Date: Tue Oct 28 11:18:48 2025 -0400 chore(icons): deprecate emoji icons in favor of nerdfonts commit 3dea370 Author: Francis Belanger <francis.belanger@gmail.com> Date: Tue Oct 28 08:49:27 2025 -0400 chore(emmyrc): fix broken .emmyrc.json commit c07f293 Author: Cameron Ring <cameron@cs.stanford.edu> Date: Mon Oct 27 17:32:50 2025 -0700 fix(renderer): render errors after last part commit bebe01c Author: Francis Belanger <francis.belanger@gmail.com> Date: Mon Oct 27 15:56:57 2025 -0400 feat(rendering): incremental rendering (sudo-tee#62) Introduces an incremental rendering that updates only the changed portion(s) of the buffer instead of re-rendering everything on every change. This reduces CPU usages for large sessions. This PR also incorporate a functional test suite in `tests/manual` where you can record a run snapshot tests. This is a major revision of the rendering system. Co-authored-by: Cameron Ring <cameron@cs.stanford.edu> commit 0f2d1e5 Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 23 07:32:58 2025 -0400 feat(blink): enable other completion sources for blink This should fix sudo-tee#65 commit e06f651 Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 23 07:31:11 2025 -0400 fix(cmp): fix file mention closing when typing for nvim_cmp commit 84d9ae0 Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 23 06:32:17 2025 -0400 fix(mentions): letter `a` appended when triggering mentions commit 44d22ba Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 23 06:23:49 2025 -0400 test(toggle): fix tests for api.open commit 826341d Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 23 06:18:09 2025 -0400 fix(toggle): toggle keymap was always triggering insert mode This should fix sudo-tee#77 commit 803eb3e Author: Francis Belanger <francis.belanger@gmail.com> Date: Wed Oct 22 15:53:52 2025 -0400 docs(session_picker): add config for delete session in README commit edba833 Author: Francis Belanger <francis.belanger@gmail.com> Date: Wed Oct 22 15:50:21 2025 -0400 feat(session_picker): add keybind in title commit 357ef3c Author: Cameron Ring <cameron@cs.stanford.edu> Date: Fri Oct 17 18:37:41 2025 -0700 feat(session_picker): Fixes sudo-tee#68 commit fed6941 Author: Francis Belanger <francis.belanger@gmail.com> Date: Mon Oct 20 15:19:21 2025 -0400 fix(completion): completion were broken after last change commit c505554 Author: Francis Belanger <francis.belanger@gmail.com> Date: Mon Oct 20 14:53:50 2025 -0400 fix(focus_input): fix focusing input on window opening commit 4824151 Author: Francis Belanger <francis.belanger@gmail.com> Date: Mon Oct 20 14:37:36 2025 -0400 fix(input_window): properly restore input text when reopening the window commit ca62c0c Author: Francis Belanger <francis.belanger@gmail.com> Date: Mon Oct 20 14:24:17 2025 -0400 fix(bash-tool): properly shown bash command on permission prompt This should fix sudo-tee#74 commit 28d6379 Author: Francis Belanger <francis.belanger@gmail.com> Date: Mon Oct 20 14:08:45 2025 -0400 fix: focusing input window in insert mode The shortcut <C-i> is interpreted as <tab> by terminals I moved it to i. sudo-tee#72 focusing the input_window should restore to the previous position not the char before sudo-tee#64 commit 946af3a Author: Francis Belanger <francis.belanger@gmail.com> Date: Sat Oct 18 15:11:17 2025 -0400 fix(slash_commands): allow slash_commands to be entered in input window This should fix sudo-tee#71 commit abc1e2a Author: Francis Belanger <francis.belanger@gmail.com> Date: Sat Oct 18 11:25:55 2025 -0400 feat(completion): add folder icon kind commit 031bf0a Author: Francis Belanger <francis.belanger@gmail.com> Date: Sat Oct 18 11:12:19 2025 -0400 feat: support for folder mentions commit e99a463 Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 16 16:34:41 2025 -0400 feat(completion): add file search from server api commit 601cc82 Author: Cameron Ring <cameron@cs.stanford.edu> Date: Thu Oct 9 15:52:47 2025 -0700 fix(config): add config metatable (sudo-tee#59) Fixes sudo-tee#58 Makes config access less error prone and more ergonomic commit ca0ff90 Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 9 09:50:28 2025 -0400 chore: update .luarc.json for better support of emmylua_ls commit a82b08c Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 9 09:49:28 2025 -0400 fix: prefix replacement not working properly commit 9d949e7 Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 9 08:43:57 2025 -0400 feat: add a keymap_prefix to configure the default `<leader>o` commit 8c65d9b Author: Cameron Ring <cameron@cs.stanford.edu> Date: Thu Oct 9 03:29:02 2025 -0700 feat(config)!: modern keymap format + mode support (sudo-tee#52) This is a complete overhaul of the keymaps, The old config should still work but with a warning for migration The new format shoud now be: ```lua keymap = { editor = { ['<leader>og'] = { 'toggle' }, -- I don't think we really need to support just string, it makes things more complex for nothing ['<leader>oi'] = { 'open_input' }, ['<leader>oI'] = { 'open_input_new_session' }, ['<leader>oo'] = { 'open_output' }, ['<leader>ot'] = { 'toggle_focus' }, ['<leader>oq'] = { 'close' }, ['<leader>os'] = { 'select_session' }, ['<leader>op'] = { 'configure_provider' }, ['<leader>od'] = { 'diff_open' }, ['<leader>o]'] = { 'diff_next' }, ['<leader>o['] = { 'diff_prev' }, ['<leader>oc'] = { 'diff_close' }, ['<leader>ora'] = { 'diff_revert_all_last_prompt' }, ['<leader>ort'] = { 'diff_revert_this_last_prompt' }, ['<leader>orA'] = { 'diff_revert_all' }, ['<leader>orT'] = { 'diff_revert_this' }, ['<leader>orr'] = { 'diff_restore_snapshot_file' }, ['<leader>orR'] = { 'diff_restore_snapshot_all' }, ['<leader>oC'] = { 'open_configuration_file' }, ['<leader>ox'] = { 'swap_position' }, ['<leader>opa'] = { 'permission_accept' }, ['<leader>opA'] = { 'permission_accept_all' }, ['<leader>opd'] = { 'permission_deny' }, }, output_window = { ['<leader>something'] = {function () -- custom code end}, ['<esc>'] = { 'close' }, ['<C-c>'] = { 'stop' }, [']]'] = { 'next_message' }, ['[['] = { 'prev_message' }, ['<tab>'] = { 'toggle_pane', mode = { 'n', 'i' } }, ['<C-i>'] = { 'focus_input' }, ['<leader>oS'] = { 'select_child_session' }, ['<leader>oD'] = { 'debug_message' }, ['<leader>oO'] = { 'debug_output' }, ['<leader>ods'] = { 'debug_session' }, }, input_window = { ['<cr>'] = { 'submit_input_prompt', mode = { 'n', 'i' } }, ['<esc>'] = { 'close' }, ['<C-c>'] = { 'stop' }, ['~'] = { 'mention_file', mode = 'i' }, ['@'] = { 'mention', mode = 'i' }, ['/'] = { 'slash_commands', mode = 'i' }, ['<tab>'] = { 'toggle_pane', mode = { 'n', 'i' } }, ['<up>'] = { 'prev_prompt_history', mode = { 'n', 'i' } }, ['<down>'] = { 'next_prompt_history', mode = { 'n', 'i' } }, ['<M-m>'] = { 'switch_mode' }, ['<leader>oS'] = { 'select_child_session' }, ['<leader>oD'] = { 'debug_message' }, ['<leader>oO'] = { 'debug_output' }, ['<leader>ods'] = { 'debug_session' }, }, permission = { accept = 'a', accept_all = 'A', deny = 'd', }, ``` commit fb33ce6 Author: Francis Belanger <francis.belanger@gmail.com> Date: Tue Oct 7 10:22:36 2025 -0400 refactor: simplify keymaps by having a corresponding api function commit fa31457 Author: Francis Belanger <francis.belanger@gmail.com> Date: Tue Oct 7 13:23:32 2025 -0400 feat: restore mentions when navigating history

Here's the updated PR to have global and window keymaps be key first.
I went back and forth on it, but I currently have window permissions split out into their own table and have them action first. (but if you want it the other way, I can change it so they're also key first).