Unboxing is our regular feature where someone at Box UK spends a few hours playing with a new framework, library, tool or technique and blogs about his or her experience.
I’ve been using Vim for a few years now, and love it. When developing with Clojure, however, I’ve always felt like I’ve been missing out on the tight integration my Emacs-touting colleagues seem to enjoy. I’ve tried picking up Emacs a few times, but have always ended up coming back to Vim as I just feel much more productive with my day-to-day languages.
Until now my setup has involved using a Slime plugin to send functions to a REPL running inside a Screen session. This actually works reasonably well; the plugin just grabs chunks of text and pipes them to the screen session. It’s agnostic to the source and destination, so can be useful for many things, but it does lack the aforementioned tight integration so I’ve always hoped for something better…
What is it?Over the last year the Clojure community has moved away from using Swank/Slime to the nREPL protocol. For Vim, there is a plugin called vim-fireplace (previously vim-foreplay) which provides this functionality. This post is a little different to our usual unboxings where the author has no experience of the tech, as I’ve been using this for a little while, but I want to take you through what vim-fireplace is and how nicely it works.
Getting to gripsInstallation is pretty straightforward. I use vundle to manage my plugins, so installing vim-fireplace is as easy as adding it to my config:
Bundle ‘guns/vim-clojure-static’ Bundle ‘tpope/vim-fireplace’
I’ve also included the vim-clojure-static plugin which provides syntax highlighting, indentation and filetype settings for Clojure and ClojureScript. If you use Pathogen then you can find the repos to clone on Github.
Unlike with Emacs where (as I’m told, anyway) it’ll start an nREPL server for you when you ‘jack in’, we need to start the REPL that Vim is going to connect to. This is easy of course with Leiningen:
$> lein repl nREPL server started on port 55983 REPL-y 0.1.10 Clojure 1.5.1 Exit: Control+D or (exit) or (quit) Commands: (user/help) Docs: (doc function-name-here) (find-doc "part-of-name-here") Source: (source function-name-here) (user/sourcery function-name-here) Javadoc: (javadoc java-object-or-class-here) Examples from clojuredocs.org: [clojuredocs or cdoc] (user/clojuredocs name-here) (user/clojuredocs "ns-here" "name-here") user=>
You’ll see that it prints out the port nREPL is listening on. This has also been written to the file target/repl-port which vim-fireplace will use. There’s no need to start Vim or nREPL before/after each other; any order will work. You can even restart the REPL and vim-fireplace will reconnect to the new one (or even connect to a running application!)
To test that it’s working, open a Clojure file from your project and enter :%Eval, which will evaluate the current namespace. You should see a message on the statusline that will be the result of the last expression in the file (probably a function name).
Then you can try executing some code. Type an invocation to one of the functions in your namespace, move the cursor to it, and then type :Eval. You should see the result of the function appear in the message window at the bottom of Vim:
Sweet! Let’s try some other features…
Going DeeperUsing :Eval and :%Eval is fine for a demo, but not for more than a few minutes. So, I added some handy key bindings (ctrl-e, and shift-e, respectively).
nnoremap <C-e> :Eval<CR> nnoremap E :%Eval<CR>
This makes it really quick and easy to compile and evaluate forms, and error messages will be displayed right there in Vim when they occur (so, no need to switch to another application as I had to do before).
The next useful feature is the ability to access documentation and function source code. Documentation can be accessed either by using :Doc FUNCTION_NAME, or more handily by using K while the cursor is over a function. This will then display the documentation for that function in a message window at the bottom of the screen. Here’s an example for clojure.core/map.
This isn’t just limited to the clojure.core docs; it’ll work for all your project code and any libraries you’re using. As you can imagine, having this information one keystroke away saves a lot of time. If the docs are not enough, you can also display the source for a function using [d, like…
It’s nice to see good example code from clojure.core, but it’s invaluable when looking up that function you just wrote that you now need to reference.