But using Emacs for Java or Scala seems like taking a few steps back in human race's development, right? Or maybe?...
ENSIME the ENhanced Scala Interaction Mode for Emacs
The ensime package is a set of software pieces written in elisp, Scala, and Java, and it looks promising. Here are the main features copied from theReadme.md
file (along with some screenshots taken by me):
- Highlight errors and warnings in your code buffers.
- Inspect the type of any expression.
- Browse packages
- Completion for variables, methods, constructors, etc.
- Incrementally search through classpath symbols
- Find all references to a symbol
- Jump to symbol definitions.
- Semantic Highlighting
- Automated Refactorings (rename, organize imports, extract method)
- Source Formatting
- AST-based selection
- Supports sbt7,10,11
- Supports Maven,Ivy build descriptions
- Embedded sbt shell
- REPL
- Debug support
- Linking to online Scaladoc
Installation
The easiest way to install it is to download the latest bundle from the downloads page and unpack it into your local~/.emacs.d/plugins/
directory.Next step is to enable loading the
scala-mode
and ensime
in your .emacs
file:
(add-to-list 'load-path (expand-file-name "~/.emacs.d/plugins/ensime/elisp"))
(add-to-list 'load-path (expand-file-name "~/.emacs.d/plugins/scala-mode"))
(when (and (require 'scala-mode-auto nil 'noerror) (require 'ensime nil 'noerror))
(add-to-list 'auto-mode-alist '("\\.scala.html$" . scala-mode))
(add-hook 'scala-mode-hook 'ensime-scala-mode-hook))
Then the
sbt
plugin has to be added to your projects app_name/project/plugins.scala
file:
addSbtPlugin("org.ensime" % "ensime-sbt-cmd" % "VERSION")
The VERSION
string should be replaced with the latest plugin version that can be read
on the plugin project page in the README.md
section.
At last the project should be (re)generated with the command:
ensime generate
that can be issued in the play
console, and the project is ready to be 'connected' with the M-x ensime
command in Emacs.
Every time a library or Scala source is added to or removed from the project the command should be used. Otherwise you can hit an occasional 'symbol not found' message.
Memory usage
There is one issue that concerns me when using the ensime mode: the memory usage. When the project becomes 'connected' a background Java process is spawn, and that would be OK wasn't it for the 1.9GB of physical memory usage on a 64-bit, or about 1GB on a 32-bit Linux system for a simple project that does almost nothing except displaying the index page.Exploring the ensime manual I came across the config file settings section describing the
:only-include-in-index (regex*)
that allowed me to cut by half the amount of physical memory eaten by the background process.
The listing below shows Build.scala
that helped me to achieve this effect:
import sbt._
import Keys._
import PlayProject._
import org.ensime.sbt.Plugin.Settings.ensimeConfig
import org.ensime.sbt.util.SExp._
object ApplicationBuild extends Build {
val appName = "dinobase"
val appVersion = "1.0-SNAPSHOT"
val appDependencies = Seq(
// Add your project dependencies here,
)
val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings(
// Add your own project settings here
ensimeConfig := sexp(
key(":only-include-in-index"), sexp(
"controllers\\..*",
"models\\..*",
"views\\..*",
"play\\..*"
)
)
)
}
Enable semantic highlighting
By default emacs uses syntactic highlighting in sources. Because a syntax highlighter cannot tell whether a symbol isval
or var
, or a method call it is recommended to enable the semantic highlighter by the snippet below to your .emacs
file.
(setq ensime-sem-high-faces
'(
(var . (:foreground "#ff2222"))
(val . (:foreground "#111111"))
(varField . (:foreground "#ff6666"))
(valField . (:foreground "#666666"))
(functionCall . (:foreground "#84BEE3"))
(param . (:foreground "#111111"))
(class . font-lock-type-face)
(trait . (:foreground "#084EA8"))
(object . (:foreground "#026DF7"))
(package . font-lock-preprocessor-face)))
Ofcourse some tunning may be neede to suit your taste.
Link to Play! sources and customize Scaladoc and Javadoc
According to the manual it should be possible to add the link to the Play! sources by adding appropriate keys to theensimeConfig
variable.
key(":source-roots"), sexp(
"/home/rajish/proj/scala-beginner/dinobase/app",
"/home/rajish/proj/scala-beginner/dinobase/test",
"/home/rajish/bin/play2/framework/src"
)
But currently that takes no effect. When this issue gets fixed it should be
managed in that way but for now you should tweak manually the value of the :source-roots
key in the generated .ensime
file.
Linking to Play! scaladoc should work when the following snippet is added to your
.emacs
file, but due to this issue
it doesn't.
(defun make-play-doc-url (type &optional member)
(ensime-make-java-doc-url-helper
"file:///home/rajish/bin/play2/documentation/api/scala/" type member))
(add-to-list 'ensime-doc-lookup-map '("^play\\.api\\." . make-play-doc-url))
And currently there is no on-line scaladoc repository for the Play! framework, so we are forced to plant a local http server serving the documentation or resort to browsing the sources linked to the project (see previous paragraph).It seems to be a better idea to put such settings to the project's
.ensime
file via customization in the Build.scala
file. That's why I filled
yet another issue.Conclusion
First impression is very promising when the memory issue is minimized. I'll keep on using ensime for some time, and will report here when something worth noting (like an appearance of the new commandemacsify
) happen.
Excellent article!
ReplyDeleteOf course, real programmers use butterflies with one wing :)
So real programmers don't use IDEs, they use Emacs, with an Emacs plugin that replicates all the features that those dreadful IDEs provides...
ReplyDeleteSounds like you're not an Emacs user, aren't you? This post is for die-hard emacsers, and every die-hard emacser does not live outside Emacs (except for going to the toilet/lavatory/loo - one shouldn't litter the place of living.)
DeleteFYI Emacs is built from 'plugins'. Without them you couldn't do any sensible thing in Emacs. And those 'plugins' make the editor(some of us call it OS or even God) awesome.