Skip to content

Snippet, Buffer Sources Not Being Loaded #132

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Drew-Daniels opened this issue Oct 18, 2024 · 6 comments
Closed

Snippet, Buffer Sources Not Being Loaded #132

Drew-Daniels opened this issue Oct 18, 2024 · 6 comments

Comments

@Drew-Daniels
Copy link

Drew-Daniels commented Oct 18, 2024

⚠️ EDIT: I've made some clarifications after diving into this more below, but my problem doesn't appear to be so much related to custom snippets displaying for completion but rather snippet and buffer sources appearing to not be usable as sources at all.

Original:

Thanks for making this plugin. Seems like a speedier alternative to the previous nvim-cmp and luasnip setup I was using for awhile.

Issue

This plugin worked out of the box, and I only ran into snags after trying to port my luasnip snippets over to the VSCode format so I can use them with blink.cmp.

But it looks like my local snippets aren't getting loaded, and when I try to adjust my configuration so that they are, I lose all the out-of-the-box functionality. I guess I'm not sure what the configuration needs to look like for this to happen for both friendly-snippets and custom snippets to work together.

Context

I think my confusion stems from a couple things:

1. sources.providers configuration confusion

It looks like the default sources.providers configuration is completely overridden if we pass anything to sources.providers

Maybe this is intentional (or it works differently), but it seems like a difficult way for users to configure things, especially when it's not super clear to me in the docs what these defaults are.

Here's what I see when my config looks like this:

require("blink-cmp").setup({
  keymap = {
    scroll_documentation_up = "<C-u>",
    scroll_documentation_down = "<C-d>",
    select_next = "<C-n>",
    select_prev = "<C-p>",
    accept = "<C-e>",
    show = "<C-space>",
    hide = "<C-space>",
    show_documentation = "<C-k>",
    hide_documentation = "<C-k>",
    snippet_forward = "<C-j>",
    snippet_backward = "<C-h>",
  },
  nerd_font_variant = "mono",
  highlight = {
    use_nvim_cmp_as_default = true,
  },
  -- no provider.sources configuration
})
Test_filter(data)

... But as soon as I configure anything in providers.sources, I lose all of those completions, and my custom snippets don't appear either:

require("blink-cmp").setup({
  keymap = {
    scroll_documentation_up = "<C-u>",
    scroll_documentation_down = "<C-d>",
    select_next = "<C-n>",
    select_prev = "<C-p>",
    accept = "<C-e>",
    show = "<C-space>",
    hide = "<C-space>",
    show_documentation = "<C-k>",
    hide_documentation = "<C-k>",
    snippet_forward = "<C-j>",
    snippet_backward = "<C-h>",
  },
  nerd_font_variant = "mono",
  highlight = {
    use_nvim_cmp_as_default = true,
  },
  -- TODO: Need to figure out why custom snippets aren't being sourced
  sources = {
    providers = {
      { "blink.cmp.sources.snippets", name = "Snippets", score_offset = -3 },
    },
  },
})
show_docunentation = C-k,

2. Unsure how to configure custom snippets in addition to other snippet sources, like friendly-snippets

Even when I have a provider like the following, and I specify the path to where my snippets are, they aren't being displayed as options for completion. Other snippets are - but not my custom ones:

require("blink-cmp").setup({
  keymap = {
    scroll_documentation_up = "<C-u>",
    scroll_documentation_down = "<C-d>",
    select_next = "<C-n>",
    select_prev = "<C-p>",
    accept = "<C-e>",
    show = "<C-space>",
    hide = "<C-space>",
    show_documentation = "<C-k>",
    hide_documentation = "<C-k>",
    snippet_forward = "<C-j>",
    snippet_backward = "<C-h>",
  },
  nerd_font_variant = "mono",
  highlight = {
    use_nvim_cmp_as_default = true,
  },
  sources = {
    providers = {
      { "blink.cmp.sources.lsp", name = "LSP" },
      { "blink.cmp.sources.path", name = "Path", score_offset = 3 },
      { "blink.cmp.sources.snippets", name = "Snippets", score_offset = -3, opts = { search_paths = {vim.fn.stdpath("config") .. "/snippets" } } },
      { "blink.cmp.sources.buffer", name = "Buffer", fallback_for = { "LSP" } },
    },
  },
})
Test_filter(data)

