6.3 KiB
+++ title = "Language Server Protocols in Vim" date = 2020-09-16 tags = ["vim"] +++ Language Server Protocol aka LSP is an open source initiative of ... Microsoft. Each "language server" defines every detail of a programming language's syntax and grammar, like its keywords, and how you put them together. This knowledge base is in turn used by editor helpers who can for instance lint your code or suggest completion, a field of features labeled "Intellisense".
Since Vim 8, programmers may run asynchronous code in vimscript. This feature is leveraged in some plugins that use LSP to lint or suggest while you type. Let's name vim-lsp, coc.vim and vim-ale.
Vim plugins on your own
It is worth noting that coc.vim provides a language server installer (vim-lsp
also has vim-lsp-settings
that should do the job, although I was not able to
run it on my system). It is very likely that your operating system chips some,
at least if it's a linux. But if you already have Vim running on your OS, it
should be quite simple to use one of the formers with a plugin manager. If you
don't have any plugin manager, be advised that Vim 8 ships its own plugin system
; you just need to unpack the plugin's main directory in
~/.vim/pack/PACK_NAME/start/
. PACK_NAME
can be anything you want, and its
subdirectory start
can be filled with as many plugins as you please. In this
case, you could do for instance :
$ mkdir -p ~/.vim/pack/LSP/start
$ cd ~/.vim/pack/LSP/start
$ git clone https://github.com/neoclide/coc.nvim
And that's it ! (If you don't have git neither a terminal but still have Vim,
you can still go at coc.vim and manually unpack the latest version's
tarball you Vim's config dir - pack
should lie next to ftplugin
et al).
Vim plugins in your package manager
You might prefer to use your system's package manager to install plugins, so that they get upgraded with the rest of the system. In this case you could do for instance in Arch linux :
# pacman -S vim-ale
Once properly set up, vim-ale will lint the file you are editing in the
background (using Vim 8 async processes). It will send all errors and warnings
found while you type to the location window, a temporary "subwindow" that you
can check back with :lw
. See :help location-list-window
to get more info on
this feature. You can jump to the last diagnosed error with :ll
, and navigate
with :lla
and :lne
.
The nice bonus is the completion option. It lists all matching expressions with
what you began typing, and as you scroll the list, Vim's preview-window
pops
up and gives a description of whatever you are coding - objects in python,
functions in bash, etc.
I'm afraid vim-ale on its own doesn't know much about any language at all. You will have to feed it with a knowledge provider for each of the languages you care for. See the next chapter about this.
Meanwhile, I tweaked vim-ale to populate Vim's default completion sequence,
remap completion shortcuts, and let the preview window be opened at the bottom
with the following content into ~/.vim/plugin/ale.vim
:
" vim-ale settings
" Enable ale completion where available.
" This setting must be set before ALE is loaded.
let g:ale_completion_enabled = 1
let g:ale_completion_autoimport = 1
" Lets ctrl-x ctrl-o open ale completion
set omnifunc=ale#completion#OmniFunc
" Remap tab, shift-tab and enter to useful completion shortcuts when
" completion already began :
inoremap <expr> <Tab> pumvisible() ? "\<C-n>" : "\<Tab>"
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
inoremap <expr> <cr> pumvisible() ? "\<C-y>" : "\<cr>"
" Let preview window open on the bottom (J)
augroup previewWindowPosition
au!
autocmd BufWinEnter * call PreviewWindowPosition()
augroup END
function! PreviewWindowPosition()
if &previewwindow
wincmd J
endif
endfunction
Installing language servers
You could install your favourite language's language server. For example under Arch :
# pacman -S bash-language-server
And then let Vim know about it. Create ~/.vim/plugin/language-servers.vim
and
paste :
" Support for bash
if executable('bash-language-server')
augroup LspBash
autocmd!
autocmd User lsp_setup call lsp#register_server({
\ 'name': 'bash-language-server',
\ 'cmd': {server_info->[&shell, &shellcmdflag, 'bash-language-server start']},
\ 'allowlist': ['sh'],
\ })
augroup END
endif
Arch users also get python, C/C++ (in the ccls
package), and LaTeX language
servers in community. I also found rls-git
for Rust language server, HTML from
Microsoft's VSCode, and javascript with typescript-language-server-bin
in the
AUR.
vim-lsp maintains a list of usual Vim LSP support scripts on its wiki. Once you've picked up your choice and installed it it's mostly a matter of copy and paste.
Well, all this sounded quite systematic ! But ... vim-ale also maintains a list of working linters here. And it turns out that before language servers, there was quite a bunch of linters doing the job all right. And vim-ale is able to run those "traditional" linters while you type. And they allow completion while you type. They also bear a smaller footprint. This discussion could go more into the details of each language support, but finally why go for the big overhead of this open source infrastructure ?
I ended up replacing language servers as follows :
language | LSP implementation | linter |
---|---|---|
bash | bash-language-server |
shellcheck |
C/C++ | ? | ccls |
css | vscode-css-languageserver-bin |
prettier |
javascript | typescript-language-server-bin |
typescript 's tsserver |
json | vscode-json-language-server |
prettier |
html | vscode-html-languageserver-bin |
htmlhint |
markdown | ? | mdl |
python | python-language-server |
autopep8 |
vala | vala-language-server |
uncrustify |
vimscript | vim-language-server |
vint |