Skip to content

Commit 2fc871b

Browse files
committed
implement interface for applying snippetTextEdits.
1 parent 22b7c11 commit 2fc871b

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

lua/luasnip/extras/lsp.lua

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
local luasnip_ns_id = require("luasnip.session").ns_id
2+
local ls = require("luasnip")
3+
4+
local M = {}
5+
6+
---Apply text/snippetTextEdits (at most one snippetText though).
7+
---@param snippet_or_text_edits `(snippetTextEdit|textEdit)[]`
8+
--- snippetTextEdit as defined in https://github.com/rust-lang/rust-analyzer/blob/master/docs/dev/lsp-extensions.md#snippet-textedit)
9+
---@param bufnr number, buffer where the snippet should be expanded.
10+
---@param offset_encoding string|nil, 'utf-8,16,32' or ni
11+
---@param apply_text_edits_fn function, has to apply regular textEdits, most
12+
--- likely `vim.lsp.util.apply_text_edits` (we expect its' interface).
13+
function M.apply_text_edits(snippet_or_text_edits, bufnr, offset_encoding, apply_text_edits_fn)
14+
-- plain textEdits, applied using via `apply_text_edits_fn`.
15+
local text_edits = {}
16+
-- contains keys
17+
-- - snippet (parsed snippet)
18+
-- - mark (extmark, textrange replaced by the snippet)
19+
local snippet_params
20+
21+
for _, v in ipairs(snippet_or_text_edits) do
22+
if v.newText and v.insertTextFormat == 2 then
23+
assert(snippet_params == nil, "Only one snippetTextEdit may be applied at once.")
24+
25+
-- from vim.lsp.apply_text_edits.
26+
local start_row = v.range.start.line
27+
local start_col = vim.lsp.util._get_line_byte_from_position(bufnr, v.range.start, offset_encoding)
28+
local end_row = v.range['end'].line
29+
local end_col = vim.lsp.util._get_line_byte_from_position(bufnr, v.range['end'], offset_encoding)
30+
31+
snippet_params = {
32+
snippet_body = v.newText,
33+
mark = vim.api.nvim_buf_set_extmark(bufnr, luasnip_ns_id, start_row, start_col, {
34+
end_row = end_row,
35+
end_col = end_col
36+
}),
37+
}
38+
else
39+
table.insert(text_edits, v)
40+
end
41+
end
42+
43+
-- first apply regular textEdits...
44+
apply_text_edits_fn(text_edits, bufnr, offset_encoding)
45+
46+
-- ...then the snippet.
47+
local mark_info = vim.api.nvim_buf_get_extmark_by_id(bufnr, luasnip_ns_id, snippet_params.mark, {details = true})
48+
local mark_begin_pos = {mark_info[1], mark_info[2]}
49+
local mark_end_pos = {mark_info[3].end_row, mark_info[3].end_col}
50+
51+
-- luasnip can only expand snippets in the active buffer, so switch (nop if
52+
-- buf already active).
53+
vim.api.nvim_set_current_buf(bufnr)
54+
ls.lsp_expand(snippet_params.snippet_body, {
55+
pos = mark_begin_pos,
56+
clear_region = {
57+
from = mark_begin_pos,
58+
to = mark_end_pos,
59+
},
60+
})
61+
end
62+
63+
return M

0 commit comments

Comments
 (0)