Abbr nvim/plugins/init.lua:

return require("lazy").setup({
  {
    "chrisgrieser/nvim-scissors",
    dependencies = { "nvim-telescope/telescope.nvim", "garymjr/nvim-snippets" },
  },
  {
    "saghen/blink.cmp",
    lazy = false, -- lazy loading handled internally
    -- optional: provides snippets for the snippet source
    dependencies = "rafamadriz/friendly-snippets",
    -- use a release tag to download pre-built binaries
    version = "v0.*",
    -- OR build from source, requires nightly: https://rust-lang.github.io/rustup/concepts/channels.html#working-with-nightly-rust
    -- build = 'cargo build --release',
    -- On musl libc based systems you need to add this flag
    -- build = 'RUSTFLAGS="-C target-feature=-crt-static" cargo build --release',
  },
})

uname -a:

Darwin drews-m1-mbp 23.6.0 Darwin Kernel Version 23.6.0: Mon Jul 29 21:14:30 PDT 2024; root:xnu-10063.141.2~1/RELEASE_ARM64_T6000 arm64

nvim --version:

❯ nvim --version
NVIM v0.10.2
Build type: Release
LuaJIT 2.1.1727870382
Run "nvim -V1 -v" for more info

nvim/snippets/lua.json:

  • This is the snippet I am trying to have show up listed in my completions, but no luck yet:
{
  "TODO": {
    "body": "-- TODO: ${1:TODO}",
    "prefix": "td"
  }
}
@Drew-Daniels
Copy link
Author

I've been doing some more investigation into this and it looks like a couple things are happening on my end:

  1. Snippets (friendly-snippets for now, gave up on trying to get custom snippets loaded for now) do not appear to be getting loaded as completion sources
  2. Buffer completions also appear to not be usable either

lazy.nvim configuration

return require("lazy").setup({
  {
    "saghen/blink.cmp",
    lazy = false, -- lazy loading handled internally
    -- optional: provides snippets for the snippet source
    dependencies = "rafamadriz/friendly-snippets",
    -- use a release tag to download pre-built binaries
    version = "v0.*",
    -- OR build from source, requires nightly: https://rust-lang.github.io/rustup/concepts/channels.html#working-with-nightly-rust
    -- build = 'cargo build --release',
    -- On musl libc based systems you need to add this flag
    -- build = 'RUSTFLAGS="-C target-feature=-crt-static" cargo build --release',
  },
})

LSP Completions

LSP completions work fine without any issues, when I rely on the sources defaults, or when set sources.providers as I do here:

require("blink-cmp").setup({
  keymap = {
    scroll_documentation_up = "<C-u>",
    scroll_documentation_down = "<C-d>",
    select_next = "<C-n>",
    select_prev = "<C-p>",
    accept = "<C-e>",
    show = "<C-space>",
    hide = "<C-space>",
    show_documentation = "<C-k>",
    hide_documentation = "<C-k>",
    snippet_forward = "<C-j>",
    snippet_backward = "<C-h>",
  },
  nerd_font_variant = "mono",
  highlight = {
    use_nvim_cmp_as_default = true,
  },
  -- TODO: Need to figure out why custom snippets aren't being sourced
  sources = {
    providers = {
      { "blink.cmp.sources.lsp", name = "LSP" },
      -- { "blink.cmp.sources.path", name = "Path", score_offset = 3 },
      -- { "blink.cmp.sources.snippets", name = "Snippets", score_offset = -3 },
      -- { "blink.cmp.sources.buffer", name = "Buffer", fallback_for = { "LSP" } },
    },
  },
})
clang-format,

Path Completions

