diff --git a/README.md b/README.md index 4b6020f..f49fbd8 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,10 @@

## Features -- **Composable Mappings**: get rid of boilerplate code in your config -- **Treesitter Integration**: show snippets based on the filetype at your cursor position -- **Regular Expression Snippets**: snippets with the `r` option are supported +- **Composable mappings**: get rid of boilerplate code in your config +- **Treesitter integration**: show snippets based on the filetype at your cursor position +- **Regular expression snippets**: snippets with the `r` option are supported +- **Custom context snippets**: snippets are only shown in the correct context - **Customization**: change which and how snippets are displayed by cmp ## Dependencies @@ -134,17 +135,14 @@ are handled entirely by UltiSnips. If set to `"expandable"`, only those snippets currently expandable by UltiSnips will be shown. The snippets will always be in sync with the currently available UltiSnips snippets. -`"all"` will show all snippets for the current filetype. If using this option, be aware -that all snippets for the current buffer will be cached (even if the snippet definitions -changed). You can then manually reload the snippets with the command `:CmpUltisnipsReloadSnippets` -or by using an autocommand: +`"all"` will show all snippets for the current filetype except regex and custom context snippets. +This is due to caching of all snippets for the current buffer. They will not update even if the snippet definitions changed +- you can then manually reload the snippets with the command `:CmpUltisnipsReloadSnippets` or by using an autocommand: ```vim autocmd BufWritePost *.snippets :CmpUltisnipsReloadSnippets ``` -Custom context snippets (option `e`) are currently not available. - **Default:** `"expandable"` --- diff --git a/autoload/cmp_nvim_ultisnips.vim b/autoload/cmp_nvim_ultisnips.vim index fdcbdb1..b94f270 100644 --- a/autoload/cmp_nvim_ultisnips.vim +++ b/autoload/cmp_nvim_ultisnips.vim @@ -5,27 +5,38 @@ " per snippet) with the keys "trigger", "description", "options" and "value". " " If 'expandable_only' is "True", only expandable snippets are returned, otherwise all -" snippets for the current filetype are returned. +" snippets except regex and custom context snippets for the current filetype are returned. function! cmp_nvim_ultisnips#get_current_snippets(expandable_only) let g:_cmpu_current_snippets = [] python3 << EOF import vim from UltiSnips import UltiSnips_Manager, vim_helper -if vim.eval("a:expandable_only") == "True": - before = vim_helper.buf.line_till_cursor +before = vim_helper.buf.line_till_cursor +visual_content = UltiSnips_Manager._visual_content +expandable_only = vim.eval("a:expandable_only") == "True" +if expandable_only: snippets = UltiSnips_Manager._snips(before, True) else: snippets = UltiSnips_Manager._snips("", True) for snippet in snippets: + is_context_snippet = snippet._context_code != None + is_regex_snippet = "r" in snippet._opts + # If show_snippets == "all", the snippets are cached so ignore "dynamic" snippets. + if not expandable_only and (is_context_snippet or is_regex_snippet): + continue + # For custom context snippets, always check if the context matches. + if is_context_snippet and not snippet._context_match(visual_content, before): + continue + vim.command( "call add(g:_cmpu_current_snippets, {" - "'trigger': py3eval('str(snippet._trigger)')," - "'description': py3eval('str(snippet._description)')," - "'options': py3eval('str(snippet._opts)')," - "'value': py3eval('str(snippet._value)')," - "'matched': py3eval('str(snippet._matched)')," + "'trigger': py3eval('snippet._trigger')," + "'description': py3eval('snippet._description')," + "'options': py3eval('snippet._opts')," + "'value': py3eval('snippet._value')," + "'matched': py3eval('snippet._matched')," "})" ) EOF diff --git a/lua/cmp_nvim_ultisnips/source.lua b/lua/cmp_nvim_ultisnips/source.lua index ae5404e..26918ab 100644 --- a/lua/cmp_nvim_ultisnips/source.lua +++ b/lua/cmp_nvim_ultisnips/source.lua @@ -27,25 +27,19 @@ function source.complete(self, _, callback) local snippets = cmpu_snippets.load_snippets(self.expandable_only) for _, snippet in pairs(snippets) do - -- Skip expression snippets for now - if not snippet.options:match("e") then - local is_regex_snippet = snippet.options:match("r") - -- Avoid expanding a regex snippet with an invalid insertText when self.expandable_only == false - -- (_cmpu_line_till_cursor is only set when self.expandable_only == true) - if not is_regex_snippet or is_regex_snippet and self.expandable_only then - local item = { - insertText = (is_regex_snippet and snippet.matched) or snippet.trigger, - label = snippet.trigger, - kind = cmp.lsp.CompletionItemKind.Snippet, - snippet = snippet, - } - table.insert(items, item) - end - end + local is_regex_snippet = snippet.options:match("r") + local item = { + insertText = (is_regex_snippet and snippet.matched) or snippet.trigger, + label = snippet.trigger, + kind = cmp.lsp.CompletionItemKind.Snippet, + snippet = snippet, + } + table.insert(items, item) end callback { items = items, - -- Cmp will update the items on every keystroke + -- If true, cmp will update the items on every keystroke. + -- When self.expandable_only == false, the snippets are cached so no need to update. isIncomplete = self.expandable_only, } end