aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/snippet.lua
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2024-05-24 19:18:11 +0000
committerJosh Rahm <joshuarahm@gmail.com>2024-05-24 19:18:11 +0000
commitff7ed8f586589d620a806c3758fac4a47a8e7e15 (patch)
tree729bbcb92231538fa61dab6c3d890b025484b7f5 /runtime/lua/vim/snippet.lua
parent376914f419eb08fdf4c1a63a77e1f035898a0f10 (diff)
parent28c04948a1c887a1cc0cb64de79fa32631700466 (diff)
downloadrneovim-ff7ed8f586589d620a806c3758fac4a47a8e7e15.tar.gz
rneovim-ff7ed8f586589d620a806c3758fac4a47a8e7e15.tar.bz2
rneovim-ff7ed8f586589d620a806c3758fac4a47a8e7e15.zip
Merge remote-tracking branch 'upstream/master' into mix_20240309
Diffstat (limited to 'runtime/lua/vim/snippet.lua')
-rw-r--r--runtime/lua/vim/snippet.lua94
1 files changed, 51 insertions, 43 deletions
diff --git a/runtime/lua/vim/snippet.lua b/runtime/lua/vim/snippet.lua
index 5e60efa778..3d8f73f362 100644
--- a/runtime/lua/vim/snippet.lua
+++ b/runtime/lua/vim/snippet.lua
@@ -254,9 +254,10 @@ local function display_choices(tabstop)
assert(tabstop.choices, 'Tabstop has no choices')
local start_col = tabstop:get_range()[2] + 1
- local matches = vim.iter.map(function(choice)
- return { word = choice }
- end, tabstop.choices)
+ local matches = {} --- @type table[]
+ for _, choice in ipairs(tabstop.choices) do
+ matches[#matches + 1] = { word = choice }
+ end
vim.defer_fn(function()
vim.fn.complete(start_col, matches)
@@ -342,7 +343,7 @@ local function setup_autocmds(bufnr)
or cursor_row > snippet_range[3]
or (cursor_row == snippet_range[3] and cursor_col > snippet_range[4])
then
- M.exit()
+ M.stop()
return true
end
@@ -361,7 +362,7 @@ local function setup_autocmds(bufnr)
end
-- The cursor is either not on a tabstop or we reached the end, so exit the session.
- M.exit()
+ M.stop()
return true
end,
})
@@ -377,7 +378,7 @@ local function setup_autocmds(bufnr)
(snippet_range[1] == snippet_range[3] and snippet_range[2] == snippet_range[4])
or snippet_range[3] + 1 > vim.fn.line('$')
then
- M.exit()
+ M.stop()
end
if not M.active() then
@@ -400,7 +401,7 @@ end
--- Refer to https://microsoft.github.io/language-server-protocol/specification/#snippet_syntax
--- for the specification of valid input.
---
---- Tabstops are highlighted with hl-SnippetTabstop.
+--- Tabstops are highlighted with |hl-SnippetTabstop|.
---
--- @param input string
function M.expand(input)
@@ -446,17 +447,22 @@ function M.expand(input)
base_indent = base_indent .. (snippet_lines[#snippet_lines]:match('(^%s*)%S') or '') --- @type string
end
- local lines = vim.iter.map(function(i, line)
+ local shiftwidth = vim.fn.shiftwidth()
+ local curbuf = vim.api.nvim_get_current_buf()
+ local expandtab = vim.bo[curbuf].expandtab
+
+ local lines = {} --- @type string[]
+ for i, line in ipairs(text_to_lines(text)) do
-- Replace tabs by spaces.
- if vim.o.expandtab then
- line = line:gsub('\t', (' '):rep(vim.fn.shiftwidth())) --- @type string
+ if expandtab then
+ line = line:gsub('\t', (' '):rep(shiftwidth)) --- @type string
end
-- Add the base indentation.
if i > 1 then
line = base_indent .. line
end
- return line
- end, ipairs(text_to_lines(text)))
+ lines[#lines + 1] = line
+ end
table.insert(snippet_text, table.concat(lines, '\n'))
end
@@ -526,37 +532,13 @@ end
--- @alias vim.snippet.Direction -1 | 1
---- Returns `true` if there is an active snippet which can be jumped in the given direction.
---- You can use this function to navigate a snippet as follows:
+--- Jumps to the next (or previous) placeholder in the current snippet, if possible.
---
---- ```lua
---- vim.keymap.set({ 'i', 's' }, '<Tab>', function()
---- if vim.snippet.jumpable(1) then
---- return '<cmd>lua vim.snippet.jump(1)<cr>'
---- else
---- return '<Tab>'
---- end
---- end, { expr = true })
---- ```
----
---- @param direction (vim.snippet.Direction) Navigation direction. -1 for previous, 1 for next.
---- @return boolean
-function M.jumpable(direction)
- if not M.active() then
- return false
- end
-
- return M._session:get_dest_index(direction) ~= nil
-end
-
---- Jumps within the active snippet in the given direction.
---- If the jump isn't possible, the function call does nothing.
----
---- You can use this function to navigate a snippet as follows:
+--- For example, map `<Tab>` to jump while a snippet is active:
---
--- ```lua
--- vim.keymap.set({ 'i', 's' }, '<Tab>', function()
---- if vim.snippet.jumpable(1) then
+--- if vim.snippet.active({ direction = 1 }) then
--- return '<cmd>lua vim.snippet.jump(1)<cr>'
--- else
--- return '<Tab>'
@@ -598,15 +580,41 @@ function M.jump(direction)
setup_autocmds(M._session.bufnr)
end
---- Returns `true` if there's an active snippet in the current buffer.
+--- @class vim.snippet.ActiveFilter
+--- @field direction vim.snippet.Direction Navigation direction. -1 for previous, 1 for next.
+
+--- 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.
--- @return boolean
-function M.active()
- return M._session ~= nil and M._session.bufnr == vim.api.nvim_get_current_buf()
+function M.active(filter)
+ local active = M._session ~= nil and M._session.bufnr == vim.api.nvim_get_current_buf()
+
+ local in_direction = true
+ if active and filter and filter.direction then
+ in_direction = M._session:get_dest_index(filter.direction) ~= nil
+ end
+
+ return active and in_direction
end
--- Exits the current snippet.
-function M.exit()
+function M.stop()
if not M.active() then
return
end