47 Degrees joins forces with Xebia read more

Scala development with GNU Emacs

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

Emacs Splash

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.

You can download the latest copy from a mirror: https://ftpmirror.gnu.org/emacs/. If you use Mac OS X: https://emacsformacosx.com/

Prelude

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:

(require 'prelude-scala)

ENSIME

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
  • Refactoring
  • 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-refresh-contents 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.

Edit ~/.sbt/1.0/plugins/plugins.sbt with:

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 ~/.sbt/1.0/plugins/build.sbt:

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

Run it

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 *inferior-ensime-server* buffer.

If you see errors, you may need to compile your project. You can do that in the console with sbt compile test:compile

Discovering ENSIME

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 (link no longer active).

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 . or SPACE and then pressing TAB.

This action will show a “popup” menu that you can navigate with arrow keys UP and DOWN, or search inside them with C-s.

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 ENTER

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 (Link no longer active) 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.

SBT support

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.

Other perks

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.

Magit

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.

As always, get in touch with us on Facebook, Twitter, or the comments below if you have any further questions.

References:

https://ensime.github.io/editors/emacs/ (Link no longer active.)

Ensure the success of your project

47 Degrees can work with you to help manage the risks of technology evolution, develop a team of top-tier engaged developers, improve productivity, lower maintenance cost, increase hardware utilization, and improve product quality; all while using the best technologies.