require("blink-cmp").setup({
  keymap = {
    scroll_documentation_up = "<C-u>",
    scroll_documentation_down = "<C-d>",
    select_next = "<C-n>",
    select_prev = "<C-p>",
    accept = "<C-e>",
    show = "<C-space>",
    hide = "<C-space>",
    show_documentation = "<C-k>",
    hide_documentation = "<C-k>",
    snippet_forward = "<C-j>",
    snippet_backward = "<C-h>",
  },
  nerd_font_variant = "mono",
  highlight = {
    use_nvim_cmp_as_default = true,
  },
  -- TODO: Need to figure out why custom snippets aren't being sourced
  sources = {
    providers = {
      -- { "blink.cmp.sources.lsp", name = "LSP" },
      { "blink.cmp.sources.path", name = "Path", score_offset = 3 },
      -- { "blink.cmp.sources.snippets", name = "Snippets", score_offset = -3 },
      -- { "blink.cmp.sources.buffer", name = "Buffer", fallback_for = { "LSP" } },
    },
  },
})
image

Snippet Completions

I have listed friendly-snippets as a blink.cmp dependency, but am not seeing any of them suggested as a type triggers of snippets like the one for print, which has a trigger of p:

image
require("blink-cmp").setup({
  keymap = {
    scroll_documentation_up = "<C-u>",
    scroll_documentation_down = "<C-d>",
    select_next = "<C-n>",
    select_prev = "<C-p>",
    accept = "<C-e>",
    show = "<C-space>",
    hide = "<C-space>",
    show_documentation = "<C-k>",
    hide_documentation = "<C-k>",
    snippet_forward = "<C-j>",
    snippet_backward = "<C-h>",
  },
  nerd_font_variant = "mono",
  highlight = {
    use_nvim_cmp_as_default = true,
  },
  -- TODO: Need to figure out why custom snippets aren't being sourced
  sources = {
    providers = {
      -- { "blink.cmp.sources.lsp", name = "LSP" },
      -- { "blink.cmp.sources.path", name = "Path", score_offset = 3 },
      { "blink.cmp.sources.snippets", name = "Snippets", score_offset = -3 },
      -- { "blink.cmp.sources.buffer", name = "Buffer", fallback_for = { "LSP" } },
    },
  },
})
image

Buffer Completions

As a type words that I know have been used in the buffer I am editing, I do not see them suggested, like print in the example below:

require("blink-cmp").setup({
  keymap = {
    scroll_documentation_up = "<C-u>",
    scroll_documentation_down = "<C-d>",
    select_next = "<C-n>",
    select_prev = "<C-p>",
    accept = "<C-e>",
    show = "<C-space>",
    hide = "<C-space>",
    show_documentation = "<C-k>",
    hide_documentation = "<C-k>",
    snippet_forward = "<C-j>",
    snippet_backward = "<C-h>",
  },
  nerd_font_variant = "mono",
  highlight = {
    use_nvim_cmp_as_default = true,
  },
  -- TODO: Need to figure out why custom snippets aren't being sourced
  sources = {
    providers = {
      -- { "blink.cmp.sources.lsp", name = "LSP" },
      -- { "blink.cmp.sources.path", name = "Path", score_offset = 3 },
      -- { "blink.cmp.sources.snippets", name = "Snippets", score_offset = -3 },
      { "blink.cmp.sources.buffer", name = "Buffer", fallback_for = { "LSP" } },
    },
  },
})
image

@Drew-Daniels Drew-Daniels changed the title Custom Snippets Not Being Loaded Snippet, Buffer Sources Not Being Loaded Oct 18, 2024
@Saghen
Copy link
Owner

Saghen commented Oct 18, 2024

Buffer source isn't showing because you have fallback_for = { "LSP" } but no source named LSP for it to fallback for. The snippets I'm not sure and I'm not able to reproduce it. If you have the chance, you could debug the register_snippets function here

