nvim-lspconfig
Collection of common configurations for Neovim's built-in language server client. The configurations are supported on a best-effort basis, and rely on contributions from regular users to stay up-to-date.
This repo handles automatically launching, initializing, and configuring language servers that are installed on your system.
Install
-
Requires Neovim HEAD/nightly (v0.5 prerelease). The configs in this repo assume that you are using the latest Neovim HEAD/nightly build. Update Neovim and nvim-lspconfig before reporting an issue.
-
nvim-lspconfig is just a plugin. Install it like any other Vim plugin, e.g. with vim-plug:
:Plug 'neovim/nvim-lspconfig'
Quickstart
- Install a language server, e.g. pyright via
npm i -g pyright
- Install
nvim-lspconfig
via your plugin manager - Add the language server setup to your init.vim. The server name must match those found in the table of contents in CONFIG.md
lua << EOF
require'lspconfig'.pyright.setup{}
EOF
- Open a file that is placed in a directory recognized by the server (see server configuration in CONFIG.md; e.g., for pyright, this is any directory containing ".git", "setup.py", "setup.cfg", "pyproject.toml", or "requirements.txt")
- See Keybindings and completion for mapping useful functions and enabling omnifunc completion
- Try
:LspInfo
to see the status of active and configured language servers.
Usage
All provided examples are in Lua, see :help :lua-heredoc
to use Lua from your init.vim,
or the quickstart above for an example of a lua heredoc.
Each config provides a setup()
function to initialize the server with reasonable default
initialization options and settings, as well as some server-specific commands. This is
invoked in the following form, where <server>
corresponds to the language server name
in CONFIG.md.
setup()
takes optional arguments , each of which overrides the respective
part of the default configuration. The allowed arguments are detailed below.
require'lspconfig'.<server>.setup{<config>}
Example: using the defaults
To use the defaults, just call setup()
with an empty config
parameter.
For the gopls
config, that would be:
require'lspconfig'.gopls.setup{}
Example: override some defaults
To set some config properties at setup()
, specify their keys. For example to
change how the "project root" is found, set the root_dir
key:
local lspconfig = require'lspconfig'
lspconfig.gopls.setup{
root_dir = lspconfig.util.root_pattern('.git');
}
The documentation for each config lists default values and
additional optional properties. For a more complicated example overriding
the name
, log_level
, message_level
, and settings
of texlab:
local lspconfig = require'lspconfig'
lspconfig.texlab.setup{
name = 'texlab_fancy';
log_level = vim.lsp.protocol.MessageType.Log;
message_level = vim.lsp.protocol.MessageType.Log;
settings = {
latex = {
build = {
onSave = true;
}
}
}
}
Example: custom config
To configure a custom/private server, just
- load the lspconfig module:
local lspconfig = require('lspconfig')
, - Define the config:
lspconfig.configs.foo_lsp = { … }
- Call
setup()
:lspconfig.foo_lsp.setup{}
local lspconfig = require'lspconfig'
local configs = require'lspconfig/configs'
-- Check if it's already defined for when reloading this file.
if not lspconfig.foo_lsp then
configs.foo_lsp = {
default_config = {
cmd = {'/home/ashkan/works/3rd/lua-language-server/run.sh'};
filetypes = {'lua'};
root_dir = function(fname)
return lspconfig.util.find_git_ancestor(fname) or vim.loop.os_homedir()
end;
settings = {};
};
}
end
lspconfig.foo_lsp.setup{}
Example: override default config for all servers
If you want to change default configs for all servers, you can override default_config like this.
local lspconfig = require'lspconfig'
lspconfig.util.default_config = vim.tbl_extend(
"force",
lspconfig.util.default_config,
{ log_level = lsp.protocol.MessageType.Warning.Error }
)
Individual server settings and initialization options
See CONFIG.md for documentation and configuration of individual language servers. This document contains installation instructions for each language server, and is auto-generated from the documentation in the lua source. Do not submit PRs modifying CONFIG.md directly; CONFIG.md will be overwritten by docgen
You do not need to copy settings or init_options from this configuration into your config
Keybindings and completion
The following maps most of the standard functions to keybindings, and maps omnicomplete to use
the lsp.omnifunc. See :help lsp
for more details
lua << EOF
local nvim_lsp = require('lspconfig')
local on_attach = function(client, bufnr)
local function buf_set_keymap(...) vim.api.nvim_buf_set_keymap(bufnr, ...) end
local function buf_set_option(...) vim.api.nvim_buf_set_option(bufnr, ...) end
buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')
-- Mappings.
local opts = { noremap=true, silent=true }
buf_set_keymap('n', 'gD', '<Cmd>lua vim.lsp.buf.declaration()<CR>', opts)
buf_set_keymap('n', 'gd', '<Cmd>lua vim.lsp.buf.definition()<CR>', opts)
buf_set_keymap('n', 'K', '<Cmd>lua vim.lsp.buf.hover()<CR>', opts)
buf_set_keymap('n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', opts)
buf_set_keymap('n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
buf_set_keymap('n', '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
buf_set_keymap('n', '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
buf_set_keymap('n', '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
buf_set_keymap('n', '<space>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
buf_set_keymap('n', '<space>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
buf_set_keymap('n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
buf_set_keymap('n', '<space>e', '<cmd>lua vim.lsp.diagnostic.show_line_diagnostics()<CR>', opts)
buf_set_keymap('n', '[d', '<cmd>lua vim.lsp.diagnostic.goto_prev()<CR>', opts)
buf_set_keymap('n', ']d', '<cmd>lua vim.lsp.diagnostic.goto_next()<CR>', opts)
buf_set_keymap('n', '<space>q', '<cmd>lua vim.lsp.diagnostic.set_loclist()<CR>', opts)
-- Set some keybinds conditional on server capabilities
if client.resolved_capabilities.document_formatting then
buf_set_keymap("n", "<space>f", "<cmd>lua vim.lsp.buf.formatting()<CR>", opts)
elseif client.resolved_capabilities.document_range_formatting then
buf_set_keymap("n", "<space>f", "<cmd>lua vim.lsp.buf.range_formatting()<CR>", opts)
end
-- Set autocommands conditional on server_capabilities
if client.resolved_capabilities.document_highlight then
vim.api.nvim_exec([[
hi LspReferenceRead cterm=bold ctermbg=red guibg=LightYellow
hi LspReferenceText cterm=bold ctermbg=red guibg=LightYellow
hi LspReferenceWrite cterm=bold ctermbg=red guibg=LightYellow
augroup lsp_document_highlight
autocmd! * <buffer>
autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()
autocmd CursorMoved <buffer> lua vim.lsp.buf.clear_references()
augroup END
]], false)
end
end
-- Use a loop to conveniently both setup defined servers
-- and map buffer local keybindings when the language server attaches
local servers = { "pyright", "rust_analyzer", "tsserver" }
for _, lsp in ipairs(servers) do
nvim_lsp[lsp].setup { on_attach = on_attach }
end
EOF
The wiki
Please see the wiki for additional topics, including:
- Installing language servers automatically
- Snippets support
- Project local settings
- Recommended plugins for enhanced language server features
and more.
Manually starting (or restarting) language servers
If you would like to manually managing starting language servers, but still have new buffers within a root directory autoattach
to running servers, pass autostart = false
to your .setup{}
call for a language server and call
:lua require('lspconfig').language_server_name.autostart()
.
This function can also be used to restart a workspace after stopping a language server with :lua vim.lsp.stop_client(client_id)
.
setup() function
Only the following arguments can be passed to the setup function:
lspconfig.SERVER.setup{config}
The `config` parameter has the same shape as that of
|vim.lsp.start_client()|, with these additions and changes:
{root_dir}
Required for some servers, optional for others.
Function of the form `function(filename, bufnr)`.
Called on new candidate buffers being attached-to.
Returns either a root_dir or nil.
If a root_dir is returned, then this file will also be attached. You
can optionally use {filetype} to help pre-filter by filetype.
If a root_dir is returned which is unique from any previously returned
root_dir, a new server will be spawned with that root_dir.
If nil is returned, the buffer is skipped.
See |lspconfig.util.search_ancestors()| and the functions which use it:
- |lspconfig.util.root_pattern(pattern1, pattern2...)| is a variadic function which
takes string patterns as arguments, and finds an ancestor
which contains one of the files matching the pattern.
Each pattern can be a specific filename, such as ".git", or a glob.
See `:help glob` for allowed patterns. This is equivalent to
coc.nvim's "rootPatterns"
- Related utilities for common tools:
- |lspconfig.util.find_git_root()|
- |lspconfig.util.find_node_modules_root()|
- |lspconfig.util.find_package_json_root()|
{name}
Defaults to the server's name.
{filetypes}
Set of filetypes to filter for consideration by {root_dir}.
May be empty.
Server may specify a default value.
{autostart}
Whether to automatically start a language server when a matching filetype is detected.
Defaults to true.
{log_level}
controls the level of logs to show from window/logMessage notifications. Defaults to
vim.lsp.protocol.MessageType.Warning instead of
vim.lsp.protocol.MessageType.Log.
{message_level}
controls the level of messages to show from window/showMessage notifications. Defaults to
vim.lsp.protocol.MessageType.Warning instead of
vim.lsp.protocol.MessageType.Log.
{settings}
Map with case-sensitive keys corresponding to `workspace/configuration`
event responses.
We also notify the server *once* on `initialize` with
`workspace/didChangeConfiguration`.
If you change the settings later on, you must emit the notification
with `client.workspace_did_change_configuration({settings})`
Example: `settings = { keyName = { subKey = 1 } }`
{on_attach}
`function(client, bufnr)` Runs the on_attach function from the client's
config if it was defined. Useful for doing buffer-local setup.
{on_new_config}
`function(new_config, new_root_dir)` will be executed after a new configuration has been
created as a result of {root_dir} returning a unique value. You can use this
as an opportunity to further modify the new_config or use it before it is
sent to |vim.lsp.start_client()|. If you set a custom `on_new_config`, ensure that
`new_config.cmd = cmd` is present within the function body.
Debugging
The two most common points of failure are
-
The language server is not installed. You should be able to run the
cmd
defined in each lua module from the command line. -
Not triggering root detection. The language server will only start if it is opened in a directory, or child directory, containing a file which signals the root of the project. Most of the time, this is a
.git
folder, but each server defines the root config in the lua file.
:LspInfo provides a handy overview of your active and configured language servers.
Note, that it will not report any configuration changes applied in on_new_config
.
Before reporting a bug, check your logs and the output of :LspInfo
. Add the
following to your init.vim to enable logging
lua << EOF
vim.lsp.set_log_level("debug")
EOF
Attempt to run the language server, and open the log with:
:lua vim.cmd('e'..vim.lsp.get_log_path())
Most of the time, the reason for failure is present in the logs.
Contributions
If you are missing a language server on the list in CONFIG.md, contributing a new configuration for it would be appreciated. You can follow these steps:
- Read CONTRIBUTING.md.
- Choose a language from the coc.nvim wiki or emacs-lsp.
- Create a new file at
lua/lspconfig/SERVER_NAME.lua
.- Copy an existing config to get started. Most configs are simple. For an extensive example see texlab.lua.
- Ask questions in Neovim Gitter.