Scala development with GNU Emacs
In this article, we’ll take a look at some features that that allow you to integrate Scala development in Emacs into your workflow.
If you’re anything like me, you have been trying another IDE to see if there is anything better out there. Some other IDEs you can use include Sublime Text, Eclipse, or IntelliJ. I liked what I found, but for now I’d like to return to Emacs and see how can I work within it. This post will be the first in a series in which we’ll be sharing our experience and discoveries.
Fasten your seatbelt, let’s do this.
GNU Emacs has a long history as an editor and environment used for development for a few decades. It started as a set of of macros written in 1976 at MIT by Richard M. Stallman for the TECO editor under ITS (Incompatible Timesharing System) on a PDP-10 machine
Emacs is a really extensible, customizable editor thanks to extensions written in Emacs Lisp.
These days, Emacs it’s a project that is part of the GNU Operating System.
Many Emacs users personalise their environment with their favorite extensions and customisations. To ease the process of adopting Emacs, we suggest installing Prelude because it bundles many modes and packages. Prelude works for GNU Emacs 24.x. Be sure to update your Emacs version if necessary.
To know more about Prelude, installation options, and updating, see Prelude Installation. If you want a quick summary, just do this to install Prelude:
$ curl -L https://github.com/bbatsov/prelude/raw/master/utils/installer.sh | sh
After installing Prelude, edit prelude-modules.el and uncomment the line:
ENSIME is Enhanced Scala Interaction Mode for Emacs. If you are new to Emacs you’ll need to know that a mode defines the editing behavior when working, let’s say, with a file. ENSIME provides us with the features found in modern IDEs like the ones mentioned above. ENSIME is created with a client-server architecture so it can be used by other editors.
These are among its cool features:
- Syntax highlighting
- Auto indentation
- Semantic completion of symbols
- Element inspector and searching for symbol definitions
Installing Ensime Mode inside Emacs
For detailed instructions, check out the Ensime Installation for Emacs. Please refer to them in case you want to know more, but we’ll give you a brief summary.
We recommend installing Emacs through the ELPA (Emacs Lisp Package Archive). ELPA allows the automatic installation and management of packages through Emacs.
Add this to your init.el file:
(require 'package) (add-to-list 'package-archives '("melpa" . "https://melpa.milkbox.net/packages/") t) ;;We have "sbt" and "scala" in /usr/local/bin so we add this path to the PATH environment (setq exec-path (append exec-path '("/usr/local/bin"))) (setq exec-path (append exec-path '("/usr/local/sbin"))) (setenv "PATH" (shell-command-to-string "/bin/bash -c 'echo -n $PATH'")) (require 'ensime) (add-hook 'scala-mode-hook 'ensime-scala-mode-hook)
Restart Emacs and do
M-x package-install [ENTER] ensime [ENTER]
To keep up-to-date, do
M-x list-packages [ENTER] U x [ENTER]
Installing ENSIME sbt-plugin
We need to generate a config file for our project. To do that, first we need to install the ensime-sbt plugin first.
addSbtPlugin("org.ensime" % "sbt-ensime" % "2.1.0")
Check the latest version number for ensime-sbt at: https://ensime.org/build_tools/sbt/
Add this to your
addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC13")
Generating the ENSIME file
The server part of ENSIME needs to generate an .ensime file. We need to generate this before starting ENSIME for our project.
We can generate the file by entering the directory and generating the ENSIME file automatically.
cd ~/development/our-project sbt ensimeConfig
OK, we are ready! From now on, when we work in our Scala project, we just start the session running
M-x ensime inside Emacs. It will ask for our ENSIME project file. In our example:
~/development/our-project/.ensime. We hit ENTER and we are ready to go.
This will update the .ensime file if necessary and then we’ll see some messages, wait until it says it’s ready.
Ensime server starting Connecting to swank ENSIME ready. Juan, this could be the start of a beautiful program.
If you want to review what ENSIME is doing in the background, you can read the messages in the
If you see errors, you may need to compile your project. You can do that in the console with
sbt compile test:compile
Format your file
This is called Source Formatting in the documentation. You can automatically format your visited file with
C-c C-v f. It uses the Scalariform library to format your Scala file. To see more about editing, go to Ensime Editing
Symbol and Member Completion
When you’ve written a couple of characters of code, you can autocomplete the symbol by pressing the
TAB key. As the current documentation asserts, this currently works for local variables, method parameters, unqualified method names and type names. You can also complete a type member after typing
SPACE and then pressing
This action will show a “popup” menu that you can navigate with arrow keys
DOWN, or search inside them with
Navigating to symbol definitions
Now, it’s time to review some of the cool stuff you can do. Imagine we are using some method and we want to know more about its implementation and parameters that it needs.
We can do
C-c C-v v. This will open two new buffers: one for typing, and one for displaying the results of the search: The definitions. After typing the method we are looking for, we can navigate to the implementation directly by putting the cursor over one of the results and pressing
Also, when you are over a symbol, you can type
C-u M-. to jump to the definition of the type.
Refactoring - Renaming
When we put the cursor over a symbol we want to rename, we may do
C-c C-r r and answer to the prompt to rename the symbol and all the uses of that symbol in the file.
Although this is useful, it’s not quite as powerful as the Refactor Rename from IntelliJ where the renamed symbol is inferred by type while it’s changed in all files across the project.
ENSIME is a work in a progress and we look forward to see their improvements.
We recommend you read the Edit-Compile-Workflow tips on the ENSIME documentation.
A workaround for this could be starting with “Find usage of symbol at point” (C-c C-v r), and then “Refactor/Rename” (C-c C-r r).
Refactoring - Organizing imports
Imports can be simplified sometimes by compressing them into one package. You can do a
C-c C-r o. ENSIME will suggest changes that you can confirm or cancel.
You can launch a SBT child process with
C-c C-b s to be executed on an Emacs buffer. There are shortcuts for other commands, too. I’m not a fan of learning too many shortcuts in one study session, but when I’m using a package more and more, I review the documentation to start using new ones that can improve my workflow.
Here are some that Emacs and SBT users will like:
C-c C-b c to compile,
C-c C-b r to run,
C-c C-b n to issue a clean and
C-c C-b p to do a package.
The ways you can configure Emacs and the number of packages to personalize it are so numerous that we would need to write several books to describe them.
Here are some features that I found cool in other IDEs that are very easy to find in Emacs too.
Mark characters that reaches maximum column bound
(setq whitespace-line-column 121)
With this command, all the characters in a line that are over column 121 will be marked in another color.
Changed lines from previous GIT commit while editing
If you installed Prelude, this package comes configured with diff-hl-mode, which allows you to see on a quick look what lines from our file has been changed from the previous commit. diff-hl-mode works with Git, Mercurial, SVN, Bazaar, etc.
Added lines will appear marked with a green section on the left column.
If you work in a git-backed directory, Magit is a wonderful tool. I saw the power a skilled Magit user can hold and I was amazed—I can’t help but recommend it.
Minor modes used while editing
You may be curious about the Major and Minor modes I work on while editing a Scala file. You can see yours with
M-x describe-mode. This will list the major and minor modes that applies for the file we are working on.
Enabled minor modes: Anzu Async-Bytecomp-Package Auto-Composition Auto-Compression Auto-Encryption Column-Number Company Delete-Selection Diff-Auto-Refine Diff-Hl Electric-Indent Ensime File-Name-Shadow Flx-Ido Flycheck Flyspell Font-Lock Global-Anzu Global-Auto-Revert Global-Company Global-Diff-Hl Global-Flycheck Global-Font-Lock Global-Hl-Line Global-Undo-Tree Guru Ido-Ubiquitous Line-Number Menu-Bar Mouse-Wheel Prelude Prelude-Global Projectile Projectile-Global Recentf Savehist Shell-Dirtrack Show-Smartparens Show-Smartparens-Global Size-Indication Smartparens Subword Tex-Pdf Tooltip Transient-Mark Undo-Tree Volatile-Highlights Which-Function Whitespace Winner Yas (Information about these minor modes follows the major mode info.) Scala mode defined in 'scala-mode2.el': Major mode for editing scala code.
Final words for the first steps
When using Emacs, ENSIME, Magit, it’s true that are a lot of packages and there’s a lot to grok if you are new to this environment. As I continue learning and integrating this into my daily workflow, I’ll be taking notes and sharing my discoveries and practices in our upcoming posts in the series.