Emacs is my editor of choice for Clojure development (as for all Lisps), and according to the State of Clojure 2011 survey, that’s true for 68% of all Clojure developers.
Yet from what I’ve seen, some Emacs using Clojure developers don’t evaluate their code in Emacs, and the survey shows that 20% of all Clojure developers use the command-line REPL. Read on to figure out how to change that in just about 5 minutes.
“But why would I want to evaluate Clojure in Emacs?”, you might ask. Here’s why I can’t live without it: When I was new to Lisp, I missed the step-by-step debugger I knew from imperative languages. That changed when I started to write Emacs Lisp and got used to evaluating code in the editor. In functional programming, you avoid mutable state, especially global mutable state, so you can normally locate and fix bugs by evaluating suspicious parts of your program in isolation. Proper runtime inspection is still useful and necessary in some cases, and there are tools for that, but evaluating code in Emacs has been sufficient for me so far.
While most Clojurians seem to swear by SLIME to achieve this, I’m not particularly comfortable with it. It’s big, annoying to set up and there has been no release or tag to date, you have to get the latest code from CVS. Nothing you’re likely to get up and running in 5 minutes. If you’ve got some free time, do try SLIME, you might like it. If you, like me, would rather avoid it: Read on to learn how to set up inferior-lisp-mode (where inferior-lisp stands for Lisps other than Emacs Lisp) for Clojure.
Setting up inferior-lisp-mode
All you really need to do is set the variable inferior-lisp-program to the command that invokes the Clojure REPL.
If you use Leiningen for all projects, add the following to your init.el:
(add-hook 'clojure-mode-hook (lambda () (setq inferior-lisp-program "lein repl")))
For Maven users, it takes a bit more effort. The inferior-lisp command will execute the configured command in the same directory as the file you are currently visiting, which is probably not the directory where your Maven pom.xml resides. Maven, however, wants you to execute most commands in that directory. To circumvent this, I wrote a wrapper script that locates the pom.xml before invoking Maven. Armed with that, you can set up inferior-lisp-program as follows:
(add-hook 'clojure-mode-hook (lambda () (setq inferior-lisp-program "smvn clojure:repl")))
Both Leiningen and Maven
When you are working with both Leiningen and Maven projects (like I do), things get a little more complicated. I thought about writing an Emacs Lisp function that automatically discovers whether a project is a Leiningen or a Maven project and invokes the respective command, but decided to shave that yak later. Instead, I use Emacs’ dir local variables to set the inferior-lisp-program for each project. For a Leiningen project, just add a .dir-locals.el file with the following content to your project’s root directory:
((clojure-mode . ((inferior-lisp-program . "lein repl"))))
For Maven projects, do the same with the following content:
((clojure-mode . ((inferior-lisp-program . "smvn clojure:repl"))))
And to eliminate the annoying warning that pops up whenever the dir locals are set, add the following to your init.el:
(add-hook 'clojure-mode-hook (lambda () (setq safe-local-variable-values '((inferior-lisp-program . "lein repl") (inferior-lisp-program . "smvn clojure:repl")))))
Now that you’ve set up inferior-lisp-mode, you can just open a Clojure file and type: M-x inferior-lisp, which starts a Clojure REPL in the current Emacs window. You can then use the REPL conveniently from within Emacs, and evaluate s-expressions in your code by placing the cursor on closing parantheses and pressing C-x C-e.
That’s it, have fun 🙂