2014-06-13

I’ve released a screencast detailing getting vim setup for Clojure development. This screencast covers how to do basic evaluation and get Clojure documentation from within vim.

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
clojure file.

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.

Plugins

Before we get started, we should get the some basic plugins for clojure
development. Using your preferred vim plugin manager, add these plugins:

Setup

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
vim.

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.

Evaluation

The most basic fireplace command is :Eval. :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
expected, see 2 printed out. This emulates typing at REPL prompt
directly, but there’s much more we can do with our REPL-connected vim
session.

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.

When we have our cursor on this line and type :Eval with no arguments,
we’ll see (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. cp is
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 cpp, which
will eval and print the innermost form from the cursor’s current
position.

To demonstrate what this means, let’s look at that expression again.

When our cursor is on the m of 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
evaluated.

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.

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
eval/print using cpp, but there’s another way to do one-off iterative
development like this.

Type 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

Pressing Enter in 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:

Immediately, we can see the issue. Converting each number to a string
prevents dec from working later on.

Having to type the whole line again isn’t always convenient. For those
cases, there’s 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 cqq.

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.

Documentation

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
like 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 Shift and
K. We can try this again with the map function by placing our cursor
on the function itself, and pressing K.

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 map from
clojure.core.

Show more