Duplicate snippets with Luasnip preset
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
After commit https://github.com/Saghen/blink.cmp/commit/c4eafc1f87380da04eb8b9c5b52395c48edd102e, when you have Luasnip enabled in your personal configuration and you also set snippets.preset = "luasnip", you get duplicate snippets. Reverting to the previous commit does correctly show snippets only one time.
After https://github.com/Saghen/blink.cmp/commit/c4eafc1f87380da04eb8b9c5b52395c48edd102e screenshot
Before https://github.com/Saghen/blink.cmp/commit/c4eafc1f87380da04eb8b9c5b52395c48edd102e screenshot
Somehow the prefetch on insert gets duplicate items for Luasnip snippets.
Relevant configuration
snippets = {
preset = "luasnip",
},
neovim version
NVIM v0.11.0-dev-1633+g851137f679
blink.cmp version
main
I have a similar case, but I noticed that the duplication occurs only when using the new syntax preset = "luasnip":
return {
"saghen/blink.cmp",
lazy = false,
dependencies = {
"L3MON4D3/LuaSnip",
version = "v2.*",
dependencies = { "rafamadriz/friendly-snippets" },
config = function()
--- I had to add this option compared to the old syntax
require("luasnip.loaders.from_vscode").lazy_load()
end,
},
version = "v0.11.0",
opts = {
snippets = {
preset = "luasnip",
},
.....
With the previous syntax this does not happen.
return {
"saghen/blink.cmp",
lazy = false,
dependencies = {
"L3MON4D3/LuaSnip",
version = "v2.*",
dependencies = { "rafamadriz/friendly-snippets" },
},
version = "v0.11.0",
opts = {
snippets = {
expand = function(snippet)
require("luasnip").lsp_expand(snippet)
end,
active = function(filter)
if filter and filter.direction then
return require("luasnip").jumpable(filter.direction)
end
return require("luasnip").in_snippet()
end,
jump = function(direction)
require("luasnip").jump(direction)
end,
},
...
Seems to be introduced in https://github.com/Saghen/blink.cmp/commit/712af9f50bbba4313b6247dedd5a1333391127df
Thanks @ruslanSorokin
I have not yet identified under what conditions but there seems to be edge cases where duplicates are still produced.
It happened to me twice today that at some point, duplicates would start showing up until I restart Nvim.
@Saghen, I confirm as per my last comment that duplicates are still common.
I can notice that happening several times per day if I restart Nvim each time to clear.
Sadly, I have no idea how to even approach a repro case. I have been very mindful as to when the duplication could happen, even tried to force it, but I have absolutely no idea under which conditions it does. I cannot just roll with a minimal config for hours since I would not be able to do anything. It has been a month already, it is unlikely I will be able to collect more intel.
What do you recommend? Should we reopen this issue and hope to collect more feedback beyond my case?
I couldn't even get snippets to work with the luasnip shorthand config
Echoing @helins - duplicate snippets still appear.
Have yet to find the cause of the issue.
I have some observations which may help, but not sure if I do all correct:
- I use Luasnip with
snippets= { preset = "luasnip" } - Even so this workaround is for luasnip, I see duplicates also for the default snippet engine (but I have not looked into this)
- We are in:
blink.cmp/lua/blink/cmp/sources/snippets/luasnip.lua - Precisely in
get_completions, collecting initemsour completion items - It seems that the
require('luasnip.util.util').get_snippet_filetypes()returns all file types, also the "artificial" oneall(its added "last" as the impl ofget_snippet_filetypes()states :)) - And later in the loop
require('luasnip').get_snippets(ft, { type = 'snippets' })returns the snippets for the givenft - And now comes the clue: Apparently the result for the real/concrete filetype already contains the global snippets, so all from
all - Which in essence then means, that the global snippets
allare added twice
Here is a patch which shows this: https://github.com/mputz86/blink.cmp/commit/622f64dc9f6188f9b86b765c1fb95ab91f120f56
I am not that familiar with the code yet, but at least this seems like a breadcrumb :). So let me know if that may be a/the cause and this needs some follow up :)!
For those of you who still experience this issue, could you give the mentioned PR a try? I haven’t been able to reproduce it since then, so I'm calling for testers. 🙏
I personally can't repro even without the mentioned PR any more. Don't know when it stopped being a problem, since I use Neovim native snippets engine by default. I only tested on Lua and Python that I'm familiar with.
This is the minimal repro I used for testing
-- Bootstrap lazy.nvim
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
local lazyrepo = "https://github.com/dpetka2001/lazy.nvim.git"
local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
if vim.v.shell_error ~= 0 then
vim.api.nvim_echo({
{ "Failed to clone lazy.nvim:\n", "ErrorMsg" },
{ out, "WarningMsg" },
{ "\nPress any key to exit..." },
}, true, {})
vim.fn.getchar()
os.exit(1)
end
end
vim.opt.rtp:prepend(lazypath)
-- Make sure to setup `mapleader` and `maplocalleader` before
-- loading lazy.nvim so that mappings are correct.
-- This is also a good place to setup other settings (vim.opt)
vim.g.mapleader = " "
vim.g.maplocalleader = "\\"
-- Setup lazy.nvim
require("lazy").setup({
spec = {
{
"mason-org/mason-lspconfig.nvim",
event = "BufReadPre",
opts = {
ensure_installed = { "lua_ls", "basedpyright" },
},
dependencies = {
{ "mason-org/mason.nvim", opts = {} },
"neovim/nvim-lspconfig",
},
},
{
"saghen/blink.cmp",
dependencies = { "rafamadriz/friendly-snippets" },
version = "*",
event = { "InsertEnter", "CmdlineEnter" },
opts_extend = {
"sources.completion.enabled_providers",
"sources.compat",
"sources.default",
},
opts = {
snippets = {
preset = "luasnip",
},
sources = {
default = { "lsp", "path", "snippets", "buffer" },
},
},
},
{
"L3MON4D3/LuaSnip",
build = "make install_jsregexp",
dependencies = {
{
"rafamadriz/friendly-snippets",
config = function()
require("luasnip.loaders.from_vscode").lazy_load()
end,
},
},
opts = {
history = true,
delete_check_events = "TextChanged",
},
},
},
})
Tested with latest stable version 1.7.0 at the moment. Best to wait for a bit to see if other ppl respond, otherwise for me I've no problem considering this issue solved some way or another.
I had an issue with duplicate snippets, and while setting up repro.lua for this branch, I discovered that the problem was caused by the friendly-snippets collection. If you’ve been experiencing duplicate snippets specifically in html or markdown files, feel free to check out this repro with the fix:
-- Bootstrap lazy.nvim
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
local lazyrepo = "https://github.com/dpetka2001/lazy.nvim.git"
local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
if vim.v.shell_error ~= 0 then
vim.api.nvim_echo({
{ "Failed to clone lazy.nvim:\n", "ErrorMsg" },
{ out, "WarningMsg" },
{ "\nPress any key to exit..." },
}, true, {})
vim.fn.getchar()
os.exit(1)
end
end
vim.opt.rtp:prepend(lazypath)
-- Make sure to setup `mapleader` and `maplocalleader` before
-- loading lazy.nvim so that mappings are correct.
-- This is also a good place to setup other settings (vim.opt)
vim.g.mapleader = " "
vim.g.maplocalleader = "\\"
local frienly_snippets = {
-- "rafamadriz/friendly-snippets",
"ruslanSorokin/friendly-snippets",
branch = "fix/do-not-include-global-into-md-and-html",
}
-- Setup lazy.nvim
require("lazy").setup({
spec = {
{
"mason-org/mason-lspconfig.nvim",
event = "BufReadPre",
opts = { ensure_installed = {} },
dependencies = {
{ "mason-org/mason.nvim", opts = {} },
},
},
{
"saghen/blink.cmp",
dependencies = { frienly_snippets },
version = "*",
event = { "InsertEnter", "CmdlineEnter" },
opts_extend = {
"sources.completion.enabled_providers",
"sources.compat",
"sources.default",
},
opts = {
snippets = {
preset = "luasnip",
},
sources = {
default = { "lsp", "path", "snippets", "buffer" },
},
},
},
{
"L3MON4D3/LuaSnip",
build = "make install_jsregexp",
dependencies = {
{
-- "rafamadriz/friendly-snippets",
"friendly-snippets",
config = function()
require("luasnip.loaders.from_vscode").lazy_load()
end,
},
},
opts = {
history = true,
delete_check_events = "TextChanged",
},
},
},
})