Editing Clojure, or any other Lisp dialect, is unlike editing any other language we normally write. We can no longer just make our changes line-wise, instead we must deal with editing s-expressions, or expressions surrounded by parentheses. Let’s look at a small Clojure function.
(defn say-hello
([] (println "Hello there"))
([name] (println (str "Hello " name))))
Assume we want to remove our single argument variation of this function, and instead just leave the version with no arguments, resulting in a function that looks like this:
(defn say-hello []
(println "Hello there"))
As you can see there was more to this than just deleting the last line of the function. We also had to worry about maintaining matching groups of parentheses.
When looking for information on editing lisps in Vim we often see people saying “If you’re writing a lisp, you should switch to Emacs.” If you are interested in trying Emacs, with evil-mode of course, there is a great starter kit for writing Clojure. Luckily there are a variety of great plugins to enhance Vim’s editing capabilities for editing Clojure, aside from switching our entire editor.
The most heavy-handed plugin for this is paredit. Based on
the Emacs plugin of the same name, paredit aims to be an editor changing
plugin that makes editing s-expressions very similar to editing lines of
code in other languages. To do this it overrides many normal Vim
commands such as D
to be aware of balanced sets of parentheses.
Personally I find this to work well until paredit starts fighting me.
Occasionally you can get to a state where you are unable to delete a
parenthesis because it still has a pair. Since paredit also overrides
x
and nearly every other normal mode command, this can be extremely
aggravating.
A slightly less intrusive option for making this easier is
vim-sexp. As opposed to remapping typical Vim operations
this plugin provides text objects for typical lisps
patterns such as compound forms, or an expression enclosed in
parentheses or various other delimiters. This means we can use commands
such as daf
to delete around the current compound form. I find this
significantly more pleasant while editing Clojure.
Another common operation while editing lisps is slurping and barfing. Here’s an example:
(map inc (1 2 3) 4)
We can see this is invalid syntax. What we actually want here is this:
(map inc (1 2 3 4))
To do this with typical Vim commands we may delete the parenthesis after
the 3
and put it after the 4
. Since this slurp operation is common
in lisps, along with the opposite barf operation, vim-sexp has a mapping
for this too. We can use <M-S-l>
, or Option-Shift-l
on OS X to slurp
the element to the right. Personally I find this mapping extremely
unintuitive and difficult to use. Tim Pope created the aptly
named vim-sexp-mappings-for-regular-people to solve this
problem. This plugin hooks into vim-sexp and provides more sensible
mappings for slurping and barfing. It maps >)
where the angle bracket
is the direction and the parenthesis is the end to operate on. Together
these two plugins provide all the editing capabilities that I need to
efficiently edit Clojure.
Now that we have some help editing lisps you may want some Clojure specific plugins to improve highlighting in Vim. There is a good set of syntax files for Clojure, which, as we know, can be hard to maintain. The same author also has a plugin for extended highlighting. This plugin actually runs some Clojure to highlight our code.
Talking about Clojure and Vim plugins would not be complete without mentioning vim-fireplace, a plugin for integrating with a REPL and evaluating our code within Vim. Fireplace also provides other useful mappings that you can read about in the documentation. Tim Pope makes another plugin that integrates fireplace with Leiningen projects.
Last but not least is rainbow parentheses. This plugin highlights matching parentheses with different colors so we can tell what matches what. It makes dealing with nested s-expressions much easier.
Depending on how you like to edit Clojure in Vim, some of these may not be for you. But no matter what you can definitely turn Vim into a fully featured Clojure editor.