Wednesday, 20 November 2013

Programming Clojure with Vim (2013 edition)

It's been over three years since I wrote Programming Clojure with Vim, and a lot has changed since then, including:

  • Vim now bundles some static Clojure support (Yay!).
  • VimClojure development has ceased, now replaced by two new projects:
    1. vim-clojure-static, a fork of the static portion of VimClojure.
    2. vim-fireplace, a new dynamic back end for Clojure

How has my environment changed as a result? Quite a bit, in fact:

  • I have replaced VimClojure with vim-clojure-static and vim-fireplace.
  • I love my rainbow parentheses, so I am using rainbow_parentheses.vim.
  • I have finally started using paredit from slimv.

So, how is this working out for me?

The good stuff

Look, ma, no setup!

I think the best part of this new configuration is that it uses nREPL instead of VimClojure's nailgun-based protocol. This means that I'm just a lein repl away from having my dynamic Clojure support in Vim. I no longer need to fuss with lein-tarsier or create custom development scripts.

This is a big deal.

Gone over to paredit

So, I've started using paredit. It's long been a feature I've had some interest in, as all the Emacs users I know really love it. However, I could never get used to Emacs, and when I last reviewed Slimv's paredit support, I had complained about it being buggy.

Fast forward a few years, and it's gotten a lot better. I'm still a paredit newbie, so I'm not yet slurping and barfing s-expressions like it's second nature. Nonetheless, I can finally see why Emacs users love it so much.

paredit and LustyJuggler

There is one important caveat I have found for paredit: It seems to conflict with using LustyJuggler with the home row. I presume this is a result of paredit's normal mode key mappings, but I'm not sure that this is something that can be easily fixed from the paredit side without making drastic changes to the key mappings. If I have some time, I'll look into writing a patch for LustyJuggler. For the moment, a less than ideal workaround is using the number keys when juggling buffers.

What am I missing?

So, what is missing with these new plugins that I had before with VimClojure? Really, not much. The key mappings and functionality of vim-fireplace is certainly different than that of VimClojure, but most of what I need is there.

vim-redl, most likely

The one thing I think is noticeably not in vim-fireplace is VimClojure's ability to do completion and highlighting dynamically based on what's loaded in the REPL. vim-redl seems to have that functionality, but I haven't tried it.

My configuration

I now use Vundle to manage my Vim plugins. I had been using Pathogen for a long time, but as I have updated how I manage my home directory across machines, Vundle became a better fit. Here's an excerpt of my vimrc with just the Clojure-specific parts:

" Fireplace (Clojure support)
Bundle 'tpope/vim-fireplace'

" Rainbow parentheses
Bundle 'kien/rainbow_parentheses.vim'
"  Parentheses colours using Solarized
let g:rbpt_colorpairs = [
  \ [ '13', '#6c71c4'],
  \ [ '5',  '#d33682'],
  \ [ '1',  '#dc322f'],
  \ [ '9',  '#cb4b16'],
  \ [ '3',  '#b58900'],
  \ [ '2',  '#859900'],
  \ [ '6',  '#2aa198'],
  \ [ '4',  '#268bd2'],
  \ ]

" Enable rainbow parentheses for all buffers
augroup rainbow_parentheses
  au VimEnter * RainbowParenthesesActivate
  au BufEnter * RainbowParenthesesLoadRound
  au BufEnter * RainbowParenthesesLoadSquare
  au BufEnter * RainbowParenthesesLoadBraces
augroup END

" SlimV
Bundle 'kovisoft/slimv'

" vim-clojure-static
Bundle 'guns/vim-clojure-static'

As you can see, installation is straightforward. The trickiest bits are for rainbow parentheses, where I do two different things:

  1. I set up the parentheses colours to use the various highlight colours from Solarized.
  2. I enable rainbow parentheses for all buffers and for brackets ([]) and braces ({}) as well. You may want to limit this to Clojure buffers, but I haven't found it too intrusive in other files. To do this, just replace the * in the au commands with something like *.clj.