From 1cd5c8fb0deb81b0a362d112d23bbb7c8604aa86 Mon Sep 17 00:00:00 2001 From: Charles Danesi Date: Mon, 25 Nov 2024 12:19:39 -0500 Subject: [PATCH] fix autocompletion add keybinds for scrolling docs can now cycle up/down completions with tab/shift-tab C-f / C-b jump forward/back in function args completions for search in wildmenu completion for cmd works now --- .config/nvim/lua/plugins/autocomplete.lua | 152 ++++++++++++++++++---- 1 file changed, 129 insertions(+), 23 deletions(-) diff --git a/.config/nvim/lua/plugins/autocomplete.lua b/.config/nvim/lua/plugins/autocomplete.lua index 00f3e81..5791c04 100644 --- a/.config/nvim/lua/plugins/autocomplete.lua +++ b/.config/nvim/lua/plugins/autocomplete.lua @@ -5,6 +5,7 @@ return { 'hrsh7th/cmp-buffer', 'hrsh7th/cmp-path', 'hrsh7th/cmp-cmdline', + 'hrsh7th/cmp-buffer', 'hrsh7th/cmp-nvim-lsp', 'hrsh7th/cmp-nvim-lsp-document-symbol', 'hrsh7th/cmp-nvim-lsp-signature-help', @@ -20,54 +21,121 @@ return { config = function() local cmp = require('cmp') - local luasnip = require('luasnip') + local snippet = require('luasnip') local lspkind = require('lspkind') + local select_opts = { behavior = cmp.SelectBehavior.Select } require('luasnip.loaders.from_vscode').lazy_load() cmp.setup({ + enabled = function() + -- disable completion in comments + local context = require('cmp.config.context') + + if vim.api.nvim_get_mode().mode == 'c' then + return true + else + return not context.in_treesitter_capture('comment') and not context.in_syntax_group('Comment') + end + end, view = { entries = 'custom', selection_order = 'near_cursor', }, + window = { + documentation = cmp.config.window.bordered(), + }, completion = { completeopt = 'menu,menuone,preview,noselect', }, snippet = { expand = function(args) - luasnip.lsp_expand(args.body) + snippet.lsp_expand(args.body) end, }, mapping = cmp.mapping.preset.insert({ [''] = cmp.mapping.select_prev_item(), [''] = cmp.mapping.select_next_item(), - [''] = cmp.mapping.scroll_docs(-4), - [''] = cmp.mapping.scroll_docs(4), - [''] = cmp.mapping.complete(), + [''] = cmp.mapping.scroll_docs(-4), + [''] = cmp.mapping.scroll_docs(4), + -- [''] = cmp.mapping.complete(), + + -- ┌ + -- │ if completion menu is visible, move prev/next with + -- │ tab/s-tab + -- │ if we're not attached to anything, then insert a tab + -- │ if we're inside a word, trigger the completion menu + -- └ + [''] = cmp.mapping(function(fallback) + local col = vim.fn.col('.') - 1 + + if cmp.visible() then + cmp.select_next_item(select_opts) + elseif col == 0 or vim.fn.getline('.'):sub(col, col):match('%s') then + fallback() + else + cmp.complete() + end + end, { 'i', 's' }), + [''] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item(select_opts) + else + fallback() + end + end, { 'i', 's' }), [''] = cmp.mapping.abort(), [''] = cmp.mapping.confirm({ select = false }), + [''] = cmp.mapping(function(fallback) + if snippet.jumpable(1) then + snippet.jump(1) + else + fallback() + end + end, { 'i', 's' }), + [''] = cmp.mapping(function(fallback) + if snippet.jumpable(-1) then + snippet.jump(-1) + else + fallback() + end + end, { 'i', 's' }), }), sources = cmp.config.sources({ - { name = 'nvim_lsp' }, - { name = 'luasnip' }, - { name = 'buffer' }, + { name = 'nvim_lsp', priority = 1 }, + { name = 'luasnip', priority = 2 }, + { name = 'buffer', keyword_length = 3 }, { name = 'path' }, }), formatting = { - format = lspkind.cmp_format({ - mode = 'symbol_text', - maxwidth = 50, - ellipsis_char = '...', - show_labelDetails = true, - menu = { - -- add name of source to the menu - nvim_lsp = '[LSP]', - nvim_lua = '[Lua]', - luasnip = '[LuaSnip]', - buffer = '[Buffer]', - path = '[Path]', - }, - }), + -- fields = { 'abbr', 'kind', 'menu' }, + expandable_indicator = true, + format = function(entry, vim_item) + if vim.tbl_contains({ 'path' }, entry.source.name) then + local icon, hl_group = require('nvim-web-devicons').get_icon(entry.completion_item().label) + if icon then + vim_item.kind = icon + vim_item.kind_hl_group = hl_group + return vim_item + end + end + return lspkind.cmp_format({ + with_text = true, + mode = 'symbol_text', + maxwidth = 50, + ellipsis_char = '...', + show_labelDetails = true, + menu = { + -- add name of source to the menu + nvim_lsp = '[LSP]', + nvim_lua = '[Lua]', + luasnip = '[LuaSnip]', + buffer = '[Buffer]', + path = '[Path]', + latex_symbols = '[Latex]', + }, + })(entry, vim_item) + end, }, -- VSCode-like, kind specific highlights vim.api.nvim_set_hl(0, 'CmpItemAbbrDeprecated', { bg = 'NONE', strikethrough = true, fg = '#4c566a' }), @@ -82,5 +150,43 @@ return { vim.api.nvim_set_hl(0, 'CmpItemKindProperty', { link = 'CmpItemKindKeyword' }), vim.api.nvim_set_hl(0, 'CmpItemKindUnit', { link = 'CmpItemKindKeyword' }), }) + + cmp.setup.cmdline({ '/', '?' }, { + mapping = cmp.mapping.preset.cmdline(), + view = { + entries = { + name = 'wildmenu', + separator = '|', + }, + }, + sources = { + { name = 'buffer' }, + }, + }) + + cmp.setup.cmdline(':', { + enabled = function() + local disabled = { + -- list of commands to disable completions + wq = true, + wqa = true, + } + local cmd = vim.fn.getcmdline():match('%S+') + return not disabled[cmd] or cmp.close() + end, + mapping = cmp.mapping.preset.cmdline(), + sources = cmp.config.sources({ + { name = 'path' }, + { name = 'cmdline' }, + }), + matching = { + disallow_fullfuzzy_matching = false, + disallow_fuzzy_matching = false, + disallow_partial_fuzzy_matching = false, + disallow_partial_matching = false, + disallow_prefix_unmatching = false, + disallow_symbol_nonprefix_matching = false, + }, + }) end, -} \ No newline at end of file +}