Skip to content

Instantly share code, notes, and snippets.

@VonHeikemen
Last active August 24, 2024 02:42
Show Gist options
  • Save VonHeikemen/8fc2aa6da030757a5612393d0ae060bd to your computer and use it in GitHub Desktop.
Save VonHeikemen/8fc2aa6da030757a5612393d0ae060bd to your computer and use it in GitHub Desktop.
nvim-lspconfig + nvim-cmp setup
--[[
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
Copy link

anoduck commented Nov 15, 2022

@VonHeikemen Several language servers have asked me to enable an additional capability in my lsp configuration.

capabilities.textDocument.completion.completionItem.snippetSupport = true,

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?

@VonHeikemen
Copy link
Author

VonHeikemen commented Nov 15, 2022

@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

@anoduck
Copy link

anoduck commented Nov 15, 2022

@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