Last active
June 18, 2025 19:24
-
-
Save MariaSolOs/2e44a86f569323c478e5a078d0cf98cc to your computer and use it in GitHub Desktop.
Built-in completion + snippet Neovim setup
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
---Utility for keymap creation. | |
---@param lhs string | |
---@param rhs string|function | |
---@param opts string|table | |
---@param mode? string|string[] | |
local function keymap(lhs, rhs, opts, mode) | |
opts = type(opts) == 'string' and { desc = opts } | |
or vim.tbl_extend('error', opts --[[@as table]], { buffer = bufnr }) | |
mode = mode or 'n' | |
vim.keymap.set(mode, lhs, rhs, opts) | |
end | |
---For replacing certain <C-x>... keymaps. | |
---@param keys string | |
local function feedkeys(keys) | |
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(keys, true, false, true), 'n', true) | |
end | |
---Is the completion menu open? | |
local function pumvisible() | |
return tonumber(vim.fn.pumvisible()) ~= 0 | |
end | |
-- Enable completion and configure keybindings. | |
if client.supports_method(methods.textDocument_completion) then | |
vim.lsp.completion.enable(true, client.id, bufnr, { autotrigger = true }) | |
-- Use enter to accept completions. | |
keymap('<cr>', function() | |
return pumvisible() and '<C-y>' or '<cr>' | |
end, { expr = true }, 'i') | |
-- Use slash to dismiss the completion menu. | |
keymap('/', function() | |
return pumvisible() and '<C-e>' or '/' | |
end, { expr = true }, 'i') | |
-- Use <C-n> to navigate to the next completion or: | |
-- - Trigger LSP completion. | |
-- - If there's no one, fallback to vanilla omnifunc. | |
keymap('<C-n>', function() | |
if pumvisible() then | |
feedkeys '<C-n>' | |
else | |
if next(vim.lsp.get_clients { bufnr = 0 }) then | |
vim.lsp.completion.trigger() | |
else | |
if vim.bo.omnifunc == '' then | |
feedkeys '<C-x><C-n>' | |
else | |
feedkeys '<C-x><C-o>' | |
end | |
end | |
end | |
end, 'Trigger/select next completion', 'i') | |
-- Buffer completions. | |
keymap('<C-u>', '<C-x><C-n>', { desc = 'Buffer completions' }, 'i') | |
-- Use <Tab> to accept a Copilot suggestion, navigate between snippet tabstops, | |
-- or select the next completion. | |
-- Do something similar with <S-Tab>. | |
keymap('<Tab>', function() | |
local copilot = require 'copilot.suggestion' | |
if copilot.is_visible() then | |
copilot.accept() | |
elseif pumvisible() then | |
feedkeys '<C-n>' | |
elseif vim.snippet.active { direction = 1 } then | |
vim.snippet.jump(1) | |
else | |
feedkeys '<Tab>' | |
end | |
end, {}, { 'i', 's' }) | |
keymap('<S-Tab>', function() | |
if pumvisible() then | |
feedkeys '<C-p>' | |
elseif vim.snippet.active { direction = -1 } then | |
vim.snippet.jump(-1) | |
else | |
feedkeys '<S-Tab>' | |
end | |
end, {}, { 'i', 's' }) | |
-- Inside a snippet, use backspace to remove the placeholder. | |
keymap('<BS>', '<C-o>s', {}, 's') | |
end |
Very cool! I'd like to add:
-- Autoselect the first item but don't insert it.
-- Allows quick use, just write something and enter to select the first one.
vim.opt.completeopt = { "menu", "menuone", "noinsert" }
-- Make completion menu appear whenever you type something.
-- Example from: https://neovim.io/doc/user/lsp.html#lsp-attach
-- Optional: trigger autocompletion on EVERY keypress. May be slow!
local chars = {}
for i = 32, 126 do
table.insert(chars, string.char(i))
end
client.server_capabilities.completionProvider.triggerCharacters = chars
vim.lsp.completion.enable(true, client.id, args.buf, {
autotrigger = true,
})
Some things that the built-in completion does not support (yet?):
- Hover documentation next to completion item. It does however support preview if you append
"preview"
tocompleteopt
. - Combined menu of both LSP and buffer items. You can only have either one or the other.
- Custom snippet support? I didn't get my custom snippets working. As I understand, this completion only works on LSP server provided completions?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
is the
autotrigger = true
supposed to show the autocomplete menu while we are editing the buffer?I've set it up with it, but when writing in a ts file for example nothing shows up, however pressing
<c-x><c-o>
does show the autocomplete menuor do we have to do more configuration to have it working? thanks!