diff options
author | Viktor Kojouharov <developer@sugr.org> | 2020-05-28 14:31:56 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-28 08:31:56 -0400 |
commit | 5a9226c800d3075821203952da7c38626180680d (patch) | |
tree | 6d36d84f9c16561d12de8fd7aafcce23a72a294f /runtime/lua/vim/lsp/util.lua | |
parent | 2ca8f02a6461fd4710c4ecc555fbe7ee9f75a70a (diff) | |
download | rneovim-5a9226c800d3075821203952da7c38626180680d.tar.gz rneovim-5a9226c800d3075821203952da7c38626180680d.tar.bz2 rneovim-5a9226c800d3075821203952da7c38626180680d.zip |
lua: simple snippet support in the completion items (#12118)
Old behavior is: foo(${placeholder: bar, ...)
with lots of random garbage you'd never want inserted.
New behavior is: foo(bar, baz)
(which maybe is good, maybe is bad [depends on user], but definitely better than it was).
-----
* Implement rudimentary snippet parsing
Add support for parsing and discarding snippet tokens from the completion items.
Fixes #11982
* Enable snippet support
* Functional tests for snippet parsing
Add simplified real-world snippet text examples to the completion items
test
* Add a test for nested snippet tokens
* Remove TODO comment
* Return the unmodified item if the format is plain text
* Add a plain text completion item
Diffstat (limited to 'runtime/lua/vim/lsp/util.lua')
-rw-r--r-- | runtime/lua/vim/lsp/util.lua | 72 |
1 files changed, 70 insertions, 2 deletions
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index b6eaae1fef..752d4ff439 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -199,6 +199,66 @@ function M.get_current_line_to_cursor() return line:sub(pos[2]+1) end +local function parse_snippet_rec(input, inner) + local res = "" + + local close, closeend = nil, nil + if inner then + close, closeend = input:find("}", 1, true) + while close ~= nil and input:sub(close-1,close-1) == "\\" do + close, closeend = input:find("}", closeend+1, true) + end + end + + local didx = input:find('$', 1, true) + if didx == nil and close == nil then + return input, "" + elseif close ~=nil and (didx == nil or close < didx) then + -- No inner placeholders + return input:sub(0, close-1), input:sub(closeend+1) + end + + res = res .. input:sub(0, didx-1) + input = input:sub(didx+1) + + local tabstop, tabstopend = input:find('^%d+') + local placeholder, placeholderend = input:find('^{%d+:') + local choice, choiceend = input:find('^{%d+|') + + if tabstop then + input = input:sub(tabstopend+1) + elseif choice then + input = input:sub(choiceend+1) + close, closeend = input:find("|}", 1, true) + + res = res .. input:sub(0, close-1) + input = input:sub(closeend+1) + elseif placeholder then + -- TODO: add support for variables + input = input:sub(placeholderend+1) + + -- placeholders and variables are recursive + while input ~= "" do + local r, tail = parse_snippet_rec(input, true) + r = r:gsub("\\}", "}") + + res = res .. r + input = tail + end + else + res = res .. "$" + end + + return res, input +end + +-- Parse completion entries, consuming snippet tokens +function M.parse_snippet(input) + local res, _ = parse_snippet_rec(input, false) + + return res +end + -- Sort by CompletionItem.sortText -- https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion local function sort_completion_items(items) @@ -213,9 +273,17 @@ end -- https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion local function get_completion_word(item) if item.textEdit ~= nil and item.textEdit.newText ~= nil then - return item.textEdit.newText + if protocol.InsertTextFormat[item.insertTextFormat] == "PlainText" then + return item.textEdit.newText + else + return M.parse_snippet(item.textEdit.newText) + end elseif item.insertText ~= nil then - return item.insertText + if protocol.InsertTextFormat[item.insertTextFormat] == "PlainText" then + return item.insertText + else + return M.parse_snippet(item.insertText) + end end return item.label end |