hrsh7th / nvim-cmp

A completion plugin for neovim coded in Lua.
MIT License
7.51k stars 376 forks source link

completion menu does not trigger on insert enter #1059

Open Spo0on opened 2 years ago

Spo0on commented 2 years ago

FAQ

Announcement

Minimal reproducible full config

my lsp-config.lua file

-- local nvim_lsp = require('lspconfig')

local lsp = vim.lsp
local handlers = lsp.handlers

-- Hover doc popup
local pop_opts = { border = "rounded", max_width = 80 }
handlers["textDocument/hover"] = lsp.with(handlers.hover, pop_opts)
handlers["textDocument/signatureHelp"] = lsp.with(handlers.signature_help, pop_opts)

-- Use an on_attach function to only map the following keys
-- after the language server attaches to the current buffer
local opts = { noremap=true, silent=false }
vim.keymap.set('n', '<space>e', vim.diagnostic.open_float, opts)
vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, opts)
vim.keymap.set('n', ']d', vim.diagnostic.goto_next, opts)
vim.keymap.set('n', '<space>q', vim.diagnostic.setloclist, opts)

local on_attach = function(client, bufnr)
        -- Enable completion triggered by <c-x><c-o>
        vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc')

        -- Mappings.
        -- See `:help vim.lsp.*` for documentation on any of the below functions
        local bufopts = { noremap=true, silent=true, buffer=bufnr }
        vim.keymap.set('n', 'gD', lsp.buf.declaration, bufopts)
        vim.keymap.set('n', 'gd', lsp.buf.definition, bufopts)
        vim.keymap.set('n', 'K', lsp.buf.hover, bufopts)
        -- vim.keymap.set('n', 'gi', lsp.buf.implementation, bufopts)
        -- rimappare: il comando qui sotto (coincide con un altro comando)
        -- vim.keymap.set('n', '<C-k>', lsp.buf.signature_help, bufopts)
        vim.keymap.set('n', '<space>wa', lsp.buf.add_workspace_folder, bufopts)
        vim.keymap.set('n', '<space>wr', lsp.buf.remove_workspace_folder, bufopts)
        vim.keymap.set('n', '<space>wl', function()
                print(vim.inspect(vim.lsp.buf.list_workspace_folders()))
        end, bufopts)
        vim.keymap.set('n', '<space>D', lsp.buf.type_definition, bufopts)
        vim.keymap.set('n', '<space>rn', lsp.buf.rename, bufopts)
        vim.keymap.set('n', '<space>ca', lsp.buf.code_action, bufopts)
        vim.keymap.set('n', 'gr', lsp.buf.references, bufopts)
        -- buf_set_keymap('n', '<C-j>', '<cmd>lua vim.lsp.diagnostic.goto_prev()<CR>', opts)
        -- buf_set_keymap('n', '<S-C-j>', '<cmd>lua vim.lsp.diagnostic.goto_next()<CR>', opts)
        -- buf_set_keymap('n', '<space>q', '<cmd>lua vim.lsp.diagnostic.set_loclist()<CR>', opts)
        vim.keymap.set('n', '<space>f', lsp.buf.formatting, bufopts)

        -- RRethy/vim-illuminate
        require 'illuminate'.on_attach(client)
end

-- RRethy/vim-illuminate config (lua)
vim.api.nvim_command [[ hi def link LspReferenceText CursorLine ]]
vim.api.nvim_command [[ hi def link LspReferenceWrite CursorLine ]]
vim.api.nvim_command [[ hi def link LspReferenceRead CursorLine ]]
-- vim.api.nvim_set_keymap('n', '<a-n>', '<cmd>lua require"illuminate".next_reference{wrap=true}<cr>', {noremap=true})
-- vim.api.nvim_set_keymap('n', '<a-p>', '<cmd>lua require"illuminate".next_reference{reverse=true,wrap=true}<cr>', {noremap=true})

local lsp_flags = {
        -- This is the default in Nvim 0.7+
        debounce_text_changes = 150,
}

