Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 135
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 135
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 187
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 188
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 189
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 194
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 195
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 196
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 197
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 241
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 264
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 269
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 275
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 285
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 286
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 296
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 297
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 298
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 308
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 309
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 310
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 311
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 321
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 322
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 323
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 324
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 325
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 497
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 527
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 540
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 587
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 626
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 668
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 668
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 670
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 673
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 682
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 688
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 693
Deprecated: Array and string offset access syntax with curly braces is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php on line 699
Deprecated: Function get_magic_quotes_gpc() is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.http.php on line 410
Deprecated: Function get_magic_quotes_gpc() is deprecated in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.http.php on line 410
Warning: Cannot modify header information - headers already sent by (output started at /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php:309) in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.http.php on line 272
Warning: Cannot modify header information - headers already sent by (output started at /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php:309) in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.http.php on line 274
Warning: Cannot modify header information - headers already sent by (output started at /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php:309) in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.http.php on line 274
Warning: Cannot modify header information - headers already sent by (output started at /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php:309) in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.http.php on line 274
Warning: Cannot modify header information - headers already sent by (output started at /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php:309) in /home/didierve/didierverna.net/blog/inc/public/lib.urlhandlers.php on line 110
Warning: Cannot modify header information - headers already sent by (output started at /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php:309) in /home/didierve/didierverna.net/blog/inc/public/lib.urlhandlers.php on line 130
Warning: Cannot modify header information - headers already sent by (output started at /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.json.php:309) in /home/didierve/didierverna.net/blog/inc/libs/clearbricks/common/lib.http.php on line 295 Didier Verna's Scientific Blog - Tag - indentationDidier Verna's scientific blog: Lisp, Emacs, LaTeX and random stuff.2024-01-31T17:45:28+00:00Didier Vernaurn:md5:a22c53786aff986a2da4c770c233a8f9DotclearOne more indentation hackurn:md5:3b8c24fe3792a983a2358d415d869534Wednesday, July 20 2011Wednesday, July 20 2011Didier VernaLispCommon LispEmacs Lispindentationtext editing <p>Here's yet another indentation hack that I came up with recently.</p>
<p>All the work done by Nikodemus on the Slime indentation contrib is pretty cool, especially the notion of indentation style (though I wish the styles were Custom variables, but that is another story). I tend to use indentation styles for global, maybe collaborative preferences, but on several occasions however, I find that this approach has a couple of drawbacks.</p>
<ul>
<li>One of them is that the indentation information is far away from the corresponding symbol, in a separate file. If you change a function's prototype for instance, you may also need to load the file(s) in which the corresponding style(s) is (are) defined and edit them.</li>
<li>The other problem is that if you want to let other people edit your source code and honor your indentation style, you also need to provide them with the style definition, and they need to load it separately.</li>
</ul>
<p>For those reasons, I tend to think that the indentation style approach is not very well suited for project-specific indentation settings. What I would like is to provide indentation information close to the function definition, and also to have that information automatically available when <em>anyone</em> loads the project into Slime. Here's a way to do it.
<br />
<br /></p>
<p>The key to success here is the function <code>swank:eval-in-emacs</code> which, as its name suggests, sends some Emacs Lisp code to your (X)Emacs session for evaluation. This function effectively allows you to trigger some Emacs Lisp computation from a Common Lisp file. Remember that indentation information is stored in the <code>common-lisp-indent-function</code> property of a symbol. The function <code>clindent</code> below does this:</p>
<pre class="lisp lisp" style="font-family:inherit"><span style="color: #66cc66;">(</span><span style="color: #b1b100;">defun</span> clindent <span style="color: #66cc66;">(</span><span style="color: #b1b100;">symbol</span> indent<span style="color: #66cc66;">)</span>
<span style="color: #ff0000;">"Set SYMBOL's indentation to INDENT in (X)Emacs.
This function sets SYMBOL's common-lisp-indent-function property.
If INDENT is a symbol, use its indentation definition.
Otherwise, INDENT is considered as an indentation definition."</span>
<span style="color: #66cc66;">(</span><span style="color: #b1b100;">when</span> <span style="color: #66cc66;">(</span><span style="color: #b1b100;">and</span> <span style="color: #66cc66;">(</span><span style="color: #b1b100;">member</span> <span style="color: #66cc66;">:</span><span style="color: #555;">swank</span> *features*<span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">(</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">(</span><span style="color: #66cc66;">(</span>configuration
<span style="color: #66cc66;">(</span>find-<span style="color: #b1b100;">symbol</span> <span style="color: #ff0000;">"MY.PACKAGE.CONFIGURATION"</span> <span style="color: #66cc66;">:</span><span style="color: #555;">cl-user</span><span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">(</span><span style="color: #b1b100;">when</span> <span style="color: #66cc66;">(</span><span style="color: #b1b100;">and</span> configuration <span style="color: #66cc66;">(</span><span style="color: #b1b100;">boundp</span> configuration<span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">(</span><span style="color: #b1b100;">getf</span> <span style="color: #66cc66;">(</span>symbol-<span style="color: #b1b100;">value</span> configuration<span style="color: #66cc66;">)</span> <span style="color: #66cc66;">:</span><span style="color: #555;">swank-eval-in-emacs</span><span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">(</span><span style="color: #b1b100;">funcall</span> <span style="color: #66cc66;">(</span><span style="color: #b1b100;">intern</span> <span style="color: #ff0000;">"EVAL-IN-EMACS"</span> <span style="color: #66cc66;">:</span><span style="color: #555;">swank</span><span style="color: #66cc66;">)</span>
`<span style="color: #66cc66;">(</span>put '<span style="color: #66cc66;">,</span><span style="color: #b1b100;">symbol</span> 'common-lisp-indent-<span style="color: #b1b100;">function</span>
<span style="color: #66cc66;">,</span><span style="color: #66cc66;">(</span><span style="color: #b1b100;">if</span> <span style="color: #66cc66;">(</span><span style="color: #b1b100;">symbolp</span> indent<span style="color: #66cc66;">)</span>
`<span style="color: #66cc66;">(</span><span style="color: #b1b100;">get</span> '<span style="color: #66cc66;">,</span>indent 'common-lisp-indent-<span style="color: #b1b100;">function</span><span style="color: #66cc66;">)</span>
`'<span style="color: #66cc66;">,</span>indent<span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span>
t<span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span></pre>
<p>As explained in the docstring, this function will ask (X)Emacs to put <code>SYMBOL</code>'s <code>common-lisp-indent-function</code> property to a definition, either provided directly, or retrieved from another symbol. For example, if your package defines an <code>econd</code> macro, you may want to call it like this:</p>
<pre class="lisp lisp" style="font-family:inherit"><span style="color: #66cc66;">(</span>clindent 'econd '<span style="color: #b1b100;">cond</span><span style="color: #66cc66;">)</span></pre>
<p>This function ensures that Swank is actually available before using it (first condition in the <code>and</code> clause). I will explain the other weird bits later on.</p>
<p>The next question is when exactly do we want to call this function? The answer is: pretty much on all occasions. Your code might be loaded from source and interpreted, or it might be compiled. But then, it might be compiled within or outside a Slime environment. In any case, you want your indentation information to be sent to (X)Emacs everytime it's possible. So obviously, we're gonna wrap this function in an <code>eval-when</code> form thanks to a macro. This is also a good opportunity to save some quoting.</p>
<pre class="lisp lisp" style="font-family:inherit"><span style="color: #66cc66;">(</span><span style="color: #b1b100;">defmacro</span> defindent <span style="color: #66cc66;">(</span><span style="color: #b1b100;">symbol</span> indent<span style="color: #66cc66;">)</span>
<span style="color: #ff0000;">"Set SYMBOL's indentation to INDENT in (X)Emacs.
SYMBOL and INDENT need not be quoted.
See CLINDENT for more information."</span>
`<span style="color: #66cc66;">(</span>eval-<span style="color: #b1b100;">when</span> <span style="color: #66cc66;">(</span><span style="color: #66cc66;">:</span><span style="color: #555;">compile-toplevel</span> <span style="color: #66cc66;">:</span><span style="color: #555;">execute</span> <span style="color: #66cc66;">:</span><span style="color: #555;">load-toplevel</span><span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">(</span>clindent '<span style="color: #66cc66;">,</span><span style="color: #b1b100;">symbol</span> '<span style="color: #66cc66;">,</span>indent<span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span></pre>
<p>And now, right on top of your <code>econd</code> definition, you can just say this:</p>
<pre class="lisp lisp" style="font-family:inherit"><span style="color: #66cc66;">(</span>defindent econd <span style="color: #b1b100;">cond</span><span style="color: #66cc66;">)</span></pre>
<p>Now here's one final step. If your package uses its own readtable, it's even more convenient to define a reader-macro for indentation information. I choose <code>#i</code>:</p>
<pre class="lisp lisp" style="font-family:inherit"><span style="color: #66cc66;">(</span><span style="color: #b1b100;">defun</span> i-reader <span style="color: #66cc66;">(</span>stream subchar arg<span style="color: #66cc66;">)</span>
<span style="color: #ff0000;">"Read an argument list for the DEFINDENT macro."</span>
<span style="color: #66cc66;">(</span>declare <span style="color: #66cc66;">(</span>ignore subchar arg<span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">(</span><span style="color: #b1b100;">cons</span> 'defindent <span style="color: #66cc66;">(</span>read stream<span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">(</span>set-dispatch-macro-character #\# #\i #'i-reader *readtable*<span style="color: #66cc66;">)</span></pre>
<p>And now, the code in my package will look like this:</p>
<pre class="lisp lisp" style="font-family:inherit">#i<span style="color: #66cc66;">(</span>econd <span style="color: #b1b100;">cond</span><span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">(</span><span style="color: #b1b100;">defmacro</span> econd #<span style="color: #66cc66;">|...|</span>#<span style="color: #66cc66;">)</span></pre>
<p>Pretty cool, eh?
<br />
<br />
All right. We still have two weirdos to explain in the <code>clindent</code> function.</p>
<p>First, you noticed that the function's computation is conditionalized on the existence of a <code>cl-user::my.package.configuration</code> variable, which actually stores a property list of various compiling or loading options for this package. The option we're interested in is <code>:swank-eval-in-emacs</code>, which must be set to non-nil. Here's why. The execution of Emacs Lisp code from Swank is (rightfully) considered as a security risk so it is disabled by default. If you want to authorize that, you need to set the (Emacs) variable <code>slime-enable-evaluate-in-emacs</code> to <code>t</code>. Otherwise, calling <code>swank:evaluate-in-emacs</code> is like calling 911. So we have a chicken-and-egg problem here: if we want to avoid an error in <code>clindent</code>, we would need to check the value of this variable, but in order to do that, we would need to evaluate something in (X)Emacs ;-)</p>
<p>The solution I choose is hence to disable the functionality by default, and document the fact that if people want to use my indentation information, they need to set <strong>both</strong> the Slime variable and my package-specific option to non-nil before loading the package (possibly setting them back to nil afterwards). They also need to trust that I'm not going to inject anything suspicious into their (X)Emacs session at the same time...
<br />
<br /></p>
<p>The last bit we need to explain is the final <code>t</code> argument passed to <code>swank:eval-in-emacs</code>. The corresponding parameter is called <code>nowait</code> in the function's prototype. It has something to do with asynchronous computation, and in fact, I don't really know what's going on under the hood, but what I do know is that if you set it to <code>t</code>, Swank doesn't care about the return value of your form anymore, which is fine because we're only doing a side effect. On the other hand, if you omit that parameter, Swank will try to interpret the return value in some way, and you will most probably get a serialization error. Indeed, the return value is the indentation definition itself, so for example, <code>(&rest (&whole 2 &rest 1))</code> doesn't make (Common Lisp) sense.
<br />
<br /></p>
<p>That's it. Happy indenting!</p>https://www.didierverna.net/blog/index.php?post/2011/07/20/One-more-indentation-hack#comment-formhttps://www.didierverna.net/blog/index.php?feed/navlang:en/atom/comments/88Common Lisp indentation in XEmacsurn:md5:2803116969e81d6a12f96c192a9ac18fFriday, May 6 2011Friday, May 6 2011Didier VernaLispCommon Lispindentationtext editingXEmacs <p>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 <code>cl-indent.el</code>.</p>
<p>I have just modified <a href="http://www.xemacs.org">XEmacs</a> to improve the indentation of Common Lisp code. This change involves two things: the support for multiple method qualifiers in a call to <code>defmethod</code> 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.</p>
<h2>Method qualifiers</h2>
<p>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:</p>
<pre>(defmethod foo :around () (defmethod foo :around
do-this) ()
do-this)
(defmethod foo
:around () (defmethod foo
do-this) :around
()
do-this)</pre>
<p>Now let's add a second method qualifier:</p>
<pre>(defmethod foo comb :around () (defmethod foo
do-this) comb :around ()
do-this)</pre>
<p>Woops. Neither is correct. But now, you get this instead:</p>
<pre>(defmethod foo comb :around () (defmethod foo
do-this) comb :around ()
do-this)</pre>
<p>Three more examples to show how confused we were:</p>
<pre>(defmethod foo comb :around (defmethod foo comb (defmethod foo
() :around comb
do-this) () :around
do-this) ()
do-this)</pre>
<p>And how better we just got:</p>
<pre>(defmethod foo comb :around (defmethod foo comb (defmethod foo
() :around comb
do-this) () :around
do-this) ()
do-this)</pre>
<p>Indeed, you can see that everything between the method's name and its body is now correctly indented by 4.</p>
<h2>Lambda Lists</h2>
<p>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 <code>defun</code>, <code>defgeneric</code>, <code>defmethod</code> etc.
First of all, here are two examples showing that we were not very clever before:</p>
<pre>(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)</pre>
<p>Basically, everything was blindly aligned at the beginning of the lambda-list. Here is what you get now:</p>
<pre>(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)</pre>
<p>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 <code>lisp-lambda-list-keyword-parameter-indentation</code> (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 <code>lisp-lambda-list-keyword-parameter-alignment</code> to <code>t</code> and you will get this instead:</p>
<pre>(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)</pre>
<p>Finally, just as you could align keyword parameters together, you can also align the keywords together. Set the new customizable user option named <code>lisp-lambda-list-keyword-alignment</code> to t, and you will get this (only the second example differs):</p>
<pre>(defun foo (mand1 mand2 &optional opt1
opt2
&rest args
&key key1 key2
(key3 val3) &aux aux1
aux2)
do-this)</pre>
<p>These are in fact my preferred settings, although both alignment options default to <code>nil</code>. Here is a final example demonstrating how you could format a long lambda-list with plenty of arguments:</p>
<pre>(defun foo (mand1 mand2
&optional
opt1 opt2 opt3
&key
key1 key2 key3
&aux
aux1 aux2 aux3)
do-this)</pre>
<p>These indentation problems have been a huge peeve of mine for quite a long time. I hope you will find the changes useful!</p>https://www.didierverna.net/blog/index.php?post/2011/05/06/Common-Lisp-indentation-in-XEmacs#comment-formhttps://www.didierverna.net/blog/index.php?feed/navlang:en/atom/comments/81