blink.cmp icon indicating copy to clipboard operation
blink.cmp copied to clipboard

Tab/S-Tab overridden after accepting snippet

Open chaozwn opened this issue 1 year ago • 12 comments

Make sure you have done the following

  • [X] I have updated to the latest version of blink.cmp
  • [X] I have read the README

Bug Description

I didn't add snippet_forward in <Tab>, but it actually works,I just hit <Tab> in the video, can remove it from <Tab>.

https://github.com/user-attachments/assets/1c98410b-8a28-4dd9-8255-11f9694e1e64

Relevant configuration

keymap = {
      ["<Up>"] = { "select_prev", "fallback" },
      ["<Down>"] = { "select_next", "fallback" },
      ["<C-N>"] = {
        "snippet_forward",
        "fallback",
      },
      ["<C-P>"] = {
        "snippet_backward",
        "fallback",
      },
      ["<C-J>"] = { "select_next", "fallback" },
      ["<C-K>"] = { "select_prev", "fallback" },
      ["<C-U>"] = { "scroll_documentation_up", "fallback" },
      ["<C-D>"] = { "scroll_documentation_down", "fallback" },
      ["<C-E>"] = { "hide", "fallback" },
      ["<CR>"] = { "accept", "fallback" },
      ["<Tab>"] = {
        function(cmp)
          if cmp.windows.autocomplete.win:is_open() then
            return cmp.accept()
          elseif has_words_before() then
            return cmp.show()
          end
        end,
        "fallback",
      },
      ["<S-Tab>"] = {
        function(cmp)
          if cmp.windows.autocomplete.win:is_open() then return cmp.select_prev() end
        end,
        "fallback",
      },
    },

neovim version

nvim 0.10.2

blink.cmp version: branch, tag, or commit

version: "*"

chaozwn avatar Nov 08 '24 02:11 chaozwn

I'm not able to reproduce this behavior, it seems to be an issue with your nvim config. Perhaps you have another bind on <Tab> that's getting called on the fallback?

saghen avatar Nov 09 '24 01:11 saghen

I'm not able to reproduce this behavior, it seems to be an issue with your nvim config. Perhaps you have another bind on <Tab> that's getting called on the fallback?

You may not have understood what I meant. In snippet mode, that is, when you select a snippet item during completion, if the snippet_forward is not fully cycled through, my Tab key won't work(It just performs a normal jump without selecting any item from the completion menu). This happens even when I use the default configuration of LazyVim. Removing the fallback results in the same effect.

chaozwn avatar Nov 09 '24 02:11 chaozwn

Does the native Neovim snippets feature have the Tab key bound by default?

chaozwn avatar Nov 09 '24 02:11 chaozwn

Yeah that's bizarre but it seems to be caused by some other plugin overriding blink's keymaps. Neovim doesn't bind <Tab> by default. If you can reproduce this with nvim -u NONE (or with a minimal config), then I can take another look

saghen avatar Nov 09 '24 02:11 saghen

Yeah that's bizarre but it seems to be caused by some other plugin overriding blink's keymaps. Neovim doesn't bind <Tab> by default. If you can reproduce this with nvim -u NONE (or with a minimal config), then I can take another look

vim.env.LAZY_STDPATH = ".repro"
load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))()

-- install plugins
require("lazy.minit").repro({
  spec = {
    {
      "hrsh7th/nvim-cmp",
      enabled = false,
    },
    {
      "saghen/blink.cmp",
      version = "*",
      opts_extend = { "sources.completion.enabled_providers" },
      dependencies = {
        "rafamadriz/friendly-snippets",
        -- add blink.compat to dependencies
        -- { "saghen/blink.compat", opts = {} },
      },
      event = "InsertEnter",

      ---@module 'blink.cmp'
      ---@type blink.cmp.Config
      opts = {
        highlight = {
          -- sets the fallback highlight groups to nvim-cmp's highlight groups
          -- useful for when your theme doesn't support blink.cmp
          -- will be removed in a future release, assuming themes add support
          use_nvim_cmp_as_default = false,
        },
        -- set to 'mono' for 'Nerd Font Mono' or 'normal' for 'Nerd Font'
        -- adjusts spacing to ensure icons are aligned
        nerd_font_variant = "mono",
        windows = {
          autocomplete = {
            -- draw = "reversed",
            winblend = vim.o.pumblend,
          },
          documentation = {
            auto_show = true,
          },
          ghost_text = {
            enabled = true,
          },
        },

        -- experimental auto-brackets support
        accept = { auto_brackets = { enabled = true } },

        -- experimental signature help support
        -- trigger = { signature_help = { enabled = true } }
        sources = {
          completion = {
            -- remember to enable your providers here
            enabled_providers = { "lsp", "path", "snippets", "buffer" },
          },
        },

        keymap = {
          ["<Up>"] = { "select_prev", "fallback" },
          ["<Down>"] = { "select_next", "fallback" },
          ["<C-N>"] = {
            "snippet_forward",
            "fallback",
          },
          ["<C-P>"] = {
            "snippet_backward",
            "fallback",
          },
          ["<C-J>"] = { "select_next", "fallback" },
          ["<C-K>"] = { "select_prev", "fallback" },
          ["<C-U>"] = { "scroll_documentation_up", "fallback" },
          ["<C-D>"] = { "scroll_documentation_down", "fallback" },
          ["<C-E>"] = { "hide", "fallback" },
          ["<CR>"] = { "accept", "fallback" },
          ["<Tab>"] = {
            function(cmp)
              vim.notify("hello1")
              if cmp.windows.autocomplete.win:is_open() then
                vim.notify("hello2")
                return cmp.accept()
              end
            end,
            "fallback",
          },
          ["<S-Tab>"] = {
            function(cmp)
              if cmp.windows.autocomplete.win:is_open() then
                return cmp.select_prev()
              end
            end,
            "fallback",
          },
        },
      },
    },
    {
      "neovim/nvim-lspconfig",
      config = function()
        require("lspconfig").lua_ls.setup({})
      end,
    },
  },
})

