Emacs is a great tool for clojure development. In fact you often hear people raving about the marriage of emacs and clojure without any clear explanation of if or why it's better than any other editor that you could use for clojure development.
I'm not going to get into why emacs is good for clojure development here. The aim of this post is to help someone who is looking to try it get up and running quickly, so they can try it for themselves.
I'm assuming you already have emacs installed and clojure setup. I won't go into the basics of using emacs here, but I'll outline a few of the features that you may find handy for working with clojure code.
The quickest way to get your emacs up and running is to install emacs-live. Emacs live is
"An opinionated set of defaults for getting started with a specific focus on live coding with Overtoneand Quil."
It provides an excellent default setup for working with clojure.
Emacs Modes for clojure development
One of the most common complaints I hear from people who haven't tried clojure is about the abundant parentheses and how difficult they are to manage. Managing and matching parentheses is really a problem for the text editor, not the programmer. If you have trouble with unmatched parentheses, then either your text editor is not up to the task or you're not using it correctly.
Paredit mode is an emacs mode that takes care of the minutiae of working with s-expressions. Some of the things it does for you include:
- Ensures your parentheses are always balanced. E.g. It won't allow you to create an opening bracket without the corresponding bracket, or it won't let you delete a single bracket - you have to delete the entire expression.
- Lets you cut, paste, move etc s-expressions in their entirety. You can move the entire sub-tree of an expression somewhere else or wrap an entire expression with another one.
If you've never used Paredit before, it can be a little off-putting. You need to move from thinking in terms of text-tokens to thinking in terms of expressions. Once you get used to it though, the parentheses that so many people are wary of fade into the background. They become easy to manage.
To get a feel for Paredit, lets edit a small clojure file and play around with the brackets.
Lets create a new clojure project...
...and then open the generated core.clj file.
If you've setup emacs-live you should see the following list of active modes when you open this file:
Active modes for a .clj file: Clojure, Undo-Tree, yas, VHl, AC, Paredit
Now, try to delete a closing ")". You can't. Navigate to the opening "(" of the println form. Press C-k to delete it. Notice that it deletes the entire form, but not the entire line - the last ")" remains. Keep, pressing C-k - you can't delete that closing ")"!
Press C-y to paste the println form back to where it was. Now highlight the println form (Press C-space on the opening "(" and then move the cursor to the closing ")" ). Now if you enter an opening bracket "(" it will wrap that entire expression with brackets. There's a lot more stuff you can do with Paredit mode that facilitates working with lisp-forms - take some time to get comfortable with it.
This provides indentation, highlighting and navigation for your clojure code. You don't really need to learn to use it - just know that you need what it provides.
Cider provides a set of commands for starting and running a repl from emacs, and then sending code for evaluation to that repl. This is core to emacs clojure development. You get into a workflow of constantly evaluating and re-evaluating functions as you iterively develop them and incrementally build up a working program in the repl.
Let's continue with our example project from above and launch a repl from emacs.
will start a repl (This command may be cider-jack-in instead of nrepl-jack-in, depending on which version of cider you have installed). Once it's started you should be able to enter clojure code in the repl and see the results immediately.
Let's evaluate some of our clojure code in the repl. The handiest way to do this is
C-c C-e. This will evaluate the previous form in the text window and print the results.
Lets navigate to the space just after the last closing ")". Now if you run
C-c C-e you should see the results of evaluating that function in your status window i.e. (
Now switch you the repl window and change to the hello.core namespace.
You can now run the foo function from the repl.
Let's say our foo function is broken and we want to debug it. We'll set x in the repl and then we can step into our function and evaluate the forms in the function individually.
In the repl enter
(def x "Broken")
Now go back to the core.clj file and navigate the cursor to the space after the closing bracket of the angle println form. If we press
C-c C-e we should see "Broken Hello, World!"in the repl
This is a very simple example, but in this way we can step through functions evaluating forms, seeing what every form in a function evaluates to for a given input. We can re-evaluate a function at any time to update the code that the repl is running. This gives us a lot of power to inspect how our code is behaving and to interively build up a working program in the repl.
Here are a few more commands that are useful for interacting with the repl and evaluating code. You can find the full list of available commands in the cider documentation.
|C-c C-e||Evaluate the form preceding the cursor and print the result to the echo area|
|C-c C-r||Evaluate the highlighted region|
|C-c M-n||Switch the namespace of the repl buffer to the namespace of the current buffer|
|C-c C-z||Switch to the repl buffer (and back to previous buffer)|
|C-c C-k||Load (all) the current buffer|
|C-c C-d||Display the doc string for the symbol under the cursor|
|M-p||previous repl command|
|M-n||next repl command|
|Tab||Autocomplete current symbol|
|C-c C-z||Back to previous buffer|
So that's a very quick and basic tour of how to get started with emacs for clojure development. The best thing to do now is to jump in and start using emacs for editing clojure code, while at the same time reading the paredit and cider documentation and incorporating them into your workflow as you go along.