Last active
August 24, 2024 02:42
-
-
Save VonHeikemen/8fc2aa6da030757a5612393d0ae060bd to your computer and use it in GitHub Desktop.
nvim-lspconfig + nvim-cmp setup
This file contains 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
--[[ | |
blogpost: | |
https://vonheikemen.github.io/devlog/tools/setup-nvim-lspconfig-plus-nvim-cmp/ | |
Dependencies: | |
LSP: | |
https://github.com/neovim/nvim-lspconfig | |
https://github.com/williamboman/mason.nvim (optional) | |
https://github.com/williamboman/mason-lspconfig.nvim (optional) | |
Completion: | |
https://github.com/hrsh7th/nvim-cmp | |
https://github.com/hrsh7th/cmp-nvim-lsp | |
https://github.com/hrsh7th/cmp-buffer | |
https://github.com/hrsh7th/cmp-path | |
https://github.com/saadparwaiz1/cmp_luasnip | |
Snippets: | |
https://github.com/L3MON4D3/LuaSnip | |
https://github.com/rafamadriz/friendly-snippets | |
]] | |
--- | |
-- Keybindings | |
--- | |
vim.api.nvim_create_autocmd('LspAttach', { | |
desc = 'LSP actions', | |
callback = function() | |
local bufmap = function(mode, lhs, rhs) | |
local opts = {buffer = true} | |
vim.keymap.set(mode, lhs, rhs, opts) | |
end | |
bufmap('n', 'K', '<cmd>lua vim.lsp.buf.hover()<cr>') | |
bufmap('n', 'gd', '<cmd>lua vim.lsp.buf.definition()<cr>') | |
bufmap('n', 'gD', '<cmd>lua vim.lsp.buf.declaration()<cr>') | |
bufmap('n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<cr>') | |
bufmap('n', 'go', '<cmd>lua vim.lsp.buf.type_definition()<cr>') | |
bufmap('n', 'gr', '<cmd>lua vim.lsp.buf.references()<cr>') | |
bufmap('n', 'gs', '<cmd>lua vim.lsp.buf.signature_help()<cr>') | |
bufmap('n', '<F2>', '<cmd>lua vim.lsp.buf.rename()<cr>') | |
bufmap('n', '<F3>', '<cmd>lua vim.lsp.buf.format({async = true})<cr>') | |
bufmap('n', '<F4>', '<cmd>lua vim.lsp.buf.code_action()<cr>') | |
bufmap('n', 'gl', '<cmd>lua vim.diagnostic.open_float()<cr>') | |
bufmap('n', '[d', '<cmd>lua vim.diagnostic.goto_prev()<cr>') | |
bufmap('n', ']d', '<cmd>lua vim.diagnostic.goto_next()<cr>') | |
end | |
}) | |
--- | |
-- Diagnostics | |
--- | |
local sign = function(opts) | |
vim.fn.sign_define(opts.name, { | |
texthl = opts.name, | |
text = opts.text, | |
numhl = '' | |
}) | |
end | |
sign({name = 'DiagnosticSignError', text = '✘'}) | |
sign({name = 'DiagnosticSignWarn', text = '▲'}) | |
sign({name = 'DiagnosticSignHint', text = '⚑'}) | |
sign({name = 'DiagnosticSignInfo', text = ''}) | |
vim.diagnostic.config({ | |
virtual_text = false, | |
severity_sort = true, | |
float = { | |
border = 'rounded', | |
source = 'always', | |
}, | |
}) | |
vim.lsp.handlers['textDocument/hover'] = vim.lsp.with( | |
vim.lsp.handlers.hover, | |
{border = 'rounded'} | |
) | |
vim.lsp.handlers['textDocument/signatureHelp'] = vim.lsp.with( | |
vim.lsp.handlers.signature_help, | |
{border = 'rounded'} | |
) | |
--- | |
-- LSP servers | |
--- | |
-- require('mason').setup({}) | |
-- require('mason-lspconfig').setup({}) | |
local lspconfig = require('lspconfig') | |
local lsp_capabilities = require('cmp_nvim_lsp').default_capabilities() | |
lspconfig.tsserver.setup({ | |
capabilities = lsp_capabilities, | |
}) | |
lspconfig.lua_ls.setup({ | |
capabilities = lsp_capabilities, | |
}) | |
--- | |
-- Autocomplete | |
--- | |
vim.opt.completeopt = {'menu', 'menuone', 'noselect'} | |
require('luasnip.loaders.from_vscode').lazy_load() | |
local cmp = require('cmp') | |
local luasnip = require('luasnip') | |
local select_opts = {behavior = cmp.SelectBehavior.Select} | |
cmp.setup({ | |
snippet = { | |
expand = function(args) | |
luasnip.lsp_expand(args.body) | |
end | |
}, | |
sources = { | |
{name = 'path'}, | |
{name = 'nvim_lsp', keyword_length = 1}, | |
{name = 'buffer', keyword_length = 3}, | |
{name = 'luasnip', keyword_length = 2}, | |
}, | |
window = { | |
documentation = cmp.config.window.bordered() | |
}, | |
formatting = { | |
fields = {'menu', 'abbr', 'kind'}, | |
format = function(entry, item) | |
local menu_icon = { | |
nvim_lsp = 'λ', | |
luasnip = '⋗', | |
buffer = 'Ω', | |
path = '🖫', | |
} | |
item.menu = menu_icon[entry.source.name] | |
return item | |
end, | |
}, | |
mapping = { | |
['<Up>'] = cmp.mapping.select_prev_item(select_opts), | |
['<Down>'] = cmp.mapping.select_next_item(select_opts), | |
['<C-p>'] = cmp.mapping.select_prev_item(select_opts), | |
['<C-n>'] = cmp.mapping.select_next_item(select_opts), | |
['<C-u>'] = cmp.mapping.scroll_docs(-4), | |
['<C-d>'] = cmp.mapping.scroll_docs(4), | |
['<C-e>'] = cmp.mapping.abort(), | |
['<C-y>'] = cmp.mapping.confirm({select = true}), | |
['<CR>'] = cmp.mapping.confirm({select = false}), | |
['<C-f>'] = cmp.mapping(function(fallback) | |
if luasnip.jumpable(1) then | |
luasnip.jump(1) | |
else | |
fallback() | |
end | |
end, {'i', 's'}), | |
['<C-b>'] = cmp.mapping(function(fallback) | |
if luasnip.jumpable(-1) then | |
luasnip.jump(-1) | |
else | |
fallback() | |
end | |
end, {'i', 's'}), | |
['<Tab>'] = cmp.mapping(function(fallback) | |
local col = vim.fn.col('.') - 1 | |
if cmp.visible() then | |
cmp.select_next_item(select_opts) | |
elseif col == 0 or vim.fn.getline('.'):sub(col, col):match('%s') then | |
fallback() | |
else | |
cmp.complete() | |
end | |
end, {'i', 's'}), | |
['<S-Tab>'] = cmp.mapping(function(fallback) | |
if cmp.visible() then | |
cmp.select_prev_item(select_opts) | |
else | |
fallback() | |
end | |
end, {'i', 's'}), | |
}, | |
}) |
@anoduck if you are using the same config in this gist, you don't have to add it. The variable lsp_defaults.capabilities
has that enabled.
https://gist.github.com/VonHeikemen/8fc2aa6da030757a5612393d0ae060bd#file-init-lua-L97-L104
@VonHeikemen Awesome sauce! Thanks! What I needed to know.
I am really grateful for your guides on creating a configuration for nvim in lua. They are really detailed, and exceptionally worded. I find myself going back to them for reference, and now that I found you keep them updated, I will be returning to them often. It is the best tutorial I have read.
You should write a book on it and get no-starch press to publish it. You could title it, something like, "Absolute Nvim, in lua" ... just a suggestion... :)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@VonHeikemen Several language servers have asked me to enable an additional capability in my lsp configuration.
I haven't figured out how to work this into the current configuration schema, or even if it is needed. If this is needed to be added, how would you go about doing so?