Emacs + ENSIME, part 2 - Excelsior
Apr. 30th, 2011
01:45 pm - Emacs + ENSIME, part 2
Yesterday I've got a chance to play with Emacs and ENSIME, as I've planned before. Below you can find some of my impressions from that. Since this is my first experience with Emacs, this blog will also feature generic Emacs stuff.
I must admit that I'm impressed by Emacs. First of all, its lightness is remarkable. Unlike industrial monsters, such as VS and IDEA, it's perceived as a lightweight tool that will never ever freeze or eat up several gigs of RAM. Secondly, I've never imagined that it's possible to use IDE without mouse. Well, it is. I haven't seen much of Emacs, but from what I've seen, it's heavily optimized towards keyboard. Say, after you build a project in ENSIME, a new buffer gets popped near the current one. If there are no errors, you just press "q" to close it. If there are some errors, you can use TAB to navigate them. And all that without docking windows, double clicks and stuff. Finally, scriptability of Emacs is astounding. Within ten minutes of tinkering, I've managed to make Emacs automatically maximize its windows and reopen previously opened project upon startup. After struggling with VS Shell, this feels like heaven.
Installing ENSIME was a breeze. I just followed the instructions in the user manual and everything worked well. The only thing I stumbled upon was the lack of direct evidence of ENSIME being operational - no logs, no menus, nothing. Though, after some time I opened a .scala file and noticed that there are two new menus: "Scala" (from scala-mode) and "ENSIME" (from ENSIME). After that I googled some youtube screencasts about ENSIME and got an idea of what functionality it provides (check the "Demo Videos" section of the project's homepage - those links cover the most important features of the plugin).
A couple of words about how it works, since the architecture seems quite neat to me. Upon certain user actions, ENSIME plugin (hosted within Emacs and written in elisp) communicates with ENSIME server (a standalone Scala app) using a simple text protocol (actually, one can even take a look at request and responses in a designated buffer of Emacs). To process requests, the server usually calls Scala presentation compiler which resides within scala-compiler.jar. Apart from the compilation itself, the presentation compiler provides additional services like typing and auto-completion (read more details here).
I quickly created an SBT project with hello-world code and started experimenting. Basic stuff like REPL and compilation worked finely - that was a good start. Then I tried to type some gibberish and save the file, and immediately after that ENSIME redlined the errors I had made, and even provided tooltips with error messages - a neat feature! After that I tested the most essential navigation function, "Go To Definition". It worked correctly, and, moreover, it provided a way to navigate back (Navigation > Pop definition stack). I tried the type and package explorers, and they also were pretty good.
The troubles began when I proceeded with testing the "Refactor" menu group. To be honest, I'm not a refactoring gourmet, and from the entire toolbox of refactorings that is provided by IDEA/Resharper, I use only a handful of tools: rename, extract/inline, rename namespace and move type to another namespace. Most of them are present in ENSIME, so I was pretty optimistic about what I was going to face... Until I found out that most of the time those refactorings work incorrectly even for the simple project I had created (issue #1, issue #2, issue #3).
I filed the issues to the project's issue tracker and, in the meanwhile, will use IDEA and its Scala plugin. I have been deeply impressed by Emacs philosophy, but there's no way I can code productively without basic refactoring tools. I hope that, along with the release of Scala 2.9, Aemon will publish a new version of ENSIME that will be free from these unfortunate defects.