emacs + scala

For a bit more than a year I have been working mainly with Scala in Emacs. While it's not like working with a LISP, there are a few tweaks that make life a bit easier. I'll describe my setup and the small additions that work for me. There's only very little Emacs Lisp, but you can always find more details on fgeller/emacs.d.

As a caveat, while I used aemoncannon/ensime heavily in the beginning, I rarely switch it on nowadays, mostly due to the overhead with sub projects in SBT. Instead I use other tools to get similar functionality. These tools are not as tightly integrated with Scala, but that also means many are applicable for other scenarios as well. Also, none of this is meant as a reference, but more as pointers – I'm always curious to learn about other techniques :)

Entry point is usually the project root via an alias in eshell to set the default-directory. Then I'll start a SBT session via compile in comint-mode to run tests and drive compilation (e.g., via an alias for (compile "sbt" t) in eshell).

SBT session in compile-mode.

I use magit/magit for getting a basic overview of where I left off or to create a new branch. Then there are multiple options to find a file to edit. Either jump to a specific line in a file with uncommitted changes via the hunk in magit-status, or browse the log and jump via a commit, or browse current files under version control via emacs-helm/helm-ls-git.

magit with log view.

I use hvesalai/scala-mode2 for basic syntax highlighting plus drothlis/pretty-symbols for two more unicode glyphs ;)

Jump to source line from commit.

In the background, there is usually a process running for formatting files via mdr/scalariform that I connect to by adding to the after-save-hook. It's a small fgeller/scalariform-daemon that waits for HTTP requests and formats files in place. This means that I lose undo history but that hasn't been an issue for me. I tried magit's integration with bartman/git-wip, but very rarely used it. Most importantly, it saves time to start up the JVM for each format request and combined with a low value for auto-revert-interval you get quick formats on save.

magnars/expand-region.el and Fuco1/smartparens enable a light version of structured editing, but mostly there is little special configuration for editing Scala code versus general text editing. There are tons of cool resources out there that do a much better job at describing snippets, auto-completion or quick in buffer jumping and more :)

SBT's triggered execution via the tilde operator is usually my main driver during development for red-green-refactor. Using compile-mode to run the SBT session enables jumping to specific lines on compilation or test failure.

Jump to source line from compilation error.

For other navigation I use a combination of tags and basic text search. For tags, I configure Exuberant ctags as a plug-in parser for GNU global. ctags allows me to simply add a basic regex-based configuration for Scala files and global allows for incremental updates on save. I also add other sources to my projects to enable jumping to tags in other libraries or the Scala distribution for reference. helm-gtags allows for convenient selection between multiple candidates by matching on the source line or file name. I also copied helm-gtags functionality for a crude helper to create import statements based on indexed tags.

Jump to symbol definition with helm-gtags.

Finally, for in-buffer search there is the excellent built-in isearch but for text searches across files I use Wilfred/ag.el as a front-end for ggreer/the_silver_searcher. As a bonus, you get easy text changes across files via mhayashi1120/Emacs-wgrep.

Use wgrep to edit lines across files.