How do I set buffer-local keymaps that only activate when an LSP server attaches to a buffer in Neovim?
Answer
vim.api.nvim_create_autocmd('LspAttach', ...)
Explanation
Setting your LSP keymaps inside a LspAttach autocmd ensures they are only active in buffers where a language server is actually running. Global keymaps that call vim.lsp.buf.* functions fail silently (or not so silently) in buffers without LSP. The LspAttach event fires every time a server connects to a buffer, giving you the buffer number and client ID so you can set scoped mappings.
How it works
vim.api.nvim_create_autocmd('LspAttach', { callback = fn })registers a function called on each attachopts.bufinside the callback is the buffer number the server attached to- Passing
buffer = bufnrtovim.keymap.set()makes the mapping buffer-local and automatically removed when the buffer is wiped
Example
vim.api.nvim_create_autocmd('LspAttach', {
callback = function(opts)
local bufnr = opts.buf
local map = function(lhs, rhs, desc)
vim.keymap.set('n', lhs, rhs, { buffer = bufnr, desc = desc })
end
map('K', vim.lsp.buf.hover, 'LSP hover')
map('gd', vim.lsp.buf.definition, 'Go to definition')
map('gr', vim.lsp.buf.references, 'Go to references')
map('<leader>rn', vim.lsp.buf.rename, 'Rename symbol')
map('<leader>ca', vim.lsp.buf.code_action, 'Code action')
end,
})
Tips
- Access the client with
vim.lsp.get_client_by_id(opts.data.client_id)to guard capability-specific keymaps:if client:supports_method('textDocument/rename') then - Add
group = vim.api.nvim_create_augroup('MyLsp', { clear = true })to the autocmd opts to prevent duplicate registrations when your config is reloaded - This pattern works alongside both
vim.lsp.enable()(Neovim 0.11+) andnvim-lspconfig