Skip to content

Instantly share code, notes, and snippets.

@MariaSolOs
Last active June 26, 2024 08:42
Show Gist options
  • Save MariaSolOs/2e44a86f569323c478e5a078d0cf98cc to your computer and use it in GitHub Desktop.
Save MariaSolOs/2e44a86f569323c478e5a078d0cf98cc to your computer and use it in GitHub Desktop.
Built-in completion + snippet Neovim setup
---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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment