UPDATE: since the original publication of this blog entry, Nikodemus Siivola and I have done some more work on various other aspects of Common Lisp indentation, and I must say that the result is pretty satisfactory. Nikodemus has merged all the changes into Slime, and I have done so for XEmacs. If you're an XEmacs user, you don't need to use the slime-indentation contrib to get these improvements. Simply upgrade the "prog-modes" package and load cl-indent.el
.
I have just modified XEmacs to improve the indentation of Common Lisp code. This change involves two things: the support for multiple method qualifiers in a call to defmethod
and, much more importantly, a cleaner and more flexible scheme for indenting lambda lists. The patch has also been submitted to the GNU Emacs developers. Below is a more detailed description of what you get with these changes.
Method qualifiers
Until now, only one method qualifier was understood. Below are some examples demonstrating that the one method qualifier and the argument list are indented by 4 characters, and the method's body only by 2:
(defmethod foo :around () (defmethod foo :around
do-this) ()
do-this)
(defmethod foo
:around () (defmethod foo
do-this) :around
()
do-this)
Now let's add a second method qualifier:
(defmethod foo comb :around () (defmethod foo
do-this) comb :around ()
do-this)
Woops. Neither is correct. But now, you get this instead:
(defmethod foo comb :around () (defmethod foo
do-this) comb :around ()
do-this)
Three more examples to show how confused we were:
(defmethod foo comb :around (defmethod foo comb (defmethod foo
() :around comb
do-this) () :around
do-this) ()
do-this)
And how better we just got:
(defmethod foo comb :around (defmethod foo comb (defmethod foo
() :around comb
do-this) () :around
do-this) ()
do-this)
Indeed, you can see that everything between the method's name and its body is now correctly indented by 4.
Lambda Lists
The next round of changes deals with the formatting of lambda-lists. As such, this will apply everywhere a lambda-list is expected, such as defun
, defgeneric
, defmethod
etc.
First of all, here are two examples showing that we were not very clever before:
(defun foo (mand1 mand2
&optional opt1
opt2
&rest args
&key key1 key2
(key3 val3) &aux aux1
aux2)
do-this)
(defun foo (mand1 mand2 &optional opt1
opt2
&rest args
&key key1 key2
(key3 val3) &aux aux1
aux2)
do-this)
Basically, everything was blindly aligned at the beginning of the lambda-list. Here is what you get now:
(defun foo (mand1 mand2
&optional opt1
opt2
&rest args
&key key1 key2
(key3 val3) &aux aux1
aux2)
do-this)
(defun foo (mand1 mand2 &optional opt1
opt2
&rest args
&key key1 key2
(key3 val3) &aux aux1
aux2)
do-this)
The difference is that keyword parameters are indented with respect to their corresponding keyword. The amount of indentation is provided by a new customizable user option named lisp-lambda-list-keyword-parameter-indentation
(oh boy, what a mouthful). If you prefer, you can also have the parameters vertically aligned with each other. Set the new customizable user option named lisp-lambda-list-keyword-parameter-alignment
to t
and you will get this instead:
(defun foo (mand1 mand2
&optional opt1
opt2
&rest args
&key key1 key2
(key3 val3) &aux aux1
aux2)
do-this)
(defun foo (mand1 mand2 &optional opt1
opt2
&rest args
&key key1 key2
(key3 val3) &aux aux1
aux2)
do-this)
Finally, just as you could align keyword parameters together, you can also align the keywords together. Set the new customizable user option named lisp-lambda-list-keyword-alignment
to t, and you will get this (only the second example differs):
(defun foo (mand1 mand2 &optional opt1
opt2
&rest args
&key key1 key2
(key3 val3) &aux aux1
aux2)
do-this)
These are in fact my preferred settings, although both alignment options default to nil
. Here is a final example demonstrating how you could format a long lambda-list with plenty of arguments:
(defun foo (mand1 mand2
&optional
opt1 opt2 opt3
&key
key1 key2 key3
&aux
aux1 aux2 aux3)
do-this)
These indentation problems have been a huge peeve of mine for quite a long time. I hope you will find the changes useful!