Vim / NeoVim
Setup using Coc
The following instructions should enable Erlang language server integration via the Coc system (an intellisense engine for both Vim and Neovim).
Installing Coc with vim-plug
For vim-plug users with nodejs >= 10.12 installed, installing the plugin is just:
" Use release branch (Recommended)
Plug 'neoclide/coc.nvim', {'branch': 'release'}
To make the plugin aware of erlang_ls however, it needs configuration.
Coc plugin configuration
Coc is configured through coc-settings.json
, which can be opened in vim by
issuing the command:
:CocConfig
If erlang_ls
is present in your $PATH
variable then the following config
should suffice:
{
"languageserver": {
"erlang": {
"command": "erlang_ls",
"filetypes": ["erlang"]
}
}
}
When vim starts editing a file of filetype erlang
, if the erlang_ls server
can be started and connected to, you should see something like the following
message from Coc:
[coc.nvim] Erlang LS (in erlang_ls), version: X.Y.Z+build.REF
For suggestions on configuring Coc and possible key-bindings see its example configuration documentation.
Setup for Neovim using the built-in language server client
The following instructions should enable Erlang language server integration using the built-in language server client in Neovim. The nvim-lspconfig plugin is used to configure, launch, and initialize the language server.
Installing nvim-lspconfig
Install using, for example, vim-plug:
Plug 'neovim/nvim-lspconfig'
Enable the language server
Add the following setup call to your init.vim
to make the language server attach
to Erlang files:
lua require'lspconfig'.erlangls.setup{}
Now, when you open an Erlang file you should see a message like this:
LSP[erlangls][Info] Erlang LS (in <your-project>), version: ..., OTP version: ...
Test it by writing some incorrect code. You should see a syntax error message.
Run :LspInfo
to get the status of active and configured language servers.
Configuration
There are no default keybindings for the LSP commands. You can find a good example on how to set these up in the Keybindings and completion section on the nvim-lspconfig plugin page. The idea is to create a function that sets up your keybindings and configuration, which is passed to the setup function in the previous section. This function is then called when the Erlang language server is attached. See the Neovim LSP documentation for more information.
Example
" init.vim
...
lua require'lspconfig'.erlangls.setup{}
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', '<space>ca', '<cmd>lua vim.lsp.buf.code_action()<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)
end
if client.resolved_capabilities.document_range_formatting then
buf_set_keymap("v", "<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=Grey guibg=LightYellow
hi LspReferenceText cterm=bold ctermbg=Grey guibg=LightYellow
hi LspReferenceWrite cterm=bold ctermbg=Grey 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 = { "erlangls" }
for _, lsp in ipairs(servers) do
nvim_lsp[lsp].setup { on_attach = on_attach }
end
EOF
Tips and tricks
Run :h vim.diagnostic.config
inside Neovim for instructions on how to display
diagnostics. :h vim.lsp.codelens.refresh
describes how to show code lenses.