diff options
Diffstat (limited to '.config')
| -rw-r--r-- | .config/nvim/plugin/50-autocompletion.lua | 116 |
1 files changed, 69 insertions, 47 deletions
diff --git a/.config/nvim/plugin/50-autocompletion.lua b/.config/nvim/plugin/50-autocompletion.lua index caf749d..dbc5dee 100644 --- a/.config/nvim/plugin/50-autocompletion.lua +++ b/.config/nvim/plugin/50-autocompletion.lua @@ -1,81 +1,103 @@ -- --- Completion configuration plugin +-- 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 +---------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------------------------- --- Insert mode completion ------------------------------------------------------------------------------------------------------------------------- --- See `:help ins-completion-menu` +local function i_select_next_menu_item() + return vim.fn.pumvisible() == 1 and "<C-n>" or "<Tab>" +end + +local function i_select_previous_menu_item() + return vim.fn.pumvisible() == 1 and "<C-p>" or "<S-Tab>" +end + +---------------------------------------------------------------------------------------------------- vim.opt.autocomplete = true -- Show completion menu automatically vim.opt.completeopt = { "noselect", -- No item selected initially - "fuzzy", "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.opt.pumwidth = 25 -vim.keymap.set("i", "<Tab>", function() - return vim.fn.pumvisible() == 1 and "<C-n>" or "<Tab>" -end, { expr = true }) -vim.keymap.set("i", "<S-Tab>", function() - return vim.fn.pumvisible() == 1 and "<C-p>" or "<S-Tab>" -end, { expr = true }) --- Jump between snippet placeholders, falling back to native behavior when no snippet is active -vim.keymap.set({ "i", "s" }, "<C-n>", function() - return vim.snippet.active({ direction = 1 }) and "<Cmd>lua vim.snippet.jump(1)<CR>" or "<C-n>" -end, { expr = true }) -vim.keymap.set({ "i", "s" }, "<C-p>", function() - return vim.snippet.active({ direction = -1 }) and "<Cmd>lua vim.snippet.jump(-1)<CR>" or "<C-p>" -end, { expr = true }) +vim.keymap.set("i", "<Tab>", i_select_next_menu_item, { expr = true }) +vim.keymap.set("i", "<S-Tab>", i_select_previous_menu_item, { expr = true }) + +---------------------------------------------------------------------------------------------------- +-- Command-line mode autocompletion +---------------------------------------------------------------------------------------------------- +-- `<Space><BS>` 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 "<C-n><Space><BS>" or "<C-n>" + 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 "<Space><BS>" or "<C-e>" + end + return "<C-y>" +end ------------------------------------------------------------------------------------------------------------------------- --- Command-line mode completion ------------------------------------------------------------------------------------------------------------------------- --- See `:help cmdline-completion` and `:help cmdline-autocompletion` +---------------------------------------------------------------------------------------------------- -- Show completion menu automatically -vim.api.nvim_create_autocmd({ "CmdlineChanged", "CmdlineEnter" }, { +vim.api.nvim_create_autocmd({ "CmdLineChanged", "CmdlineEnter" }, { desc = "Autocompletion", group = vim.g.dotfiles.augroup, - pattern = "[:\\/\\?]", + 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.pumborder = "rounded" +vim.opt.wildchar = 9 -- Char code (`<Tab>`) 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 (doesn't work with files/dirs, see `:help 'wildoptions'`, but patterns do work!) + "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 insert first full match + "full", -- List matches and inserts first full match } --- Insert unique match -vim.keymap.set("c", string.format("%c", vim.o.wildchar), function() - local complete_info = vim.fn.cmdcomplete_info() - if complete_info.pum_visible == 1 then - return #complete_info.matches == 1 and "<C-n><Space><BS>" or "<C-n>" - end - vim.fn.wildtrigger() -end, { expr = true, desc = "Command line wildcard expansion" }) --- Show next completion choices after accepting an entry with `<C-y>` -vim.keymap.set("c", "<C-y>", function() - local complete_info = vim.fn.cmdcomplete_info() - if complete_info.pum_visible == 1 then - return complete_info.selected ~= -1 and "<Space><BS>" or "<C-e>" - end - return "<C-y>" -end, { expr = true }) + +-- 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-y>", c_accept_selection_or_dismiss, { expr = true }) |
