: Learning GNU Emacs, 3rd Edition

9.8.1 Indentation in Lisp Modes

9.8.1 Indentation in Lisp Modes

The Lisp modes provide "flashing" of matching left parentheses; if the matching parenthesis is outside of the current window, the line it is on appears in the minibuffer. The Lisp modes also provide indentation via the Tab key and C-j for newline-and-indent (except in Lisp interaction mode, described later in this chapter). The indentation style supported by the Lisp modes "knows" a lot about Lisp keywords and list syntax; unfortunately, it is not easily customized.[67]

Here is an example, a Lisp equivalent of the "times" C function shown earlier in the chapter, that illustrates the indentation style:

(defun times (x y)
(let ((i 0)
(result 0))
(while (< i x)
(setq result (+ result y)
i (1+ i)))
result))

The basic indentation value is 2; this value is used whenever code on the next line goes down a level in nesting. For example, the body of the function, after the line containing defun, is indented by 2. The (while... and result)) lines are indented by 2 with respect to the let because they are the body of the block let introduces.

Things like defun, let, and while are function calls, even though they act like keywords. The indentation convention for function calls is that if there are arguments on lines after the line where the function name and first argument appear, the additional arguments line up with the first one. In other words, this has the form:

(function-name arg1
arg2
arg3
...)

The multiple arguments to setq in the preceding function provide another example of this.

However, the indentation of the line (result 0) shows that something a bit different happens with lists that are not function calls. The list in question is actually ((i 0) (result 0)), which is a list with two elements (both of which are also lists). The indentation style supported by the Lisp modes lines up these two elements.

Even though keyword-like terms such as let and while are actually function calls, the Lisp modes "understand" these functions to the extent that special indentation conventions are set up for them. For example, if we were to put the condition for the while-loop on a separate line and press Tab to indent it properly, the result would be:

(while
(< i x)
(setq result (+ result y)
i (1+ i)))

Similar things happen with if and cond control structures; Chapter 11 contains properly indented examples.

Another remark about indentation conventions: the Lisp modes are geared toward a style in which multiple right parentheses are put on the same line immediately following each other, instead of on separate lines. For example, the line i (1+ i))) contains right parentheses that close off the 1+ function, the setq, and the while respectively. If you prefer, you can put your closing parentheses on separate lines, but if you press Tab to indent them, they won't line up properly with their matching open parentheses; you have to indent them manually.

In addition to the Tab and C-j commands for indentation, the Lisp modes support the command C-M-q (for indent-sexp), which indents every line in the S-expression just following the cursor. You can use this command, for example, to indent an entire function definition: just put the cursor right before the defun and type C-M-q.


: 0.253. /Cache: 3 / 1