Need a hand with tech consulting? I can help!
Learn more about how we can work via black.af .

Using Language Servers within NeoVim

NeoVim with Language Server makes for an interesting experience.

:pencil: by Jacky Alciné Jacky Alciné :book: an guide post :bookmark: vim , neovim , editor :clock7: written :eyeglasses: about 4 minutes, 734 words :link: Comments - 2 Mention(s) - Permalink

As noticed a lot, I’m a big user of NeoVim. I use to write my journal entries, notes or anything that I can capture into text and save to my local file system.

Recently, I shared a link with a friend who wanted to get TypeScript support with LanguageServer1 in Neovim. However, the post made quite a few assumptions that, quite frankly, wasn’t the most helpful given the landscape for documentation for Vim plugin tooling. This post aims to make that setup process a lot simpler for you. If you have any questions; feel free to leave them in the comments (or better yet, send a WebMention).

At the time of writing, I’m working of the SHAs of the following projects:

Getting Started

I’ll need you to install a particular plugin that I personally use to get completion support popping in NeoVim. It’s named ncm2. It’s still rough around the edges but it does get the job done really well for my use cases. Check out its VimAwesome page for installation instructions for your particular plugin manager. I use vim-plug so it’ll look like this:

" A dependency of 'ncm2'.
Plug 'roxma/nvim-yarp'

" v2 of the nvim-completion-manager.
Plug 'ncm2/ncm2'

" LanguageServer client for NeoVim.
Plug 'autozimu/LanguageClient-neovim', {
  \ 'branch': 'next',
  \ 'do': 'bash install.sh',
  \ }

Easy! Save your options, install, refresh or what have you. Since I use vim-plug, after re-sourcing my setup, I’d run :PlugInstall. Once you’ve installed the plugins, be sure to run :UpdateRemotePlugins as well.

Configuring the Completion Tool

So ncm2 isn’t all listening. It has a method ncm2#enable_for_buffer. For the sake of this demo, I’ll go with the suggested (aggressive) approach of enabling it in any buffer:

autocmd BufEnter  *  call ncm2#enable_for_buffer()

I don’t feel immediately comfortable with this but the source shows it not being as wild as I feared it to be. Next, setting up some options to expand the in-built completion support NeoVim has:

" Affects the visual representation of what happens after you hit <C-x><C-o>
" https://neovim.io/doc/user/insert.html#i_CTRL-X_CTRL-O
" https://neovim.io/doc/user/options.html#'completeopt'
" This will show the popup menu even if there's only one match (menuone),
" prevent automatic selection (noselect) and prevent automatic text injection
" into the current line (noinsert).
set completeopt=noinsert,menuone,noselect

There’s a few more things we can do here with ncm2. Gettings things like [buffer symbol completion][7], snippet support and even Jedi support could be done. That’s outside of the scope of this particular post, however.

Connecting the Language Servers

Before we continue, I just want to note that because of how Language Server works, you’ll have to first install the respective server on your machine to a path that NeoVim is aware of (from $PATH or within its rtp) and then update some configuration. Because it’s not an IDE. That’s how it works in Vim land.

To test out the support of this, we’ll install the TypeScript language server to our machines. Running the following should get that working:

# I pinned a version here so it matches what I ran when I wrote this blog.
$ npm install --global javascript-typescript-langserver@2.9.4

And now in your Vim configuration:

let g:LanguageClient_serverCommands = {
  \ 'typescript': ['javascript-typescript-stdio']
  \ }

Nice. Now if we open a new TypeScript file…

Voilà! I use this every day in larger projects like twch.at and client work and it’s really great. Adding more support for other languages is as simple as looking for the corresponding language server and adding it to the dictionary in your Vim configuration above.

  1. They wrote about it - a nice read