My Life with NeoVim

Derek Prior

Early this year, my frustrations with Vim reached a boiling point. I was frustrated by slow, synchronous Syntastic checkers that I had come to rely on. I wanted the in-editor feedback the checkers provided but many of those checkers locked up my editor for seconds at a time.

I use Vim and tmux to approximate the feeling of a very light-weight IDE, even moving between the two as if they were the same program. However, tmux is not without it’s issues. My frustrations with Vim made me see that tmux is something I deal with to overcome a shortcoming of my editor rather than a tool I value on its own.

I even started to wonder if those Emacs users among us had it right. I downloaded and installed Spacemacs, probably all while I was waiting on synchronous Vim plugins to complete, and tried to make heads or tails of it all. Emacs quickly proved to be too much of a change and I wasn’t prepared to commit to it.

Enter NeoVim

I then remembered the announcement of NeoVim, a fork of Vim that promised to modernize the plugin architecture, and provide a better out-of-the-box experience for Vim users, including a built in terminal emulator.

I was surprised to find that NeoVim was already reported to be in a very usable state, supporting asynchronous plugins and operating as a drop-in replacement for Vim. I decided to give NeoVim a whirl.

Installing and Configuring NeoVim

NeoVim has packages available for Homebrew, MacPorts, Ubuntu, Debian, Arch, and many other environments. Installing on OS X with Homebrew was a brew install neovim/neovim/neovim away. That’s right, the way to summon NeoVim is to say its name three times. See the installation instructions for details on installing in your environment, but it probably won’t be as much fun as that.

NeoVim does not load your .vimrc file, nor does it use .nvimrc, as I had guessed it might. As a result, none of my configuration was carried over when I launched NeoVim for the first time.

NeoVim supports the XDG Base Directory Specification, which among other things attempts to standardize where user configuration files should live and their order of precedence. With an assist from :help nvim-from-vim, I ran the following commands which allow me to share a configuration between Vim and NeoVim.

mkdir -p ${XDG_CONFIG_HOME:=$HOME/.config}
ln -s ~/.vim $XDG_CONFIG_HOME/nvim
ln -s ~/.vimrc $XDG_CONFIG_HOME/nvim/init.vim

Overcoming Muscle Memory

Years of editing files with the vim command made learning to use nvim a challenge. For all intents and purposes, nvim is Vim for me, so where it is installed, I want to use it all the time. To make this a reality, I added the following alias to my ZSH configuration:

if type nvim > /dev/null 2>&1; then
  alias vim='nvim'

This allows me to continue to use vim on, for example, my home machine where I hadn’t yet installed NeoVim.

Asynchronous Checkers

To my surprise and delight, NeoVim worked well with my configuration, which is based on the thoughtbot dotfiles with my own customizations applied. Unfortunately, Syntastic style checkers were still blocking, just as they were under Vim. Syntastic does not take advantage of the asynchronous architecture exposed by NeoVim.

NeoMake was built from the ground up to perform similar tasks while taking advantage of NeoVim’s asynchronous jobs. I added the plugin to my configuration, but due to the fact that I inherit Sytastic from the thoughtbot dotfiles, I had to get creative to keep them both from running. I configured Syntastic and NeoMake like so:

" Run NeoMake on read and write operations
autocmd! BufReadPost,BufWritePost * Neomake

" Disable inherited syntastic
let g:syntastic_mode_map = {
  \ "mode": "passive",
  \ "active_filetypes": [],
  \ "passive_filetypes": [] }

let g:neomake_serialize = 1
let g:neomake_serialize_abort_on_error = 1

With that configuration loaded, slow checkers no longer locked my editor. While results may take a moment to be reflected in my editor, I’m free to go about my business in NeoVim while the work is done in the background.

NeoMake does not match Syntastic in terms of the sheer number of checkers supported out of the box. New makers, as they are called in NeoMake, are added regularly and can be added via configuration if desired. The languages and tools I most cared about were supported out of the box.

About That Terminal Emulator

You can open a terminal emulator from any NeoVim split with :terminal or :te. I tried to use this in place of tmux for a bit, but found there were enough cases where it didn’t behave as I would like that I went back to tmux within a week. Your experience may vary, though other NeoVim users in the office report that they don’t get much use from :terminal either.

I’d like to dedicate some time to the tmux replacement experiment again in the near future. Most of my terminal use while editing is dedicated to git operations, and I bet I could get that to work mighty nicely with NeoVim.

My Only Workaround

I found that my mapping for CTRL-h did not work from NeoVim when working from tmux. I use this mapping from both Vim and tmux to seamlessly and quickly switch between splits and panes. I worked around this issue with the following in my .vimrc:

nnoremap <silent> <BS> :TmuxNavigateLeft<cr>

The NeoVim FAQ has since been updated with a different workaround that is likely more correct, but I haven’t a clue what it means, so I’ve stuck with my own workaround for the time being.

A Successful Experiment

I’ve been using NeoVim for eight months now without giving it much thought at all beyond the initial configuration. I enjoy that NeoMake gives me asynchronous feedback as I work, but beyond that nothing else has changed about my Vim usage. If you’re not bothered by the things NeoVim purports to fix, then there’s no need to change a thing, but in my case the asynchronous job support was enough to justify the small price of admission.