#+TITLE: Scala layer #+TAGS: general|layer|multi-paradigm|programming [[file:img/scala.png]] with [[file:img/ensime.png]] * Table of Contents :TOC_5_gh:noexport: - [[#description][Description]] - [[#features][Features:]] - [[#layer-installation][Layer Installation]] - [[#backends][Backends]] - [[#metals][Metals]] - [[#ensime-deprecated][Ensime (deprecated)]] - [[#installation-when-using-sbt][Installation when using SBT]] - [[#installation-when-using-gradle][Installation when using Gradle]] - [[#configuration][Configuration]] - [[#usage][Usage]] - [[#scalastyle][Scalastyle]] - [[#use-java-doc-style][Use Java doc-style]] - [[#enable-debug-adapter-protocol-dap][Enable Debug Adapter Protocol (DAP)]] - [[#automatically-show-the-type-of-the-symbol-under-the-cursor][Automatically show the type of the symbol under the cursor]] - [[#automatically-insert-asterisk-in-multiline-comments][Automatically insert asterisk in multiline comments]] - [[#deprecated-automatic-replacement-of-arrows-with-unicode-ones][Deprecated: Automatic replacement of arrows with Unicode ones]] - [[#enable-gtags-as-a-fallback-navigation-utility][Enable GTags as a fallback navigation utility]] - [[#auto-start][Auto-start]] - [[#key-bindings][Key bindings]] - [[#ensime][Ensime]] - [[#search][Search]] - [[#ensime-search-mode][Ensime Search Mode]] - [[#sbt][sbt]] - [[#typecheck][Typecheck]] - [[#debug][Debug]] - [[#errors][Errors]] - [[#goto][Goto]] - [[#print-and-yank-types][Print and yank types]] - [[#documentation-inspect][Documentation, Inspect]] - [[#server][Server]] - [[#refactoring][Refactoring]] - [[#tests][Tests]] - [[#repl][REPL]] * Description This layer adds support for the Scala language to Spacemacs. ** Features: - Syntax highlighting - Support for language backend. Either using [[https://ensime.github.io/][ENSIME]] or [[https://scalameta.org/metals/][Metals]] - Debugging support via dap - Auto-completion - Treeview support for viewing project structure and triggering compilation - Syntax-checking - Refactoring - Incremental compilation - Scala Repl - Style linting - Eldoc integration - Optional GGTags search - Test execution directly from Emacs - Automatic replacement of ASCII arrows with unicode ones * Layer Installation To use this configuration layer, add it to your =~/.spacemacs=. You will need to add =scala= to the existing =dotspacemacs-configuration-layers= list in this file. * Backends The currently supported language backends are: - scala-metals - scala-ensime (deprecated) To set your choice of backend, configure the layer variable =scala-backend=. #+BEGIN_SRC emacs-lisp (setq-default dotspacemacs-configuration-layers '((scala :variables scala-backend 'scala-metals))) ;or 'scala-ensime #+END_SRC ** Metals Currently, you must manually install the metals server. It is possible to do so via coursier; the latest version can be built using the following commands, where =0.7.6= can be replaced with the current version of [[https://github.com/scalameta/metals/][Metals]]: #+BEGIN_SRC bash ./coursier bootstrap \ --java-opt -Xss4m \ --java-opt -Xms100m \ --java-opt -Dmetals.client=emacs \ org.scalameta:metals_2.12:0.7.6 \ -r bintray:scalacenter/releases \ -r sonatype:snapshots \ -o /usr/local/bin/metals-emacs -f #+END_SRC You will then have the common LSP key bindings; see [[https://github.com/syl20bnr/spacemacs/tree/develop/layers/%2Btools/lsp#key-bindings][LSP#key-bindings]] for more details. ** Ensime (deprecated) This package is mainly unmaintained today and should only be used as a last resort. [[https://ensime.github.io/][ENSIME]] provides IDE-like features, such as refactoring, incremental compilation and project-wide type-checking. You will also need to modify your =dotspacemacs/user-init= to pull the recommended Ensime version (Stable): #+BEGIN_SRC emacs-lisp (add-to-list 'configuration-layer-elpa-archives '("melpa-stable" . "stable.melpa.org/packages/")) (add-to-list 'package-pinned-packages '(ensime . "melpa-stable")) #+END_SRC ENSIME requires a configuration file at the root of each Scala project. It provides an SBT plugin, a gradle plugin and others (see [[https://web.archive.org/web/20190427005241/https://ensime.github.io/build_tools/][ensime.org]] for a full list) to generate these files. *** Installation when using SBT Find it with your favourite package manager, eg: #+BEGIN_SRC shell nix-env --install sbt #+END_SRC or refer to [[http://www.scala-sbt.org/download.html][the sbt installation instructions]]. *** Installation when using Gradle Refer to the [[https://web.archive.org/web/20190324005432/http://ensime.github.io/build_tools/gradle/][Ensime installation instructions]] to install the =ensime-gradle= plugin. *** Configuration Follow [[https://web.archive.org/web/20190417132406/http://ensime.github.io/build_tools/sbt/][the ENSIME configuration instructions]]. Spacemacs uses the development version of Ensime so follow the appropriate steps. To use the build functions under ~SPC m b~ you need to use version =0.13.5= or newer of =sbt=, and specify that in your project's =project/build.properties=. For example, #+BEGIN_SRC scala sbt.version=0.13.11 #+END_SRC *** Usage ~SPC SPC spacemacs/ensime-gen-and-restart~ or ~SPC m D r~ generates a new config for a project and starts the server. Afterwards ~SPC SPC ensime~ or ~SPC m D s~ will suffice do the trick. * Scalastyle [[http://www.scalastyle.org/][Scalastyle]] provides style-checking and linting. The Emacs functionality is provided by Flycheck. To use scalastyle, it must be present as an executable in your =PATH=. - macOS users: =brew install scalastyle= - Linux, please see [[http://www.scalastyle.org/command-line.html]] To test if =scalastyle= executable is in your path, run =scalastyle= in a new terminal, it should output something like: #+BEGIN_SRC bash $ scalastyle scalastyle 0.8.0 Usage: scalastyle [options] ... #+END_SRC Finally, enable the =syntax-checking= layer and set the =flycheck-scalastylerc= variable to a valid location. #+BEGIN_SRC emacs-lisp (setq-default flycheck-scalastylerc "/usr/local/etc/scalastyle_config.xml") #+END_SRC See the [[http://www.flycheck.org/en/latest/languages.html?highlight=scala#syntax-checker-scala-scalastyle][flycheck documentation]] and [[http://www.scalastyle.org/configuration.html][scalastyle configuration]] for up-to-date configuration instructions. ** Use Java doc-style To enable =java-doc-style=, set the variable =scala-indent:use-javadoc-style= to =t= #+BEGIN_SRC emacs-lisp (setq-default dotspacemacs-configuration-layers '( (scala :variables scala-indent:use-javadoc-style t))) #+END_SRC * Enable Debug Adapter Protocol (DAP) The metals backend enables integration with the DAP layer for debugging support. * Automatically show the type of the symbol under the cursor To enable the feature =ensime-type-at-point= when cursor moves, set the variable =scala-enable-eldoc= to =t=. #+BEGIN_SRC emacs-lisp (setq-default dotspacemacs-configuration-layers '( (scala :variables scala-enable-eldoc t))) #+END_SRC Enabling this option can cause slow editor performance. * Automatically insert asterisk in multiline comments To insert a leading asterisk in multiline comments automatically, set the variable =scala-auto-insert-asterisk-in-comments= to =t=. #+BEGIN_SRC emacs-lisp (setq-default dotspacemacs-configuration-layers '( (scala :variables scala-auto-insert-asterisk-in-comments t))) #+END_SRC * Deprecated: Automatic replacement of arrows with Unicode ones Scala used to support Unicode arrows =⇒=, =→= as aliases for ~=>~, =->= and =<-=, and the Scala layer would do the conversion to Unicode for you if you set =scala-use-unicode-arrows= to =t=. As the Unicode arrows are now [[https://github.com/scala/scala/pull/7540][deprecated]] in Scala, this variable has been dropped from the Scala layer. If it is still in your Scala layer variables like so: #+BEGIN_SRC emacs-lisp (setq-default dotspacemacs-configuration-layers '( (scala :variables scala-use-unicode-arrows t))) #+END_SRC Then you will need to remove it: #+BEGIN_SRC emacs-lisp (setq-default dotspacemacs-configuration-layers '(scala)) #+END_SRC * Enable GTags as a fallback navigation utility To enable gtags when in scala-mode, in case metals, or, ensime are not fully functioning set the variable =scala-enable-gtags= to =t=. #+BEGIN_SRC emacs-lisp (setq-default dotspacemacs-configuration-layers '( (scala :variables scala-enable-gtags t))) #+END_SRC * Auto-start If you prefer to have the backend start when you load a scala file, you can enable it with #+BEGIN_SRC emacs-lisp (setq-default dotspacemacs-configuration-layers '( (scala :variables scala-auto-start-backend t))) #+END_SRC * Key bindings ** Ensime *** Search | Key binding | Description | |-------------+-----------------------------------------------------| | ~SPC m /~ | incremental search using =ensime-scalex= major mode | | ~SPC m ?~ | incremental search in all live buffers | *** Ensime Search Mode | Key binding | Description | |-------------+-------------------------------------------------------------------| | ~C-j~ | Move to next match | | ~C-k~ | Move to previous match | | ~C-i~ | Insert at point import of current result | | ~RET~ | Jump to the target of the currently selected ensime-search-result | | ~C-q~ | Quit ensime search | *** sbt | Key binding | Description | |-------------+---------------------| | ~SPC m b .~ | sbt transient state | | ~SPC m b b~ | sbt command | | ~SPC m b c~ | compile | | ~SPC m b C~ | clean command | | ~SPC m b i~ | switch to sbt shell | | ~SPC m b p~ | package command | | ~SPC m b r~ | run command | *** Typecheck | Key binding | Description | |-------------+-----------------------------| | ~SPC m c t~ | type check the current file | *** Debug | Key binding | Description | |-------------+-----------------------------| | ~SPC m d A~ | Attach to a remote debugger | | ~SPC m d b~ | set breakpoint | | ~SPC m d B~ | clear breakpoint | | ~SPC m d C~ | clear all breakpoints | | ~SPC m d c~ | continue | | ~SPC m d i~ | inspect value at point | | ~SPC m d n~ | next | | ~SPC m d o~ | step out | | ~SPC m d q~ | quit | | ~SPC m d r~ | run | | ~SPC m d s~ | step | | ~SPC m d t~ | backtrace | *Note:* These key bindings need a transient-state, PR welcome :-) *** Errors | Key binding | Description | |-------------+----------------------------------------------------| | ~SPC m e e~ | print error at point | | ~SPC m e s~ | switch to buffer containing the stack trace parser | *** Goto | Key binding | Description | |-------------+------------------| | ~SPC m g g~ | go to definition | *** Print and yank types |-------------+--------------------------------| | ~SPC m h T~ | print full type name at point | | ~SPC m h t~ | print short type name at point | | ~SPC m y T~ | yank full type name at point | | ~SPC m y t~ | yank short type name at point | *** Documentation, Inspect | Key binding | Description | |-------------+----------------------------------------| | ~SPC m h h~ | show documentation for symbol at point | | ~SPC m h u~ | show uses for symbol at point | *** Server | Key binding | Description | |-------------+--------------------------------------------------------| | ~SPC m D f~ | reload open files | | ~SPC m D r~ | regenerate the =.ensime= and restart the ensime server | | ~SPC m D s~ | start ensime server | *** Refactoring | Key binding | Description | |-------------+----------------------------------------------------------------------| | ~SPC m r a~ | add type annotation | | ~SPC m r d~ | get rid of an intermediate variable (=ensime-refactor-inline-local=) | | ~SPC m r D~ | get rid of an intermediate variable (=ensime-undo-peek=) | | ~SPC m r i~ | organize imports | | ~SPC m r m~ | extract a range of code into a method | | ~SPC m r r~ | rename a symbol project wide | | ~SPC m r t~ | import type at point | | ~SPC m r v~ | extract a range of code into a variable | | ~SPC m z~ | expand/contract region | *** Tests | Key binding | Description | |-------------+--------------------------| | ~SPC m t a~ | test command (sbt) | | ~SPC m t r~ | test quick command (sbt) | | ~SPC m t t~ | test only (sbt) | *** REPL | Key binding | Description | |-------------+---------------------------------------------------------------------| | ~SPC m s a~ | ask for a file to be loaded in the REPL | | ~SPC m s b~ | send buffer to the REPL | | ~SPC m s B~ | send buffer to the REPL and focus the REPL buffer in =insert state= | | ~SPC m s i~ | start or switch to the REPL inferior process | | ~SPC m s r~ | send region to the REPL | | ~SPC m s R~ | send region to the REPL and focus the REPL buffer in =insert state= |