Even though it hurts my brain a little bit, learning Scala has been a pleasurable part of my job lately. It definitely isn’t for the faint-hearted but it has taught me a lot about thinking precisely about the topics of immutability and shared state. The functional mindset forces you to think mainly about input and output of functions and this training, I feel, makes me a better programmer even when programming in a language other than Scala.

Tools

I’m not really an IDE lover, quite the opposite, but I have started taking a shine to the comforts that Intelli-J is offering when writing Java.

I was happy to see that Intelli-J has a plugin for Scala development and have been using that for the last couple of months. Sadly, the plugin is really, really slow which makes it pretty unusable to me.

There is no question that the language is beautiful but the tools aren’t.

Enter vim

I’m already using vim for everything other than Java so I hunted around the web in order to find plugins. I’ve been quite satisfied with the following combination.

###vim-scala Obviously, you will need syntax highlighting and this plugin provides that.

###neocomplcache

The built-in vim autocomplete isn’t great for Scala but the neocomplcache plugin makes typing out long Scala class or package names easier. There is no semantic analysis behind it so all this plugin does is string matching but I was very surprised to realise that this takes you a long way. To me at least it is adequate.

ctags

In order to enable jump-to-source navigation you need to configure ctags to index scala files. You can do that by adding the following to your ~/.ctags:

--langdef=scala
--langmap=scala:.scala
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy)[ \t]*)*(private[^ ]*|protected)?[ \t]*class[ \t]+([a-zA-Z0-9_]+)/\4/c,classes/
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy)[ \t]*)*(private[^ ]*|protected)?[ \t]*object[ \t]+([a-zA-Z0-9_]+)/\4/c,objects/
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy)[ \t]*)*(private[^ ]*|protected)?[ \t]*((abstract|final|sealed|implicit|lazy)[ \t]*)*case class[ \t]+([a-zA-Z0-9_]+)/\6/c,case classes/
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy)[ \t]*)*(private[^ ]*|protected)?[ \t]*case object[ \t]+([a-zA-Z0-9_]+)/\4/c,case objects/
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy)[ \t]*)*(private[^ ]*|protected)?[ \t]*trait[ \t]+([a-zA-Z0-9_]+)/\4/t,traits/
--regex-scala=/^[ \t]*type[ \t]+([a-zA-Z0-9_]+)/\1/T,types/
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy|private[^ ]*(\[[a-z]*\])*|protected)[ \t]*)*def[ \t]+([a-zA-Z0-9_]+)/\4/m,methods/
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy|private[^ ]*|protected)[ \t]*)*val[ \t]+([a-zA-Z0-9_]+)/\3/l,constants/
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy|private[^ ]*|protected)[ \t]*)*var[ \t]+([a-zA-Z0-9_]+)/\3/l,variables/
--regex-scala=/^[ \t]*package[ \t]+([a-zA-Z0-9_.]+)/\1/p,packages/

After having done that you need to run ctags from the root of your project directory with something like this:

ctags -R . --exclude=target --exclude=vendor

By default vim will only look for the tags file in the directory of the file open in the current buffer. If you want vim do move up the directory hierarchy until it has found the file add this to your ~/.vimrc:

set tags=tags;/

Now, if you move the cursor over a type name and press Ctrl-] you will jump to the definition of the type. That’s pretty nifty!

If you want to go back to where you were before the jump press Ctrl-T.

Sorting of imports

Based on feedback from a collegue who was complaining that my imports always look messy I have contributed a command to the vim-scala plugin which automatically sorts your import statements.

You can invoke the command with :SortScalaImports and there are two modes on how your imports could be sorted. By default the command goes through the import groups (which are defined as separated by a newline) and orders them alphabetically. This is useful for when you prefer to sort your import into groups yourself like this:

// Utility imports
import com.me
import com.them

// Concurrency imports
import akka....
import scala...
import java...
import spray....

// Domain imports
import com.me.data....
import com.me.data....

The second mode can be enabled by setting the following in your .vimrc:

let g:scala_sort_across_groups=1

This will take all of your imports and puts them into 3 different groups:

  1. Java/Scala core libraries
  2. 3rd party libraries
  3. First party code, a.k.a your own

What is considered first party code can be configured by setting the a regex. I have set it to this, which is for a standard Play app:

let g:scala_first_party_namespaces='\(controllers\|views\|models\|util\|de.\)'

The result of the sort looks like this:

import java.text.SimpleDateFormat
import java.util.{ Currency, Locale, UUID, Calendar }
import scala.collection.JavaConversions._
import scala.util.Random

import play.api._
import play.api.mvc._

import controllers.Secured._
import de.mycompany.useful.library.Class
import util._