https://github.com/user-attachments/assets/8a557dae-9808-47fc-84c6-785bd894e0f1

chaozwn avatar Nov 09 '24 02:11 chaozwn

You can see from the above that when you're in snippets, the tab key loses its original function.

chaozwn avatar Nov 09 '24 02:11 chaozwn

Yeah that's bizarre but it seems to be caused by some other plugin overriding blink's keymaps. Neovim doesn't bind <Tab> by default. If you can reproduce this with nvim -u NONE (or with a minimal config), then I can take another look

I found another bug.

  1. input req and then select a snippet item
  2. after the snippet expands, randomly choose a completion item, then press <CR>.
  3. After that, you'll find that the Tab key can no longer be used for completion.

https://github.com/user-attachments/assets/8042f15e-2402-445b-ac78-8467a1ad22fe

chaozwn avatar Nov 09 '24 03:11 chaozwn

I'm not able to reproduce either issue by following the steps in the video and using the config you sent. I'm using neovim 0.10.2 as well but on NixOS. This issue seems isolated to your system so you'll have to debug this yourself. Sorry about that :confused:

saghen avatar Nov 11 '24 00:11 saghen

I'm not able to reproduce either issue by following the steps in the video and using the config you sent. I'm using neovim 0.10.2 as well but on NixOS. This issue seems isolated to your system so you'll have to debug this yourself. Sorry about that 😕

sorry, i use in nvim 0.11, There really is no problem with neovim 0.10.

chaozwn avatar Nov 11 '24 12:11 chaozwn

I think this commit https://github.com/neovim/neovim/commit/e6cfcaed184d4ecdc8a8638429e1bd9e1b3251dc which adds default keymaps for nvim snippets to Tab and S-Tab is the problem here.

tomstockl avatar Nov 22 '24 16:11 tomstockl

Relevant issue https://github.com/neovim/neovim/issues/30306. We could hack around this but I'd rather wait for 0.11 to become stable, hopefully with some way to reliably override this keymap.

saghen avatar Nov 24 '24 21:11 saghen

Hey there, that's essentially the same issue I described in https://github.com/Saghen/blink.cmp/issues/128#issuecomment-2453509648. I was going to report a new issue, but I was beaten to it (commenting here for reference)

igorlfs avatar Nov 24 '24 21:11 igorlfs

This is my blink config:

return {
  {
    "blink.cmp",
    opts = {
      keymap = {
        preset = "super-tab",
      },
    },
  },
  {
    "blink.cmp",
    optional = true,
    opts = {
      sources = { default = { "luasnip" } },
      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,
      },
    },
  },
}

I followed from blink|lazyvim & luasnip.

When I use <Tab>,the first time, it 'accept'(it's right),but when i continue <Tab>,it do nothing(it should be 'snippet_forward'). I'm not sure if it's the same problem.

GeoDaoyu avatar Dec 31 '24 02:12 GeoDaoyu

I use Neovim 0.11, this is my temporary solution, I don't use snippets, I only want completion for lsp, buffer and path. Is there any other temporary solution other than modifying the Neovim source code? 20250111_19h06m02s_grim

gmr458 avatar Jan 12 '25 00:01 gmr458

Check here for a workaround

igorlfs avatar Jan 12 '25 01:01 igorlfs

Fixed upstream in https://github.com/neovim/neovim/pull/31887

saghen avatar Mar 17 '25 18:03 saghen