nvim-cmp
nvim-cmp copied to clipboard
Is it possible to have context-aware sources?
With the context support that was added recently, it is now possible to disable completion in say, comments. Awesome!
I want to have some sources in comments; and some outside. I tried creating a function that checked current context and set sources appropriately; and thought it worked - but this didn’t update on context change while editing:
-- cmp setup lua file
local context = require("cmp.config.context")
local set_sources = function()
local s = {}
if context.in_syntax_group('Comment') or context.in_treesitter_capture('comment') then
s = {
-- comment sources
}
else
s = {
-- other sources
}
end
return s
end
cmp.setup({
-- other setup
sources = set_sources(),
)}
ideally; I’d like to pass a function directly to cmp.setup.sources. Could I hack around this with an InsertEnter autocommand and cmp.setup.buffer maybe?
This would be really nice. I generally do not care about most sources in comments, but some may be relevant.
x-post from https://github.com/hrsh7th/cmp-nvim-lsp/issues/20#issuecomment-1175254858
Take this javascript source:
import { html, render } from 'lit-html';
render(html`
<p>I'm a little teapot</p>
`, document.body);
With the cursor on the line below the <p>
tag, I'd like to receive emmet completions from emmet_ls, but when the cursor is on the line beneath the import
statement, I certainly would not like to receive emmet completions.
I would like the ability to filter lsp snippets by treesitter context.
Could SourceConfig
also take an enabled
predicate?
x-post from hrsh7th/cmp-nvim-lsp#20 (comment)
Take this javascript source:
import { html, render } from 'lit-html'; render(html` <p>I'm a little teapot</p> `, document.body);
With the cursor on the line below the
<p>
tag, I'd like to receive emmet completions from emmet_ls, but when the cursor is on the line beneath theimport
statement, I certainly would not like to receive emmet completions.I would like the ability to filter lsp snippets by treesitter context.
Could
SourceConfig
also take anenabled
predicate?
with #1067 you can do
function(entry, _)
local kinds = require("cmp.types").lsp.CompletionItemKind
local in_capture = require("cmp.config.context").in_treesitter_capture
if kinds[entry:get_kind()] == "Snippet" then
local name = vim.split(entry.source:get_debug_name(), ":")[2]
if name == "emmet_ls" then
return not in_capture "jsx_text"
end
end
end
took sometime but was bothering me as well. This works for jsx/tsx, but I'm sure there would be something you can check to know you are inhtml
With this query in ~/.config/nvim/after/queries/typescript/lit_html.scm
(call_expression
function: ((identifier) @_name
(#eq? @_name "html"))
arguments: ((template_string) @lit_html))
and this filter function:
local JS_CONFIG = {
sources = cmp.config.sources({
{ name = 'nvim_lsp', filter = function(entry, _)
local kinds = require 'cmp.types'.lsp.CompletionItemKind
if (kinds[entry:get_kind()] == 'Snippet'
and entry.source:get_debug_name() == 'nvim_lsp:emmet_ls') then
local parser = vim.treesitter.get_parser(0, 'typescript')
local query = vim.treesitter.query.get_query('typescript', 'lit_html')
local tree = parser:parse()[1]
local row = unpack(vim.api.nvim_win_get_cursor(0))
local caps = {}
for id, node, meta in query:iter_captures(tree:root(), 0, row - 1, row) do
local name = query.captures[id]
table.insert(caps, name)
end
if vim.tbl_contains(caps, 'lit_html') then
return true
end
else
return false
end
end },
{ name = 'nvim_lsp_signature_help' },
}, {
{ name = 'luasnip', option = { use_show_condition = false } },
}, {
{ name = 'treesitter' },
{ name = 'buffer', keyword_length = 3 },
}, {
{ name = 'calc' },
{ name = 'emoji' },
})
}
cmp.setup.filetype('javascript', JS_CONFIG)
cmp.setup.filetype('typescript', JS_CONFIG)
I've achieved my goal