Skip to content

hvesalai/emacs-scala-mode

Repository files navigation

emacs-scala-mode

The mode intends to provide basic emacs support for the Scala language, including:

  • local indenting of code, comments and multi-line strings
  • motion commands
  • highlighting

See also emacs-sbt-mode.

Installation

The preferred mechanism is via MELPA and use-package as per our Learning Emacs guide:

(use-package scala-mode
  :interpreter
    ("scala" . scala-mode))

Multi-line comments

The start of a multi-line comment is indented to the same level with code.

By default, if a multi-line comment begins with /* it is considered to be a Scaladoc comment. Scaladoc comments are indented according to the Scaladoc style guide.

/** This is a Scaladoc comment.
  * 2nd line.
  */

Alternatively, if the configurable variable scala-indent:use-javadoc-style is set to t, multi-line comments beginning with /** will be indented according to the Javadoc style, wherein all following lines are indented under the first asterisk.

/**
 * This is a Javadoc-style comment.
 * 2nd line.
 */

All other multi-line comments are indented under the first asterisk.

/**
 * Supercalifragilistic-
 * expialidocious!
 */

/*
 A comment
 */

Typing an asterisk in multi-line comment region, at the start of a line, will trigger indent. Furthermore, if the configurable variable scala-indent:add-space-for-scaladoc-asterisk is t (default) and the asterisk was the last character on the line, a space will be inserted after it. If you type a forward slash after the automatically inserted space, the space is deleted again so that you can end the comment without deleting the space manually.

Filling (i.e. word wrap)

Paragraph filling is supported for comments and multi-line strings. Auto-fill is not supported yet.

To re-fill a paragraph, use the fill-paragraph command ( M-q ). As always, the column at which to wrap is controlled by the fill-column variable, which you set it with the set-fill-column command. To set the default, you use the customize-variable command or a mode-hook.

Motion

Emacs commands forward-sexp and backward-sexp ( M-C-f, M-C-b ) motion commands will move over reserved words, literals, ids and lists.

Text paragraph motion (i.e. forward-paragraph, backward-paragraph) works inside comments and multi-line strings, and it respect Scaladoc's wiki-style markup.

scala-syntax:beginning-of-definition and scala-syntax:end-of-definition move the cursor forward and backward over class, trait, object, def, val, var, and type definitions. These functions are assigned to the buffer local variables beginning-of-defun-function and end-of-defun-function which makes it so that the beginning-of-defun and end-of-defun functions behave in a way that is appropriate to scala. These functions are not currently able to support some of the more advanced scala definition types.

Highlighting

The highlighting of variable definitions, such as

var test = "some mutable variable"

now result in the variable name ("test" above) to be highlighted using the variable scala-font-lock:var-face. Per default, the value of scala-font-lock:var-face is 'font-lock-warning-face. You can always change the highlighting of vars by changing scala-font-lock:var-face through the Emacs face customization (use M-x customize-face).

Very complex scala files may need the following in your emacs init (.emacs, etc):

;; For complex scala files
(setq max-lisp-eval-depth 50000)
(setq max-specpdl-size 5000)

imenu

scala-mode supports imenu, a library for accessing locations in documents that is included in emacs 24. The custom variable scala-imenu:should-flatten-index controls whether or not the imenu index will be hierarchical or completely flat. The current iMenu implementation only goes one level deep i.e. nested classes are not traversed. scala-mode's imenu support depends heavily on the scala-syntax:end-of-definition and scala-syntax:beginning-of-definition functions, and as such, it shares their limitations.

Joining lines (delete indentation) and removing horizontal whitespace

Scala-mode defines its own scala-indent:join-line and scala-indent:fixup-whitespace functions.

Unlike the normal join-line (aka delete-indentation), scala-indent:join-line detects the comment fill-prefix and removes it.

The scala-indent:fixup-whitespace first removes all horizontal whitespace, then adds one space the context requires none to be present (before semicolon, around dot, after ( or [, before ) or ], etc).

Indenting

Where four developers meet, there are four opinions on how code should be indented.

scala-mode supports 2^4 different ways of applying local heuristics to indentation.

Note that when using sbt-scalariform, your local indentation rules will be overwritten.

Run-on lines

Provided by scala-indent:default-run-on-strategy

The indenting engine has three modes for handling run-on lines. The reluctant (default) mode is geared toward a general style of coding and the eager for strictly functional style. A third mode called operators is between the two.

The difference between the modes is how they treat run-on lines. For example, the eager mode will indent map in the following code

val x = List(1, 2, 3)
 map(x => x + 1)

The operators and eager modes will indent the second row in the following code, as the first line ends with an operator character.

val x = 20 +
  21

The reluctant mode (default) will not indent the line in either case. However, all three modes will indent the second line in these examples as it is clear that the first line cannot terminate a statement.

val x = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9).
  map (x => x + 1) // last token of previous line cannot terminate a statement

val y = (List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
           map (x => x + 1)) // inside 'newlines disabled' region

You can use empty lines in the eager mode to stop it from indenting a line. For example

val x = foo("bar")
           ("zot", "kala") // indented as curry

val y = foo("bar")

("zot", "kala") // a tuple

However, in all three modes pressing the tab key repeatedly on a line will toggle between the modes.

Value expressions

Provided by scala-indent:indent-value-expression

When this variable is set to nil (default), body of a value expressions will be indented in the traditional way.

val x = try {
  some()
} catch {
  case e => other
} finally {
  clean-up()
}

However, when the variable is set to t, the body will be indented one extra step to make the val, var or def stand out. For example:

val x = try {
    some()
  } catch {
    case e => other
  } finally {
    clean-up()
  }

Parameter lists

Provided by scala-indent:align-parameters

When this variable is set to nil (default), parameters and run-on lines in parameter lists will not align under or according to the first parameter.

val y = List( "Alpha", "Bravo",
  "Charlie" )

val x = equals(List(1,2,3) map (x =>
  x + 1))

When the variable is set to t, the same will be indented as:

val y = List( "Alpha", "Bravo",
              "Charlie" )

val x = equals(List(1,2,3) map (x =>
                 x + 1))

Expression forms: if, for, try

Provided by scala-indent:align-forms

When this variable is set to nil (default), if, for and try forms are not aligned specially.

val x = if (kala)
  foo
else if (koira)
  bar
else
  zot

val x = try "1".toInt
catch { case e => 0}
finally { println("hello") }

val xs = for (i <- 1 to 10)
yield i

When the variable is set to t, the same will be indented as:

val x = if (kala)
          foo
        else if (koira)
          bar
        else
          zot

val x = try "1".toInt
        catch { case e => 0}
        finally { println("hello") }

val xs = for (i <- 1 to 10)
         yield i

Prettify-Symbols

Scala-mode has a preconfigured list of prettify-symbols rules. The prettify-symbols-mode minor-mode (included with emacs from version 24.4 onwards) displays text in your buffer as (usually) unicode symbols that express the same thing to improve readability. A good example would be displaying the boolean operators as their unicode equivalents.

To enable the feature just add these lines to the scala-mode-hook:

(setq prettify-symbols-alist scala-prettify-symbols-alist)
(prettify-symbols-mode)

Also feel free to customise the prettify rules by adding or removing from the scala-prettify-symbols-alist alist.

Libre fonts that seems to work well with this feature are: