Vim as a Scala IDE

I’ve been using VIM as my Scala IDE for the last year and I can report I’ve had a very positive experience with it. Below I have a short table of what IDE features I use and what plugins offer those features. Before you read that stuff however you need to align your perceptions and expectations with mine. I’ve used vim to write Python and Perl every workday for 8 years. I have put forth considerable effort to make vim work for me as a Scala IDE. It didn’t happen overnight. Python and Perl are weakly-typed. Many IDEs simply can’t offer “Jump to definition” in Perl code accurately as there’s no strict rules on where `$obj->$method` would even go without evaluating the program at runtime. My expectations for a productive environment are probably far less than those coming from IntelliJ or Visual Studio would hope for. You have been warned.

Compared to Python and Perl, Scala has a complicated type system, Futures, functional style and hidden implicits. All of this makes learning Scala quite a challenge. Using a full IDE such as IntelliJ (which I did for my first six months) is the best way to learn and get productive in Scala. Out of the box there’s solid sbt integration, compiler errors and feedback, type deduction, auto-completion and way more than I’m even attempting to make available to VIM.

I’ll iterate this once more for clarity: I use and recommend vim as a Scala IDE if you’re a vim expert who wishes to continue using vim in your workflow. I do not advocate it as better or more suitable than other editors, especially to those that don’t use vim.

My motivation for writing post was because I spent days trying to set up ensime-vim a year ago and it was a bit of disaster. Many of you may also have had the same bad experience. Since then I’ve tried again and been more successful. This post is to give those interested in using Scala and Vim together a refresher in what’s possible on the modern version and if it’s worth investing a couple days into getting yourself setup. For vim lovers, the answer is yes, definitely.

This table lists features, how important I feel there are, which plugin offers the feature and notes on it’s implementation:

IDE FeaturePriorityFeature available in VIMPlugin requiredNotes
Syntax HighlightingEssentialYesvim-scalaDoes accurate Scala highlighting but not as good as intellij. Doesn't interpolate strings correctly
Poor-mans Jump to DefinitionEssentialYesctagsAvailable via ctags. Pretty poor experience
Accurate Jump to DefinitionEssentialYesensime-vim:EnDeclaration
Rename symbolNice to haveYesensime-vim, vim-multiple-cursors:EnRename or using the vim multiple cursors plugin
Automatically add ImportsEssentialYesensime-vim:EnSuggestImport offers completion from real viable imports your project includes
Show symbol’s typeEssentialYesensime-vim:EnType works as well as intelliJ's add declaration feature. Very impressive
Show/highlight compilation errorsNice to haveYesensime-vim:EnTypeCheck marks characters as read and putting your cursor over shows the errors. Personally I just run sbt in a separate console however.
Autocomplete (as you type)Nice to haveYesomni-completeIn insert mode type Ctrl+X, Ctrl+0. I rarely use this feature but it does work with correct types etc. Very impressive.
Project browserNice to haveYesNerdtreeBrowsing and opening files in vim is something you'd want to do using your normal vim skills
Quick Jump to fileNice to haveYesctrlp.vimA general vim plugin autocompletes filenames as you type but vim file management tools just as effective.
Integrated debuggerNice to haveSupposedly but Unproven / Untestedensime-vimThere's a host of :EnDebug commands that I haven't explored.
Show references / usageEssentialYesack.vimI use :Ack or :Act! (over some symbol) to find references to it. This isn't a Scala specific thing.
Git integrationNice to haveYesvim-fugitiveThere's a whole host of features here. This plug in isn't Scala specfic. I only use :Gblame to find information on lines of code.

The plugins referenced above can be found here:

General Guide to Installing Ensime-vim

The first and most annoying blocker. Ensime requires your copy of vim to be compiled with +python support. You may need to hunt down the correct version in your distro’s package manager. Debian and others recently switched +python3 support which makes finding a compatible vim a little harder. I had to personally recompile vim from source to enable the feature. You can use the command to find out if you have +python support:

vim --version

Installing plugins in VIM is not simple, unless you’re using the pathogen plugin to manage this process. Get pathogen here. After this, other plugins can be installed by just “git cloning” them into your ~/.vim/bundles directory.

First, put this into ~/.sbt/0.13/global.sbt

import org.ensime.EnsimeCoursierKeys._
import org.ensime.EnsimeKeys._

ensimeIgnoreMissingDirectories := true
ensimeIgnoreSourcesInBase := true

Add this to ~/.sbt/0.13/plugins/plugins.sbt

addSbtPlugin("org.ensime" % "sbt-ensime" % "1.12.8")

Then in your Scala project’s root directory (where sbt or activator should be) run this to build the symbols for ensime:

sbt compile ensimeConfig ensimeConfigProject

Then you’re set and ready to go! You’ll need to do this for each project. After that, when you open Scala files in vim you should be greeted with the reassuring message in vim’s promt:

[ensime] Analyzer is ready

Now you’re ready the try out the commands in the table. In some scenarios I’ve had to manually run the command :EnClasspath but generally this shouldn’t be required.

Fixing issues

If Ensime crashes or won’t start, delete all of these directories and try again:

~/.config/ensime-vim/
~/.ivy2/
~/.coursair/
.ensime_cache
.ensime

Errors are reported at the path below and can help you debug and fix some of the issues.

.ensime_cache/server.log

Be aware that sometimes Ensime won’t work if your application doesn’t cleanly compile because your code already contains compiler errors.

Good luck and have fun!