-- -- 50-autocompletion.lua -- -- * Configures insert-mode/command-mode autocompletion. -- In both modes: -- * The list of completions shows up automatically -- * Tab/Shift+Tab selects (and inserts) the next/previous item -- In cmd-line mode: -- * Tab selects a lone match outright, inserts it, closes the menu -- (Useful when completing file names) -- * CTRL+Y inserts the selection; with no selection it dismisses the menu -- ---------------------------------------------------------------------------------------------------- -- Insert mode autocompletion ---------------------------------------------------------------------------------------------------- local function i_select_next_menu_item() return vim.fn.pumvisible() == 1 and "" or "" end local function i_select_previous_menu_item() return vim.fn.pumvisible() == 1 and "" or "" end ---------------------------------------------------------------------------------------------------- vim.opt.autocomplete = true -- Show completion menu automatically vim.opt.completeopt = { "noselect", -- No item selected initially "menuone", -- Show matches in a menu, even if there's only one match "popup", -- Menu items show extra info in the popup window "fuzzy", } -- Completion sources (in order of priority) vim.opt.complete = { "o", -- 'omnifunc' } vim.keymap.set("i", "", i_select_next_menu_item, { expr = true }) vim.keymap.set("i", "", i_select_previous_menu_item, { expr = true }) ---------------------------------------------------------------------------------------------------- -- Command-line mode autocompletion ---------------------------------------------------------------------------------------------------- -- `` is a self-cancelling edit: it closes the menu, then `CmdLineChanged` fires and -- tries to perform completion on the text before the cursor. local function c_insert_unique_or_wildtrigger() local complete_info = vim.fn.cmdcomplete_info() if complete_info.pum_visible == 1 then return #complete_info.matches == 1 and "" or "" end -- After navigating the command-line history, it takes two `wildtrigger()` calls to show the -- menu. The first is performed by the `CmdLineChanged` autocommand, the second is performed -- here. vim.fn.wildtrigger() return nil end local function c_accept_selection_or_dismiss() local complete_info = vim.fn.cmdcomplete_info() if complete_info.pum_visible == 1 then return complete_info.selected ~= -1 and "" or "" end return "" end ---------------------------------------------------------------------------------------------------- -- Show completion menu automatically vim.api.nvim_create_autocmd({ "CmdLineChanged", "CmdlineEnter" }, { desc = "Autocompletion", group = vim.g.dotfiles.augroup, pattern = "[:\\/\\?]", -- Matches : commands plus / and ? searches, but not = and @ callback = function() vim.fn.wildtrigger() end, }) vim.opt.wildmenu = true -- Show completions in a menu vim.opt.wildchar = 9 -- Char code (``) assigned to command line wildcard expansion vim.opt.wildoptions = { "exacttext", -- Discard regex artifacts when performing search pattern completion "pum", -- Show completions in a popup menu "tagfile", -- Show tag kind and file "fuzzy", -- Fuzzy matching (except for files/dirs, use patterns) } -- Completion modes triggered in order by `wildtrigger()` or 'wildchar' vim.opt.wildmode = { "noselect", -- List matches without inserting "full", -- List matches and inserts first full match } -- Converts `vim.opt.wildchar` char code into a key string that can be used by `vim.keymap.set()`. local wildchar_key = string.format("%c", vim.o.wildchar) vim.keymap.set( "c", wildchar_key, c_insert_unique_or_wildtrigger, { expr = true, desc = "Command line wildcard expansion" } ) vim.keymap.set("c", "", c_accept_selection_or_dismiss, { expr = true })