Spend some time trying editing Lisp code in the first phase. If editing Lisp code does not feel cumbersome then, or if it feels only as cumbersome as editing code in other languages, then there is probably no need for you to go to the second phase, and no need to use anything like paredit. But if you are not satisfied with the first phase, or if maintaining balanced parentheses still feels like a chore, then it’s time to move to the second phase, the “red tape” phase.
The first rule of the second phase is this: you will type parens only in pairs (except in comments and strings). In other words, every time you type an open paren, the next action should be to type a close paren, and every time you type a close paren, the previous action should have been typing of an open paren. Typing of
() should be considered an atomic operation from now on, in other words, you never do something like typing just an open paren and then doing something other than typing the corresponding close paren.
By following this rule, you never introduce mismatched paren in the first place. But how does one type
(foo) without violating the rule? You first type
() and then type
foo between the two parens.
Exercise 60. Configure your text editor so that there is a convenient keyboard shortcut for typing
() (and then placing the text cursor between the two parens).
M-( runs the command
insert-parentheses which types
How would you type
(let (a b c) (foo))
Let’s make that more interesting. How would you write the following?
One way of writing that is to first write the following (which you now know how to write without violating the rule):
and then write
(a b c) to get:
and so on. (Recall that you already know how to break
(a b c) into multiple lines.)
Another way is to first write:
and then wrap that with a let form, but how do you do that? If you cannot find a command for that, you can simply cut the two expressions
(foo) (bar) into clipboard and then write the following
and then break the line to get:
and then paste back
(foo) (bar) so you get:
(let (a b c)
Exercise 70. Try both ways.
Second rule is that you don’t do anything that results in mismatched parens. For example, deleting or commenting out the second-to-last line in the following code is not allowed, but deleting just the expression
(print "world") is OK.
(defun my-hi ()
(dotimes (_ 2)
(print "the end"))
What are some of allowed operations then? Here are some, which I will call “basic operations” from now on:
- well formed cut – cutting one or more expressions to the clipboard (As mentioned in the previous article, by “expression”, I mean symbolic expression)
- well formed copy
- well formed paste – pasting expressions from clipboard (and then indenting correctly)
- well formed commenting – commenting out one or more expressions
- well formed delete
- joining or splitting lines (and then indenting correctly)
- typing something that does not contain any parens or newlines (except within strings and comments)
- opening a blank line or removing one
Notice that the wrapping operation (wrapping with a let form) was done by a well formed cut (of two expressions
(foo) (bar)), and then some other basic operations, and then a well formed paste. In fact, notice that the previous exercise was done using only basic operations.
To do well formed cut (or well formed copy) easily, you need to know a convenient way to select expressions. For example, how do you select the bar form and the moo form together in the following code in your text editor?
(b c d))
The answer of course is to select from the start of the bar form to the end of the moo form, but where exactly (within those close parens) is the end of the moo form? If your text editor has some features for helping you see which close paren matches which open paren, then you can use those features to pinpoint the ending close paren for the moo form. Your editor should also have separate features or plugins for easy selection of expressions. Find them.
Emacs note: In vanilla Emacs, this is how you would select the bar form and the moo form: move point to anywhere within the bar form, and press
C-M-u as many times as necessary (to get to the starting position of the bar form), and then press
C-M-SPC as many times as necessary (twice in this case). This is generally how you select one or more expressions.
Notice that the basic operations work on the level of expressions, not on the level of letters, words or lines. Think of each basic operation as an atomic operation. In particular, if you are in the middle of doing some well formed cut and the phone rings, you complete the operation before answering the phone.
You can edit Lisp code using only basic operations, as we’ll see in next sections. The idea of the red tape phase is like the lesson of Vim: “In Vim, the trick is you work mainly with text objects (words, lines, sentences, code blocks, etc), not with letters.” In Lisp editing, the trick is you work with expressions (sexps), not with lines or letters.
Note: in some cases, you might need some kind of clipboard manager (either as a feature within your text editor, or as an external program) if you need use more than one clipboard. These cases will happen.
You should get to know the text cursor movement commands based on expressions (rather than on lines or letters) in your text editor, such as “move the cursor forward passing one expression”, “move up one nesting level.” and so on, because they will come in handy later and because they might be used for selecting expressions.
Emacs note: In vanilla Emacs,
- the command
forward-sexp, for moving past one expression, is bound to
backward-sexp is bound to
backward-up-list, for moving up one level, is bound to
down-list, for moving down one level, is bound to