local capabilities = require('cmp_nvim_lsp').update_capabilities(vim.lsp.protocol.make_client_capabilities())

--   
local signs = { Error = " ", Warn = " ", Hint = " ", Info = " " }
for type, icon in pairs(signs) do
  local hl = "DiagnosticSign" .. type
  vim.fn.sign_define(hl, { text = icon, texthl = hl, numhl = hl })
end

-- LSP Enable diagnostics
vim.lsp.handlers["textDocument/publishDiagnostics"] =
    vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
        virtual_text = true,
        underline = true,
        signs = true,
        update_in_insert = true
    })

for _, server in ipairs(require('nvim-lsp-installer').get_installed_servers()) do
        require('lspconfig')[server.name].setup {
                settings = {
                        Lua = {
                                diagnostics = {
                                        globals = {'vim'},
                                }
                        }
                },
                on_attach = on_attach,
                capabilities = capabilities,
                flags = lsp_flags
        }
end

my cmp.lua file

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 luasnip = require("luasnip")

-- Setup nvim-cmp.
local cmp = require("cmp")

local mapping_sets = {
                ['<C-Space>'] = cmp.mapping(cmp.mapping.complete(), { "i", "s", "c" }),
                ['<C-b>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { "i", "s", "c" }),
                ['<C-f>'] = cmp.mapping(cmp.mapping.scroll_docs(4), { "i", "s", "c" }),
                -- ['<CR>'] = cmp.mapping.confirm({ select = true }, {"i", "s", "c" }),
                ['<CR>'] = cmp.mapping(function(fallback)
                        if cmp.visible() then
                                -- lua local line, col = unpack(vim.api.nvim_win_get_cursor(0)) print(vim.api.nvim_buf_get_lines(0, line -1, line, true)[1])
                                local entries = cmp.get_entries()
                                -- local line, col = unpack(vim.api.nvim_win_get_cursor(0))
                                -- local entire_line = vim.api.nvim_buf_get_lines(0, line -1, line, true)[1]
                                -- local word_under_cursor = col - string.find(string.reverse(string.sub(entire_line,0,col)), ' ')+2
                                local count = 0
                                for _ in pairs(entries) do count = count  + 1 end
                                if #entries == 1 then
                                        if entries[1].exact then
                                                local table = cmp.get_active_entry()
                                                if type(table) == "nil" then
                                                        fallback()
                                                elseif type(table) == "table" then
                                                        cmp.confirm({ select = true })
                                                end
                                        else
                                                cmp.confirm({ select = true })
                                        end
                                else
                                        cmp.confirm({ select = true })
                                end
                        else
                                fallback()
                        end
                end, { "i", "s", "c" }
                ),
                -- ["<C-p>"] = cmp.mapping.select_prev_item(),
                -- ["<C-n>"] = cmp.mapping.select_next_item(),
                ['<C-e>'] = cmp.mapping({
                  i = cmp.mapping.abort(),
                  c = cmp.mapping.close(),
                }),
                ["<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", "c" }),
                ["<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", "c" }),
        }

local lspkind = require('lspkind')
cmp.setup({
        view = {
                entries = "custom"
        },
        snippet = {
                -- REQUIRED - you must specify a snippet engine
                expand = function(args)
                        -- vim.fn["vsnip#anonymous"](args.body) -- For `vsnip` users.
                        luasnip.lsp_expand(args.body) -- For `luasnip` users.
                        -- require'snippy'.expand_snippet(args.body) -- For `snippy` users.
                        -- vim.fn["UltiSnips#Anon"](args.body) -- For `ultisnips` users.
                end
        },
        window = {
                completion = cmp.config.window.bordered({
                        border = 'rounded'
                }),
                documentation = cmp.config.window.bordered({
                        border = 'rounded'
                }),
        },
        mapping = cmp.mapping.preset.insert(mapping_sets),
        sources = cmp.config.sources({
                -- { name = 'ultisnips' }, -- For ultisnips users.
                { name = 'nvim_lsp' },
                { name = 'luasnip' }, -- For luasnip users.
        }, {
                -- { name = 'vsnip' }, -- For vsnip users.
                -- { name = 'snippy' }, -- For snippy users.
                { name = 'buffer' },
        }),
        formatting = {
                format = lspkind.cmp_format({
                        -- 'text', 'text_symbol', 'symbol_text', 'symbol'
                        mode = 'symbol',
                        maxwidth = 50
                })
        }
})

