Tailwindcss/emmet_ls is breaking vtsls suggestions
Make sure you have done the following
- [x] Updated to the latest version of
blink.cmp - [x] Searched for existing issues and documentation (try
<C-k>on https://cmp.saghen.dev)
Bug Description
hey just started using vtsls, and found that after i place (/{/[ and type anything i would only get snippets from the cmp menu, i have to go to normal and back to insert mode and type to be able to see my other context, i disabled tailwindcss, and it did fix the issue, is there a workaround for this? edit: also emmet_ls
Relevant configuration
-- Run with `nvim -u repro.lua`
--
-- Please update the code below to reproduce your issue and send the updated code, with reproduction
-- steps, in your issue report
--
-- If you get warnings about prebuilt binaries, you may use `fuzzy.implementation = 'lua'`
-- but note this has caveats: https://cmp.saghen.dev/configuration/fuzzy#rust-vs-lua-implementation
vim.env.LAZY_STDPATH = '.repro'
load(vim.fn.system 'curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua')()
---@diagnostic disable-next-line: missing-fields
require('lazy.minit').repro {
spec = {
{
'saghen/blink.cmp',
version = '1.*',
dependencies = {
{
'L3MON4D3/LuaSnip',
version = '2.*',
build = function()
if vim.fn.has 'win32' == 1 or vim.fn.executable 'make' == 0 then
return
end
return 'make install_jsregexp'
end,
dependencies = {
'rafamadriz/friendly-snippets',
},
},
},
opts = {
keymap = {
preset = 'none',
['<C-space>'] = { 'show', 'show_documentation', 'hide_documentation' },
['<C-e>'] = { 'hide', 'fallback' },
['<C-y>'] = { 'accept', 'fallback' },
['<Tab>'] = { 'snippet_forward', 'fallback' },
['<S-Tab>'] = { 'snippet_backward', 'fallback' },
['<Up>'] = { 'select_prev', 'fallback' },
['<Down>'] = { 'select_next', 'fallback' },
['<C-p>'] = { 'select_prev', 'fallback_to_mappings' },
['<C-n>'] = { 'select_next', 'fallback_to_mappings' },
['<C-b>'] = { 'scroll_documentation_up', 'fallback' },
['<C-f>'] = { 'scroll_documentation_down', 'fallback' },
['<C-k>'] = { 'show_signature', 'hide_signature', 'fallback' },
},
appearance = {
nerd_font_variant = 'mono',
},
completion = {
menu = {
draw = {
treesitter = { 'lsp' },
columns = {
{ 'label', gap = 2 },
{ 'kind_icon', gap = 1, 'kind' },
},
},
},
documentation = {
auto_show = true,
auto_show_delay_ms = 200,
window = {
max_width = math.floor(vim.o.columns * 0.4),
max_height = math.floor(vim.o.lines * 0.5),
},
},
accept = {
auto_brackets = {
enabled = false,
},
},
},
signature = { enabled = true },
snippets = { preset = 'luasnip' },
sources = {
default = { 'lsp', 'path', 'snippets', 'buffer' },
},
fuzzy = { implementation = 'prefer_rust_with_warning' },
},
},
{
'neovim/nvim-lspconfig',
dependencies = {
'j-hui/fidget.nvim',
},
config = function()
-- LSP Attach autocmd with your keymaps
vim.api.nvim_create_autocmd('LspAttach', {
group = vim.api.nvim_create_augroup('lsp-attach', { clear = true }),
callback = function(event)
local map = function(keys, func, desc, mode)
mode = mode or 'n'
vim.keymap.set(mode, keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc })
end
map('<leader>rn', vim.lsp.buf.rename, '[R]e[n]ame')
map('<leader>d', vim.diagnostic.open_float, 'Show Line Diagnostic')
map('[d', function()
vim.diagnostic.jump { count = -1, float = true }
end, 'Previous Diagnostic')
map(']d', function()
vim.diagnostic.jump { count = 1, float = true }
end, 'Next Diagnostic')
map('K', vim.lsp.buf.hover, 'Show hover')
map('<leader>ca', vim.lsp.buf.code_action, '[C]ode [A]ction', { 'n', 'x' })
end,
})
-- Diagnostic config
vim.diagnostic.config {
severity_sort = true,
float = { border = 'rounded', source = 'if_many' },
underline = { severity = vim.diagnostic.severity.ERROR },
virtual_text = false,
}
-- Setup lua_ls with your config
require('lspconfig').lua_ls.setup {
settings = {
Lua = {
completion = {
callSnippet = 'Replace',
},
},
},
}
end,
},
{
'mason-org/mason.nvim',
build = ':MasonUpdate',
opts = {
ui = {
icons = {
package_installed = '✓',
package_pending = '➜',
package_uninstalled = '✗',
},
},
},
},
{
'mason-org/mason-lspconfig.nvim',
dependencies = { 'mason-org/mason.nvim', 'neovim/nvim-lspconfig' },
opts = {
ensure_installed = { 'lua_ls', 'emmet_language_server', 'tailwindcss', 'vtsls' },
},
},
},
}
neovim version
0.11.4
blink.cmp version
1.*
Please provide a repro. Or at least some materials like repro steps, video or code source to see what's going on.
Please provide a repro. Or at least some materials like repro steps, video or code source to see what's going on.
sorry i didnt see that you asked for repro, just updated my post with it
any updates on this ?
Actually could you share a video and the source file as an example so I can try to reproduce the issue? I'm not sure I understand the problem :smile:, thanks!
Actually could you share a video and the source file as an example so I can try to reproduce the issue? I'm not sure I understand the problem :smile:, thanks!
Using the config above, create a .ts file, then inside create a variable lets say const test = 'testing'; then in a new line Open parenthesis, or any symbol will do it, and try to type part of the variable 'te', you wont get any suggestions, if you try this with no symbol at the start it does give you correct suggestions, also i have noticed that signatures are not appearing too
It's likely due to vtsls returning no results on ( and then we don't query the language server again afterwards (while nvim-cmp for example will query again on the next char). This issue only seems to affect javascript-related LSPs (vtsls, vue, svelte, ...). We should probably change the default behavior just to close a bunch of these bugs, but in v2, I'd like to make this a per-LSP setting since the spec makes no mention of this afaict.
When using tailwindcss+vtsls, we merge the trigger chars from both LSPs:
{
client = "tailwindcss",
trigger_chars = { '"', "'", "`", " ", ".", "(", "[", "]", "!", "/", "-", ":" }
}
{
client = "vtsls",
trigger_chars = { ".", '"', "'", "`", "/", "@", "<", "#", " ", "*" }
}
That's why we request completion on ( or [ for vtsls using this combo although not explicitly specified by vstls itself. And it explains why it works as single use.
I'm not sure how to tackle this, not the best solution, but a logical workaround would be:
diff --git a/lua/blink/cmp/sources/lsp/cache.lua b/lua/blink/cmp/sources/lsp/cache.lua
index 839d99b..e09dc6b 100644
--- a/lua/blink/cmp/sources/lsp/cache.lua
+++ b/lua/blink/cmp/sources/lsp/cache.lua
@@ -12,7 +12,7 @@ function cache.get(context, client)
local entry = cache.entries[client.id]
if entry == nil then return end
- if context.id ~= entry.context.id then return end
+ if context.id ~= entry.context.id or context.line ~= entry.context.line then return end
if entry.response.is_incomplete_forward and entry.context.cursor[2] ~= context.cursor[2] then return end
if not entry.response.is_incomplete_forward and entry.context.cursor[2] > context.cursor[2] then return end
It's likely due to vtsls returning no results on
(and then we don't query the language server again afterwards (while nvim-cmp for example will query again on the next char). This issue only seems to affect javascript-related LSPs (vtsls, vue, svelte, ...). We should probably change the default behavior just to close a bunch of these bugs, but in v2, I'd like to make this a per-LSP setting since the spec makes no mention of this afaict.
why does it work fine when i use typescript-tools ? is there a diference ?