function scan.register_snippets(search_paths)
local registry = {}
for _, path in ipairs(search_paths) do
local files = scan.load_package_json(path) or scan.scan_for_snippets(path)
for ft, file in pairs(files) do
local key
if type(ft) == 'number' then
key = vim.fn.fnamemodify(files[ft], ':t:r')
else
key = ft
end
if not key then return end
registry[key] = registry[key] or {}
if type(file) == 'table' then
vim.list_extend(registry[key], file)
else
table.insert(registry[key], file)
end
end
end
return registry
end

@Saghen
Copy link
Owner

Saghen commented Oct 18, 2024

It looks like the default sources.providers configuration is completely overridden if we pass anything to sources.providers

Maybe this is intentional (or it works differently), but it seems like a difficult way for users to configure things, especially when it's not super clear to me in the docs what these defaults are.

The defaults can be found in the README or in config.lua. Overriding the entire list when merging is standard behavior when configuring in neovim but I agree it's confusing. Just not sure what a good alternative would be

@Drew-Daniels
Copy link
Author

Buffer source isn't showing because you have fallback_for = { "LSP" } but no source named LSP for it to fallback for. The snippets I'm not sure and I'm not able to reproduce it. If you have the chance, you could debug the register_snippets function here

function scan.register_snippets(search_paths)
local registry = {}
for _, path in ipairs(search_paths) do
local files = scan.load_package_json(path) or scan.scan_for_snippets(path)
for ft, file in pairs(files) do
local key
if type(ft) == 'number' then
key = vim.fn.fnamemodify(files[ft], ':t:r')
else
key = ft
end
if not key then return end
registry[key] = registry[key] or {}
if type(file) == 'table' then
vim.list_extend(registry[key], file)
else
table.insert(registry[key], file)
end
end
end
return registry
end

Oh, that makes sense. Thanks for pointing that out. I can confirm that removing fallback_for = { 'LSP' } fixed it.

I'll try to take a look at the register_snippets function later today

@Drew-Daniels
Copy link
Author

It looks like the default sources.providers configuration is completely overridden if we pass anything to sources.providers

Maybe this is intentional (or it works differently), but it seems like a difficult way for users to configure things, especially when it's not super clear to me in the docs what these defaults are.

The defaults can be found in the README or in config.lua. Overriding the entire list when merging is standard behavior when configuring in neovim but I agree it's confusing. Just not sure what a good alternative would be

I see, thanks for confirming how that works. I think I was mostly confused because of how the defaults are shown in the README - since there are two providers keys listed. Might be obvious to others that the second is the full default config, but I wasn't sure if the configurations in the first providers key were using the same score_offsets, opts, etc. as the second one.

image

@Drew-Daniels
Copy link
Author

Drew-Daniels commented Oct 18, 2024

Ok, figured out what the issue was finally.

When I was working on migrating from luasnip and nvim-cmp to blink.cmp, I had created a bunch of empty <language>.json files in my nvim/snippets directory (all.json, ruby.json etc.) and my package.json looked something like this (I've abbreviated it here):

{
  "name": "my-snippets",
  "contributes": {
    "snippets": [
      {
        "language": "all",
        "path": "./all.json" // empty
      },
      {
        "language": "lua",
        "path": "./lua.json"
      },

      {
        "language": "ruby", 
        "path": "./ruby.json" // empty
      }
    ]
  }
}

nvim/snippets/lua.json:

{
  "TODO": {
    "body": "-- TODO: ${1:TODO}",
    "prefix": "td"
  }
}

Once I removed all language entries for all the languages that mapped to empty .json snippet files in my package.json, and removed all those blank .json files from nvim/snippets, I saw both friendly-snippets and custom snippets displayed as completion sources the next time I opened neovim:

image
image

I'm wondering if there should be some validation done by blink.cmp to alert users if have invalid snippet files, or add error handling that skips over these files, but either way I think my problem was kind of a weird edge case since I don't expect many people to have blank .json files like I did in my nvim/snippets directory.

Anyways, thanks for the help. Pointing out the register_snippets function helped a ton in figuring out what the issue was, and I'm excited to start using this plugin!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants