diff options
author | Mathias Fußenegger <mfussenegger@users.noreply.github.com> | 2025-03-14 09:51:52 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-03-14 09:51:52 +0100 |
commit | 123f8d229eef05869ee4c98dfd4934c22a03b1f6 (patch) | |
tree | 8d61078fb3ffd635e3926d3c17d8eeea94b27b2b /runtime/lua/vim/snippet.lua | |
parent | 6401b433f7c040663b1ae01204e1b07b567d6a1b (diff) | |
download | rneovim-123f8d229eef05869ee4c98dfd4934c22a03b1f6.tar.gz rneovim-123f8d229eef05869ee4c98dfd4934c22a03b1f6.tar.bz2 rneovim-123f8d229eef05869ee4c98dfd4934c22a03b1f6.zip |
feat(snippet): set snippet keymaps permanent instead of dynamic (#31887)
Problem:
Given that `vim.snippet.expand()` sets temporary `<tab>`/`<s-tab>`
keymaps there is no way to build "smart-tab" functionality where `<tab>`
chooses the next completion candidate if the popup menu is visible.
Solution:
Set the keymap permanent in `_defaults`.
The downside of this approach is that users of multiple snippet engine's
need to adapt their keymaps to handle all their engines that are in use.
For example:
vim.keymap.set({ 'i', 's' }, "<Tab>", function()
if foreign_snippet.active() then
return "<Cmd>lua require('foreign_snippet').jump()<CR>"
elseif vim.snippet.active({ direction = 1 }) then
return "<Cmd>lua vim.snippet.jump(1)<CR>"
else
return key
end
end, { expr = true })
Upside is that using `vim.keymap.set` to override keymaps is a well
established pattern and `vim.snippet.expand` calls made by nvim itself
or plugins have working keymaps out of the box.
Co-authored-by: Maria José Solano <majosolano99@gmail.com>
Diffstat (limited to 'runtime/lua/vim/snippet.lua')
-rw-r--r-- | runtime/lua/vim/snippet.lua | 75 |
1 files changed, 2 insertions, 73 deletions
diff --git a/runtime/lua/vim/snippet.lua b/runtime/lua/vim/snippet.lua index bfd439181e..2edea6d5ad 100644 --- a/runtime/lua/vim/snippet.lua +++ b/runtime/lua/vim/snippet.lua @@ -2,8 +2,6 @@ local G = vim.lsp._snippet_grammar local snippet_group = vim.api.nvim_create_augroup('nvim.snippet', {}) local snippet_ns = vim.api.nvim_create_namespace('nvim.snippet') local hl_group = 'SnippetTabstop' -local jump_forward_key = '<tab>' -local jump_backward_key = '<s-tab>' --- Returns the 0-based cursor position. --- @@ -213,64 +211,9 @@ function Session.new(bufnr, snippet_extmark, tabstop_data) end end - self:set_keymaps() - return self end ---- Sets the snippet navigation keymaps. ---- ---- @package -function Session:set_keymaps() - local function maparg(key, mode) - local map = vim.fn.maparg(key, mode, false, true) --[[ @as table ]] - if not vim.tbl_isempty(map) and map.buffer == 1 then - return map - else - return nil - end - end - - local function set(jump_key, direction) - vim.keymap.set({ 'i', 's' }, jump_key, function() - return vim.snippet.active({ direction = direction }) - and '<cmd>lua vim.snippet.jump(' .. direction .. ')<cr>' - or jump_key - end, { expr = true, silent = true, buffer = self.bufnr }) - end - - self.tab_keymaps = { - i = maparg(jump_forward_key, 'i'), - s = maparg(jump_forward_key, 's'), - } - self.shift_tab_keymaps = { - i = maparg(jump_backward_key, 'i'), - s = maparg(jump_backward_key, 's'), - } - set(jump_forward_key, 1) - set(jump_backward_key, -1) -end - ---- Restores/deletes the keymaps used for snippet navigation. ---- ---- @package -function Session:restore_keymaps() - local function restore(keymap, lhs, mode) - if keymap then - vim._with({ buf = self.bufnr }, function() - vim.fn.mapset(keymap) - end) - else - vim.api.nvim_buf_del_keymap(self.bufnr, mode, lhs) - end - end - - restore(self.tab_keymaps.i, jump_forward_key, 'i') - restore(self.tab_keymaps.s, jump_forward_key, 's') - restore(self.shift_tab_keymaps.i, jump_backward_key, 'i') - restore(self.shift_tab_keymaps.s, jump_backward_key, 's') -end - --- Returns the destination tabstop index when jumping in the given direction. --- --- @package @@ -604,7 +547,7 @@ end --- Jumps to the next (or previous) placeholder in the current snippet, if possible. --- ---- For example, map `<Tab>` to jump while a snippet is active: +--- By default `<Tab>` is setup to jump if a snippet is active. The default mapping looks like: --- --- ```lua --- vim.keymap.set({ 'i', 's' }, '<Tab>', function() @@ -613,7 +556,7 @@ end --- else --- return '<Tab>' --- end ---- end, { expr = true }) +--- end, { descr = '...', expr = true, silent = true }) --- ``` --- --- @param direction (vim.snippet.Direction) Navigation direction. -1 for previous, 1 for next. @@ -656,18 +599,6 @@ end --- Returns `true` if there's an active snippet in the current buffer, --- applying the given filter if provided. --- ---- You can use this function to navigate a snippet as follows: ---- ---- ```lua ---- vim.keymap.set({ 'i', 's' }, '<Tab>', function() ---- if vim.snippet.active({ direction = 1 }) then ---- return '<Cmd>lua vim.snippet.jump(1)<CR>' ---- else ---- return '<Tab>' ---- end ---- end, { expr = true }) ---- ``` ---- --- @param filter? vim.snippet.ActiveFilter Filter to constrain the search with: --- - `direction` (vim.snippet.Direction): Navigation direction. Will return `true` if the snippet --- can be jumped in the given direction. @@ -689,8 +620,6 @@ function M.stop() return end - M._session:restore_keymaps() - vim.api.nvim_clear_autocmds({ group = snippet_group, buffer = M._session.bufnr }) vim.api.nvim_buf_clear_namespace(M._session.bufnr, snippet_ns, 0, -1) |