-- Use cmdline & path source for ':' (if you enabled `native_menu`, this won't work anymore).
cmp.setup.cmdline(':', {
        view = {
                entries = "custom"
        },
        mapping = mapping_sets,
        sources = cmp.config.sources({
                {
                        name = 'path',
                        option = {
                                trailing_slash = true
                        }
                }
        }, {
                { name = 'cmdline' },
        })
})

-- Use buffer source for `/` (if you enabled `native_menu`, this won't work anymore).
cmp.setup.cmdline('/', {
        view = {
                entries = "custom"
        },
        mapping = mapping_sets,
        sources = cmp.config.sources({
                {
                        name = 'path',
                        option = {
                                trailing_slash = true
                        }
                }
        }, {
                { name = 'buffer' },
        })
})

Description

When i enter insert mode with cursor just after a word it should trigger completion menu for that word, but this does not happen.

Steps to reproduce

Expected behavior

`

include

int main(void) { prin } ` when i enter in insert mode with cursor just after the "prin" word nothing happens, no completion menu appears

Actual behavior

`

include

int main(void) { prin } ` completion menu appearing in insert enter with print related completions

Additional context

No response

bbqben commented 1 year ago

I'm running into the same/similar behaviour as well when trying to get the completion menu to trigger for imports (using another library which feeds in information for what can be imported but the main issue lies with the completion menu not triggering).

Example

import { } from '..';

If you place the cursor between { } and try to trigger the menu it used to display the import options previously but currently no longer works

Shougo commented 1 year ago

Hm. I have checked the code.

https://github.com/hrsh7th/nvim-cmp/blob/4bc038f72ddfbe18a4870b8f7fe5f30b8d053f35/lua/cmp/view/wildmenu_entries_view.lua#L41

nvim-cmp registers CompleteChanged event only.
So InsertEnter event does not work.

It may fix the problem.

https://github.com/hrsh7th/nvim-cmp/issues/287#issuecomment-938693674

bbqben commented 1 year ago

@Shougo Thanks for sharing!! I'm still new to using neovim so it took me a while to get it to work with your comment.

@Spo0on I found that by using the following config I'm able to trigger the completion menu again so this might also help you:

cmp.setup({
    ...
    completion = {
        autocomplete = {
              cmp.TriggerEvent.TextChanged,
              cmp.TriggerEvent.InsertEnter,
          },
          completeopt = "menuone,noinsert,noselect",
          keyword_length = 0,
    },
    ...
})

EDIT: Using the settings above I've noticed that performance takes a bit of a hit, so you may have to adjust accordingly.

JulienLecoq commented 1 year ago

@bbqben Very weird, if we remove the cmp.TriggerEvent.TextChanged line, it doesn't trigger anymore when we enter insert mode by typing o

llllvvuu commented 11 months ago
cmp.setup({
  ...
  completion = {
      autocomplete = {
            cmp.TriggerEvent.TextChanged,
            cmp.TriggerEvent.InsertEnter,
        },
        completeopt = "menuone,noinsert,noselect",
        keyword_length = 0,
  },
  ...
})

@bbqben does this make it so that a menu shows up immediately once you press i, a, or c? Even with this, I still have to type and delete a letter to make the menu show up

HampusHauffman commented 3 months ago
            local lsp = require('lsp-zero').preset({})
            lsp.extend_cmp()
            local cmp = require("cmp")
            cmp.setup({
                completion = {
                    completeopt = 'menu,menuone,noinsert,noselect',
                    autocomplete = {
                        cmp.TriggerEvent.TextChanged,
                        cmp.TriggerEvent.InsertEnter,
                    },

                    keyword_length = 0,
                },
                ... rest of conf
                }

For me this is what worked using lsp-zero