+++ 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][vim-lsp], [coc.vim][coc.vim] and [vim-ale][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][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](http://archlinux.org) : ``` # 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` : ``` vimscript " 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 pumvisible() ? "\" : "\" inoremap pumvisible() ? "\" : "\" inoremap pumvisible() ? "\" : "\" " 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 : ``` vimscript " 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][vim-lsp-support]. 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][vim-ale-linters]. 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` | [vim-ale]: https://github.com/dense-analysis/ale [vim-ale-linters]: https://github.com/dense-analysis/ale/blob/master/supported-tools.md [vim-lsp]: https://github.com/prabirshrestha/vim-lsp [vim-lsp-support]: https://github.com/prabirshrestha/vim-lsp/wiki/Servers [coc.vim]: https://github.com/neoclide/coc.nvim