In this screencast I cover how to do basic evaluation and get Clojure documentation from within vim. I'm also including the transcript below.
Vim is a powerful text editor. Clojure is a powerful programming language. While its been possible to edit Clojure code in vim for years, the toolchain has improved greatly over the past year. Today we're going to see how we can integrate vim with our Clojure REPL environment.
Life without integration
In a shell session, let's fire up a Clojure REPL. I'm going to use
lein repl to do this. In another shell session, let's start vim and edit a
As I edit my file, I can copy code from the editor, switch to the window with the REPL in it, and paste that code in. This works, but it's an awkward, slow process. REPLs are supposed to be all about fast feedback. We can do better than copy and paste.
Before we get started, we should get the some basic plugins for clojure development. Using your preferred vim plugin manager, add these plugins:
After you've installed the necessary Vim plugins, enter a project
directory. For example, if you have a leiningen project, cd into the
directory. In one shell session, fire up a REPL with
lein repl. In
another shell session, cd that that folder once again, and then open
Fireplace is able to detect when you are in the same directory as an active REPL, and will attempt to automatically connect for you. This process is transparent, but should be obvious once we attempt to to send a command to the connected REPL.
The most basic fireplace command is
:Eval takes an arbitrary
clojure expression, sends it off to the REPL, and prints the result
for you. For example, we could run
:Eval (+ 1 1), and we would, as
2 printed out. This emulates typing at REPL prompt
directly, but there's much more we can do with our REPL-connected vim
Let's stay with
:Eval for a bit longer.
:Eval without any arguments
will send eval and print the outermost form on the current line. For
example, let's look at a simple expression.
(map inc [1 2 3])
When we have our cursor on this line and type
:Eval with no arguments,
(2 3 4) printed back.
:Eval, as with many vim commands, can also take a range. So,
:1,3Eval would evaluate all of lines 1 through 3. All of the normal
special ranges work here, such as
% for the entire file, and
for the current selection in visual mode.
:Eval works well, but there's a quicker way to get feedback.
the normal mode mapping for doing a simple eval and print. By default,
cp expects a motion. The form that I use most though is
will eval and print the innermost form from the cursor's current
To demonstrate what this means, let's look at that expression again.
(map inc [1 2 3])
When our cursor is on the
map, and we type
cpp, we'll see
(2 3 4), just as when we did the plain
:Eval. But if we move our
cursor inside the vector and type
cpp again, we'll see that inner form
Something unique to fireplace is its concept of a quasi-REPL. This is a
cousin of the
cp mappings, but with an intermediate editing window. To
demonstrate this, let's consider the following example.
(->> [1 2 3] (map str) reverse (mapv dec))
In this trivial example, we want to reverse a sequence and decrement
each number. There's a bug in here, but it's in the middle of the
thread-through macro. We could just edit the line directly and
cpp, but there's another way to do one-off iterative
development like this.
cqc in normal mode. A commandline window will open. This is very
much like a normal vim buffer, with a few notable exceptions:
- It cannot be modified or saved
Enterin normal mode sends the current line to the REPL for eval-ing.
- As you run commands, they are added to this buffer.
tpope calls this the “quasi-repl”, and indeed that is the mnemonic for
the mapping itself:
cq is the “Clojure Quasi-REPL”.
While we're in this special window, let's type the following, and hit enter:
(map str [1 2 3])
Immediately, we can see the issue. Converting each number to a string
dec from working later on.
Having to type the whole line again isn't always convenient. For those
cqq, which is like
cqc except that it pre-populates
the command window with the innermost form under the cursor. We can
see this in action by putting our cursor near the beginning of the
thread-through macro, and typing
You can think of
cqq as being very similar to
cpp, but with a chance
to edit the line or lines before sending it off to the REPL.
One of the great things about Clojure is that documentation is a
first-class citizen, and builtin functions have documentation attached
to them. With a standard REPL, we can use the
doc function to get the
signature and documentation for a given function.
With fireplace, we get this with the
:Doc command, and it works just
doc. To see the documentation for
map, for example, type
:Doc map. We immediately see the documentation for the map command printed.
There's an even shorter way to look up documentation for a function.
When your cursor is on a word, you can press
K, that is
K. We can try this again with the
map function by placing our cursor
on the function itself, and pressing
We can also use the
:Source command to show the source for a function.
When we do this with
map, we see the source code for