aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/snippet.lua
diff options
context:
space:
mode:
authorMathias Fußenegger <mfussenegger@users.noreply.github.com>2025-03-14 09:51:52 +0100
committerGitHub <noreply@github.com>2025-03-14 09:51:52 +0100
commit123f8d229eef05869ee4c98dfd4934c22a03b1f6 (patch)
tree8d61078fb3ffd635e3926d3c17d8eeea94b27b2b /runtime/lua/vim/snippet.lua
parent6401b433f7c040663b1ae01204e1b07b567d6a1b (diff)
downloadrneovim-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.lua75
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)