Skip to content

Commit b773577

Browse files
committed
Adopt neovim builtin snippet parse code
Add comment of adoption of neovim snippet code
1 parent f0d7bcd commit b773577

1 file changed

Lines changed: 64 additions & 0 deletions

File tree

lua/cmp/utils/snippet.lua

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ P.seq = function(...)
176176
end
177177

178178
local Node = {}
179+
Node.__index = Node
179180

180181
Node.Type = {
181182
SNIPPET = 0,
@@ -188,6 +189,18 @@ Node.Type = {
188189
TEXT = 7,
189190
}
190191

192+
--@see https://github.com/neovim/neovim/blob/9afa1fd35510c5fe485f4a1dfdabf94e5f051a1c/runtime/lua/vim/snippet.lua#L59
193+
194+
--- Transforms the given text into an array of lines (so no line contains `\n`).
195+
---
196+
--- @param text string|string[]
197+
--- @return string[]
198+
local function text_to_lines(text)
199+
text = type(text) == 'string' and { text } or text
200+
--- @cast text string[]
201+
return vim.split(table.concat(text), '\n', { plain = true })
202+
end
203+
191204
function Node:__tostring()
192205
local insert_text = {}
193206
if self.type == Node.Type.SNIPPET then
@@ -206,6 +219,57 @@ function Node:__tostring()
206219
return table.concat(insert_text, '')
207220
end
208221

222+
--@see https://github.com/neovim/neovim/blob/9afa1fd35510c5fe485f4a1dfdabf94e5f051a1c/runtime/lua/vim/snippet.lua#L477
223+
function Node:to_static_text()
224+
local snippet_text = {}
225+
local base_indent = vim.api.nvim_get_current_line():match('^%s*') or ''
226+
227+
--- Appends the given text to the snippet, taking care of indentation.
228+
---
229+
--- @param text string|string[]
230+
local function append_to_snippet(text)
231+
local snippet_lines = text_to_lines(snippet_text)
232+
-- Get the base indentation based on the current line and the last line of the snippet.
233+
if #snippet_lines > 0 then
234+
base_indent = base_indent .. (snippet_lines[#snippet_lines]:match('(^%s*)%S') or '') --- @type string
235+
end
236+
237+
local shiftwidth = vim.fn.shiftwidth()
238+
local curbuf = vim.api.nvim_get_current_buf()
239+
local expandtab = vim.bo[curbuf].expandtab
240+
241+
local lines = {} --- @type string[]
242+
for i, line in ipairs(text_to_lines(text)) do
243+
-- Replace tabs by spaces.
244+
if expandtab then
245+
line = line:gsub('\t', (' '):rep(shiftwidth)) --- @type string
246+
end
247+
-- Add the base indentation.
248+
if i > 1 then
249+
line = base_indent .. line
250+
end
251+
lines[#lines + 1] = line
252+
end
253+
254+
table.insert(snippet_text, table.concat(lines, '\n'))
255+
end
256+
257+
for _, c in ipairs(self.children) do
258+
if c.type == Node.Type.PLACEHOLDER then
259+
for _, ic in ipairs(c.children or {}) do
260+
if ic.type == Node.Type.TEXT then
261+
append_to_snippet(ic.esc)
262+
end
263+
end
264+
elseif c.type == Node.Type.TEXT then
265+
append_to_snippet(c.esc)
266+
end
267+
end
268+
269+
snippet_text = text_to_lines(snippet_text)
270+
return snippet_text
271+
end
272+
209273
--@see https://code.visualstudio.com/docs/editor/userdefinedsnippets#_grammar
210274

211275
local S = {}

0 commit comments

Comments
 (0)