A quick guide to set up nvim built in LSP
Edit: This article was update after the decision of the lspconfig team to delete the download option for some clients, and the moving to init.lua
configuration file.
Background
In the last few months I’ve been learning how to use vim, and more specifically neovim.
As a developper one of the most useful tool we have now is the LSP. So naturally I’ve been looking forward to neovim builtin LSP. But when it came i found it really hard to find any quick guide to set it up.
So I decided to create this guide after experimenting with nvim’s LSP to help other who would like, as I did, a quick guide to set up nvim built in LSP.
Some parts of this configuration are inspired by tjdevries configuration files.
Requirements
You can install completion-nvim
and nvim-lspconfig
with your favorite plugin manager.
You do not need to know how to program in lua to follow this guide. It’s an easy language to understand and the api provided are pretty self documented by the names of the functions.
Setting up the LSP
The first thing you should do is to create a lua
folder at the root of your neovim configuration directory. As it’s always good to keep an ordered config directory, we will put all the lua configuration files in it.
Inside your lua
directory you can create the lsp_config.lua
file.
You should now have a nvim configuration directory that looks like this (plus all your other nvim config files):
.
├── init.lua
└── lua
└── lsp_config.lua
It’s now time to edit your lsp_config.lua
file.
First if you have installed completion-nvim
as vim package, you need to add this first in your lsp_config.lua
file:
vim.cmd [[ packadd completion-nvim ]]
Adding a few local variables and helper function
We are now going to add a few important variables that are going to be useful to avoid very verbose code in the next steps:
local lsp = require('lspconfig')
local completion = require('completion')
Without this variables we would have to write require('lspconfig')
or require('completion')
in place of lsp
and completion
which could get annoying very quickly.
The next step is to create an helper function to bind new mappings, this function will be useful later in the configuration.
local mapper = function(mode, key, result)
vim.api.nvim_buf_set_keymap(0, mode, key, "<cmd>lua "..result.."<cr>", {noremap = true, silent = true})
end
This function enables us to map the key
to the result
only in the current buffer we’re working on, the mode
as the name says specify in which mode this key mapping will be enabled. Note that the mappings we’ll do with this function will override the precedent key mappings with the same key.
A custom attach function
The next thing we need is an attach function. This is where we will add all the things we want the LSP client to do when it’s attached a new buffer.
When you open a new buffer for which the language is supported by one of the LSPs you have set up, this function will be called.
local custom_attach = function()
completion.on_attach()
-- Move cursor to the next and previous diagnostic
mapper('n', '<leader>dn', 'vim.lsp.diagnostic.goto_next()')
mapper('n', '<leader>dp', 'vim.lsp.diagnostic.goto_prev()')
end
This attach function is really short, but if you wish you can add more mappings to it, and check the completion-nvim
github to check other capabilities it offers.
Putting the LSP specifics mappings in this function enables them only when the LSP is working, and not in your other buffers, where they could create errors of the LSP is not working.
Adding some LSP configs
Now is the we all have been waiting for, the LSP configs. After you have set all your locals and helper/attach functions.
You should first take a look at the nvim-lspconfig readme, in the CONFIG.md
file you have all the included configurations that the plugin provides.
If you want to add the pyls
(make sure you have. pyls
installed) as an example, you just have to add these lines to your lsp_config.lua
file:
lsp.pyls.setup{
on_attach = custom_attach
}
For most of the configurations provided you only have to add these line, replacing the pyls
by the LSP you wish to use. With the on_attach
key, the custom_attach
function will be called every time you open a new buffer that activates the LSP.
Custom lsp config
I have been using OCaml, and I found out the provided configs didn’t work well for me. Luckily you can add custom configs.
For OCamllsp (you can istall it as explained on the github page) I added this custom config:
local configs = require('lspconfig/configs')configs.ocamllsp = {
default_config = {
cmd = { 'ocamllsp' };
filtypes = {'ocaml'};
root_dir = function(fname)
return lsp.util.find_git_ancestor(fname) or vim.loop.os_homedir()
end;
settings = {};
}
}
Then to activate the config, you just have to add these lines, just as the other LSPs.
lsp.ocamllsp.setup{
on_attach = custom_attach
}
Sourcing your LSP configs
Finally in your init.lua
file you just have to add this line:
require('lsp_config')
Putting it all together
You should now have an lsp_config.lua
file that looks like that:
I hope you found this quick guide useful.
If you are curious about a more complete nvim configuration, you cam look at mine on github. You can find a lot of other configs on GitHub, it is always to check what the others are doing to find some inspirations and help.
You can also check my other Neovim guides: