abecodes / tabout.nvim

tabout plugin for neovim
The Unlicense
756 stars 19 forks source link

Unable to get this working with nvim-cmp #15

Closed Olyve closed 2 years ago

Olyve commented 2 years ago

Hi do you have any tips for getting this to work with nvim-cmp? I have tried following your suggested setup for working with nvim-compe which should be similar, but no matter what I do I cannot get this to work.

I'm using the default mapping for tab with nvim-cmp and then I have <tab> mapped to a function as suggested:

function _G.tab_complete()
   if cmp.visible()                                                                                                                                                                                                                                            
     return cmp.select_next_item()
   elseif luasnip.expand_or_jumpable() then
     return luasnip.expand_or_jump()
   elseif utils.check_back_space() then
     cmp.complete()
   else
     return utils.replace_keycodes("<Plug>(Tabout)")
   end
end

What I get though is pressing <tab> in insert mode just outputs <Plug>(Tabout) as text into the current position. The key map is using the expr = true syntax as well. Any thoughts?

abecodes commented 2 years ago

Hi @sgalizia

what happens if you replace utils.replace_keycodes("<Plug>(Tabout)") with vim.api.nvim_set_keymap('i', config.options.tabkey, "<Plug>(Tabout)", {silent = true})?

Are you using the completion = true setting?

silveste commented 2 years ago

I had similar issue as I recently switched from nvim-compe to nvim-cmp. In my case I managed to make it work by removing tabout.nvim functions and key mappings. Here are my mappings for <Tab> and <S-Tab> in nvim-cmp setup:

  ['<Tab>'] = function(fallback)
    if cmp.visible() then
      cmp.select_next_item()
    elseif luasnip.expand_or_jumpable() then
      vim.fn.feedkeys(vim.api.nvim_replace_termcodes('<Plug>luasnip-expand-or-jump', true, true, true), '')
    else
      fallback()
    end
  end,
  ['<S-Tab>'] = function(fallback)
    if cmp.visible() then
      cmp.select_prev_item()
    elseif luasnip.jumpable(-1) then
      vim.fn.feedkeys(vim.api.nvim_replace_termcodes('<Plug>luasnip-jump-prev', true, true, true), '')
    else
      fallback()
    end
  end,

When fallback() is called tabout.nvim is working out of the box and there is no need for special mappings as with nvim-compe.

az3r commented 2 years ago

based on @silveste 's answer, for anyone using vim-vsnip:

["<Tab>"] = function(fallback)
  if cmp.visible() then
    -- cmp.select_next_item()
    cmp.confirm(
      {
        behavior = cmp.ConfirmBehavior.Insert,
        select = true
      }
    )
  elseif vim.fn["vsnip#available"](1) ~= 0 then
    vim.fn.feedkeys(vim.api.nvim_replace_termcodes("<Plug>(vsnip-expand-or-jump)", true, true, true), "")
  else
    fallback()
  end
end,
["<S-Tab>"] = function(fallback)
  if cmp.visible() then
    cmp.select_prev_item()
  elseif vim.fn["vsnip#available"](1) ~= 0 then
    vim.fn.feedkeys(vim.api.nvim_replace_termcodes("<Plug>(vsnip-jump-prev)", true, true, true), "")
  else
    fallback()
  end
end,
abecodes commented 2 years ago

@silveste @Az3r Would you mind creating PRs with your additions to the README? Otherwise I will do it, but I would prefer you being listed as the contributors since it is your work

az3r commented 2 years ago

sure, i have created a pull request

abecodes commented 2 years ago

@silveste @Az3r Thanks to both of you 👍

Olyve commented 2 years ago

@Az3r I tried your solution and I still cannot get tabout to work for me. I'm not certain why it’s not working, either.

gerritvreeman commented 2 years ago

I also cannot seem to get this to work using the posted solution for vim-vsnip. The fallback function inserts X<fd>S(Tabout). It works flawlessly when removing the ["<TAB>"] mappings from nvim-cmp though.

az3r commented 2 years ago

here is my config for nvim-cmp, have a look and compare it to yours

local cmp = require "cmp"
cmp.setup(
    {
        snippet = {
            expand = function(args)
                vim.fn["vsnip#anonymous"](args.body)
            end
        },
        mapping = {
            ["<C-space>"] = cmp.mapping.complete(),
            ["<C-e>"] = cmp.mapping.close(),
            ["<Tab>"] = function(fallback)
                if cmp.visible() then
                    -- cmp.select_next_item
                    cmp.confirm(
                        {
                            behavior = cmp.ConfirmBehavior.Insert,
                            select = true
                        }
                    )
                elseif vim.fn["vsnip#available"](1) ~= 0 then
                    vim.fn.feedkeys(
                        vim.api.nvim_replace_termcodes("<Plug>(vsnip-expand-or-jump)", true, true, true),
                        ""
                    )
                else
                    fallback()
                end
            end,
            ["<S-Tab>"] = function(fallback)
                if cmp.visible() then
                    cmp.select_prev_item()
                elseif vim.fn["vsnip#available"](1) ~= 0 then
                    vim.fn.feedkeys(vim.api.nvim_replace_termcodes("<Plug>(vsnip-jump-prev)", true, true, true), "")
                else
                    fallback()
                end
            end,
            ["<C-f>"] = cmp.mapping.confirm(
                {
                    behavior = cmp.ConfirmBehavior.Insert,
                    select = true
                }
            )
        },
        sources = {
            {name = "nvim_lsp"},
            {name = "vsnip"},
            {name = "buffer"}
        },
        formatting = {
            format = function(entry, vim_item)
                -- fancy icons and a name of kind
                vim_item.kind = require("lspkind").presets.default[vim_item.kind] .. " " .. vim_item.kind

                return vim_item
            end
        }
    }
)
require('tabout').setup{}
gerritvreeman commented 2 years ago

