LuaSnip icon indicating copy to clipboard operation
LuaSnip copied to clipboard

luasnip doesn't remove autocomplete placeholder marks after exiting insert mode

Open dialtone opened this issue 3 years ago • 4 comments

GIF of what happens

Basic description is that after accepting an autocompletion luasnip, somehow pressing again tab in insert mode results in the caret jumping back to the autocompletion that was accepted.

I'm using luasnip with basic nvim-cmp integration.

-- Setup Completion
-- See https://github.com/hrsh7th/nvim-cmp#basic-configuration
-- https://github.com/hrsh7th/nvim-cmp/wiki/Example-mappings#luasnip
local has_words_before = function()
  local line, col = unpack(vim.api.nvim_win_get_cursor(0))
  return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
end
local cmp = require'cmp'
local luasnip = require("luasnip")
cmp.setup({
  -- Enable LSP snippets
  snippet = {
    expand = function(args)
      require'luasnip'.lsp_expand(args.body)
    end
  },
  mapping = {
    ['<C-p>'] = cmp.mapping.select_prev_item(),
    ['<C-n>'] = cmp.mapping.select_next_item(),
    -- Add tab support
    ['<C-d>'] = cmp.mapping.scroll_docs(-4),
    ['<C-f>'] = cmp.mapping.scroll_docs(4),
    ['<C-Space>'] = cmp.mapping.complete(),
    ['<C-e>'] = cmp.mapping.close(),
    ['<CR>'] = cmp.mapping.confirm({
      behavior = cmp.ConfirmBehavior.Insert,
      select = true,
    }),
    ["<Tab>"] = cmp.mapping(function(fallback)
      if cmp.visible() then
        cmp.select_next_item()
      elseif luasnip.expand_or_jumpable() then
        luasnip.expand_or_jump()
      elseif has_words_before() then
        cmp.complete()
      else
        fallback()
      end
    end, { "i", "s" }),

    ["<S-Tab>"] = cmp.mapping(function(fallback)
      if cmp.visible() then
        cmp.select_prev_item()
      elseif luasnip.jumpable(-1) then
        luasnip.jump(-1)
      else
        fallback()
      end
    end, { "i", "s" }),
  },

  -- Installed sources
  sources = {
    { name = 'luasnip' },
    { name = 'nvim_lsp' },
    { name = 'buffer' },
    { name = 'path' },
  },
})

dialtone avatar Aug 14 '22 18:08 dialtone

Ah, this is just the default-behaviour of luasnip, placeholders are always visited in order (including the $0, which is the one you're jumping back into) (and that does not depend on cursor-movement), so if a snippet is not jumped "through", you'll end up back in it, regardless how the cursor moved.

This can be adjusted by passing a few options to luasnip.setup: region_check_events are the auto-events, on which a check if the cursor is still inside the active snippet is performed. If it is not, the snippet will be jumped "through"/completed/left, so you won't jump back into it. I'd recommend

luasnip.setup({
  region_check_events = "CursorHold,InsertLeave",
  -- those are for removing deleted snippets, also a common problem
  delete_check_events = "TextChanged,InsertEnter",
})

but you might want to adjust those to fire more regularly.

L3MON4D3 avatar Aug 14 '22 18:08 L3MON4D3

local luasnip = require("luasnip")
luasnip.config.setup({
    region_check_events = "CursorHold,InsertLeave",
    delete_check_events = "TextChanged,InsertEnter",
})
cmp.setup({
  enabled = function()
    -- disable completion in comments
 ...
});

this doesn't appear to change anything. Even though the author of nvim-cmp sent me back here, the gif doesn't actually trigger a luasnip automcomplete, I think the deal is just in how the <tab> integrates luasnip and nvim-cmp, but the autocomplete that causes this behavior is an nvim-cmp autocomplete.

dialtone avatar Aug 14 '22 21:08 dialtone

Appending an ,InsertEnter to region_check_events should do it, if you exactly re-do the gif. I'll check later if that's also the case for me.

Its not an issue with cmp, the problem is that luasnip will always jump through all placeholders/tabstops of a snippet. It does not matter whether the Cursor is moved around, the internal state of which tabstops will be jumped to next is preserved.

Not sure what you mean with Luasnip autocomplete though, the important part is that a snippet is expanded, and luasnip takes care of that.

L3MON4D3 avatar Aug 14 '22 22:08 L3MON4D3

That seems to have done it.

dialtone avatar Aug 14 '22 22:08 dialtone

Is this method still working ? I have image

but it gives the same error, If I move out of the snippets manually and work on something else then the tab brings me back to end of the snippet

edit: Tab Function of cmp if required image

sanchit1053 avatar Mar 28 '23 10:03 sanchit1053

Maybe append append TextChangedI to region_check_events? Or CursorMovedI, but that might be too aggressive.. (ie runs that function too often, maybe affecting performance)

L3MON4D3 avatar Mar 28 '23 13:03 L3MON4D3

image For this snippet if I (instead of pressing tab inside the $$ )manually leave it and then press tab anywhere else then I always come back to the end of the snippet

sanchit1053 avatar Mar 28 '23 18:03 sanchit1053