How to edit S-expressions in Vim without plugins
If you're a Vim user and learning Clojure or another lisp, you don't have to install any plugins right away (let alone switch editors) just to make editing S-expressions palatable. You can get by pretty well with just the built-in features.
It boils down mainly to two keys: % and =. % will jump to a matching
paren (or curly/square bracket). = will re-indent a block of code. For
example, consider this implementation of the Fibonacci sequence:
(defn fib [n]
(if (#{0 1} n)
1
(+ (fib (- n 1)) (fib (- n 2)))))
Suppose we wanted to move the recursive fib calls into a (lazy) let binding. With
our cursor on the first line, we'd hit o and then add two lines:
(defn fib [n]
(let [fib-1 (delay (fib (- n 1)))
fib-2 (delay (fib (- n 2)))]
(if (#{0 1} n)
1
(+ (fib (- n 1)) (fib (- n 2)))))
With our cursor at the end of the third line, we could finish editing by hitting this sequence of keys:
0jw: move to opening paren of theifform.=%: re-indent theifform.jjWW: move to the opening paren of the(fib (- n 1))form.c%@fib-1<esc>: replace that form with@fib-1.Wc%@fib-2)<esc>: replace the secondfibform and add a closing paren for theletform.
(defn fib [n]
(let [fib-1 (delay (fib (- n 1)))
fib-2 (delay (fib (- n 2)))]
(if (#{0 1} n)
1
(+ @fib-1 @fib-2))))
For another example, say we want to add an element to the end of the div in this hiccup form:
[:div
[:p "I'm sorry Dave"]]
With our cursor on the opening bracket of the :div form, just hit %i and then <enter>[:p "I'm afraid I can't do that"]<esc>:
[:div
[:p "I'm sorry Dave"]
[:p "I'm afraid I can't do that"]]
Another useful combination is d%, which deletes the current form. I also
sometimes like to use v% to visually select a form before hitting = to
re-indent it. (And you can hit == to re-indent just the current line.) In
general, you'll find that editing S-expressions is quite natural once you've
committed % to muscle memory.
So you can edit S-expressions in plain Vimโbut should you?
If you're already in to Vim, sure. With the addition of just two plugins
(vim-fireplace and rainbow
parens) and let g:clojure_fuzzy_indent_patterns = ['.*'], I've found Vim to be a perfectly
adequate editor for Clojure. You can always try out more
plugins/Cursive/Emacs
after you've settled in.
Published 29 Mar 2020