I'm still seeing the same behavior after copying your nvim-cmp config, unfortunately. It actually looks like <S-Tab> is working correctly, but <Tab> still inserts X<fd>S(Tabout).

az3r commented 2 years ago

If you use another plugin manager just make sure tabout.nvim is loaded after nvim-treesitter and any completion that already uses your tabkey.

You should check if any plugin is using your tab key, maybe there is a conflict, if <S-tab> work then <Tab> should work, too. My config doesn't have any tab mappings except the one in cmp config

gerritvreeman commented 2 years ago

I'm not sure, because if I remove the <Tab> mapping in the nvim-cmp config, tabbing out works really well.

I think I fixed it by replacing the fallback() function in the <Tab> mapping with

vim.fn.feedkeys(vim.api.nvim_replace_termcodes("<Plug>(Tabout)", true, true, true), "")
az3r commented 2 years ago

Nice, your solution works for me, too. According nvim-cmp's documentation:

You can specify the mapping as function that receives the fallback function as arguments. The fallback function can be used to call an existing mapping.

i use fallback because tabout is the only plugin left that registers <Tab> mapping in my config. So if you have more plugins registering <Tab> then @gerritvreeman's answer is the way

rubenmate commented 2 years ago

I'm not sure, because if I remove the <Tab> mapping in the nvim-cmp config, tabbing out works really well.

I think I fixed it by replacing the fallback() function in the <Tab> mapping with

vim.fn.feedkeys(vim.api.nvim_replace_termcodes("<Plug>(Tabout)", true, true, true), "")

I have the same issue but replacing fallback() with this just insert (Tabout) for me.

Any idea of what could be going on?

abecodes commented 2 years ago

@rubenmate I use another completion, but I do smth like this after the completion's setup:

utils.map('i', utils.replace '<Tab>', 'pumvisible() ? "<C-n>" : "<Plug>Tabout"',{silent = true, expr = true})

<C-n> being the trigger for the tab-function of the completion.

The feedkeys solution should work too, I have no idea right now, why you just get the strange output. Can you change the load order? When I used cmp I loaded tabout after cmp and it worked right out of the box.

I hope smth helps, let me know :)

rubenmate commented 2 years ago

@rubenmate I use another completion, but I do smth like this after the completion's setup:

utils.map('i', utils.replace '<Tab>', 'pumvisible() ? "<C-n>" : "<Plug>Tabout"',{silent = true, expr = true})

<C-n> being the trigger for the tab-function of the completion.

The feedkeys solution should work too, I have no idea right now, why you just get the strange output. Can you change the load order? When I used cmp I loaded tabout after cmp and it worked right out of the box.

I hope smth helps, let me know :)

Thanks for your reply, I don't understand why but removing the after requirement on the packer code fixed it.

It's working great, but sometimes I get some random movements that I don't understand (Going up to a previous curly brace when tabbing out a string).

az3r commented 2 years ago

if you are using vsnip, when you expand a snippet and haven't jumped to all of its placeholders, then vsnip will jump to the next placeholder the next time you use <Plug>(vsnip-expand-or-jump) no matter where you are.

i don't know about lua-snip though

rubenmate commented 2 years ago

if you are using vsnip, when you expand a snippet and haven't jumped to all of its placeholders, then vsnip will jump to the next placeholder the next time you use <Plug>(vsnip-expand-or-jump) no matter where you are.

i don't know about lua-snip though

I think I found the problem. Turns out that GitHub Copilot is messing with the fallback function and that's why it inserts that (removed tabout and happened also with the cmp command).

https://github.com/NvChad/NvChad/issues/597#issuecomment-965055480

danielo515 commented 2 years ago

If anyone is having trouble making this work using the <Plug> or the fallback method, this is what worked for me: using plain lua:

local function tab(fallback)
    local methods = require("lvim.core.cmp").methods
    local cmp = require("cmp")
    local luasnip = require("luasnip")
    if cmp.visible() then
        cmp.select_next_item()
    elseif luasnip.expandable() then
        luasnip.expand()
    elseif methods.jumpable() then
        luasnip.jump(1)
    elseif methods.check_backspace() then
        fallback()
    else
        print("not working at all")
        require("tabout").tabout()
    end
end