From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Thierry Volpiatto Newsgroups: gmane.emacs.devel Subject: Re: Better indentation for elisp Date: Mon, 18 Feb 2013 21:45:42 +0100 Organization: Emacs Helm Message-ID: <877gm5gxl5.fsf@gmail.com> References: <1361217567226-278668.post@n5.nabble.com> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: ger.gmane.org 1361226413 29594 80.91.229.3 (18 Feb 2013 22:26:53 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Mon, 18 Feb 2013 22:26:53 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Feb 18 23:27:15 2013 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1U7ZAz-0007Ck-GC for ged-emacs-devel@m.gmane.org; Mon, 18 Feb 2013 23:27:09 +0100 Original-Received: from localhost ([::1]:59590 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U7ZAf-00078j-GY for ged-emacs-devel@m.gmane.org; Mon, 18 Feb 2013 17:26:49 -0500 Original-Received: from eggs.gnu.org ([208.118.235.92]:46256) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U7Xmr-0007Qw-Kv for emacs-devel@gnu.org; Mon, 18 Feb 2013 15:58:15 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1U7Xb2-0007nN-Vf for emacs-devel@gnu.org; Mon, 18 Feb 2013 15:46:01 -0500 Original-Received: from plane.gmane.org ([80.91.229.3]:52639) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U7Xb2-0007n8-LR for emacs-devel@gnu.org; Mon, 18 Feb 2013 15:45:56 -0500 Original-Received: from list by plane.gmane.org with local (Exim 4.69) (envelope-from ) id 1U7XbI-0007sv-Sh for emacs-devel@gnu.org; Mon, 18 Feb 2013 21:46:12 +0100 Original-Received: from lbe83-2-78-243-104-167.fbx.proxad.net ([78.243.104.167]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Mon, 18 Feb 2013 21:46:12 +0100 Original-Received: from thierry.volpiatto by lbe83-2-78-243-104-167.fbx.proxad.net with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Mon, 18 Feb 2013 21:46:12 +0100 X-Injected-Via-Gmane: http://gmane.org/ Original-Lines: 116 Original-X-Complaints-To: usenet@ger.gmane.org X-Gmane-NNTP-Posting-Host: lbe83-2-78-243-104-167.fbx.proxad.net User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3.50 (gnu/linux) Cancel-Lock: sha1:s7AYf1SLD7fCTg6k1yckUBT6da4= X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 80.91.229.3 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:157145 Archived-At: Sergey Mozgovoy writes: > The problem > > Standard indentation algorithm for Emacs Lisp is not perfect in some > respects. For example, it fails to indent code like this: > * > (flet ((sum (x y) > (+ x y)) > (diff (x y) > (- x y))) > ...) > * > or like this: > * > (func-1 (or arg-1 > arg-2) weird-arg > another-arg) > * > and this: > * > (let (var-1 var-2 > (x 10)) > (+ var-1 var-2)) > * > > SLIME indentation > > Those who use SLIME know that there's a contrib *slime-cl-indent* > which does some nice job of indenting Common Lisp code. Aside from > some CL-specific things (like the loop macro or tagbody), SLIME > indentation is different from that of Elisp in that it supports > arbitrarily-nesting indentation patterns rather than simple values. > > For example, here's indentation spec for *case* (quoted from > docstring for *common-lisp-indent-function*): > / > ... the function `case' has an indent property (4 &rest (&whole 2 &rest 1)), > meaning: > * indent the first argument by 4. > * arguments after the first should be lists, and there may be any number > of them. The first list element has an offset of 2, all the rest > have an offset of 2+1=3. > / > > > SLIME => Emacs Lisp > > I think we could just reuse some SLIME indentation ideas for Emacs > Lisp. The algorithm is smart enough to handle any typical Elisp > indentation, and it is kind of a generalization of the present one. > General idea is this: walk nested lists up not more than some depth > limit (*lisp-indent-maximum-backtracking*) and see what head > symbols (*car*s) of ancestor lists say about indentation. Upper > specs override what was said by more local ones. Whatever the current > indentation we have when the depth is exhausted becomes our end > result. > > One thing that I found odd in SLIME indentation is that they specify > absolute offsets (in spaces). I don't see why such a precision might > be really needed.. to my mind, indentation should better be specified > in terms of number of distinguished forms, like it is implemented now > for Elisp. Maybe I just don't get it. > > So I propose the following indentation patterns, roughly: > > * any valid value for *lisp-indent-function* symprop, meaning > is preserved. This includes: > + natural number (# of distinguished args); > + *defun* symbol which means to indent in defun-style; > + *nil* stands for "usual" indentation, i.e. indent like a > normal function call form; > + *:flat* -- new thing which tells that list should be > flat, no indentation for any args; > > * (*S* . (*P-1* *P-2* ... *P-N*)), where *S* is a simple pattern > (any of above), and all *P-i* are any other patterns (recursive > definition). > *S* specifies indentation for the enclosing list. b>P-1*, ..., *P-n* > specify > indentation for sublists, beginning from the second one ("first > function argument"); > > * (*S* . (*P-1* ... *P-N* &rest *P*)), same as above but *P* > applies to all the other sublists after *N*. > > So for example, we'd give indentation for the above-mentioned forms > like this: > * > (put 'flet 'lisp-indent-function '(1 (:flat &rest defun))) > (put 'let 'lisp-indent-function '(1 (:flat &rest 1))) > (put 'cond 'lisp-indent-function '(nil &rest :flat)) > * > (Yes, I do agree that *cond* is indented perfectly now, this was > just for the sake of example.) > > What is done so far > > I decided to just go ahead and try to write some Elisp indentation > machinery. > > Actually, it seems to work fine on my laptop for me. I'd be happy if > Emacs developers find my indentation actually useful and incorporate > some of it into Emacs. > > If someone gets really interested in the idea of improving Emacs Lisp > indentation, I'm always eager to share my work. See: http://article.gmane.org/gmane.emacs.devel/155910/match=lisp+indent+function -- Thierry Get my Gnupg key: gpg --keyserver pgp.mit.edu --recv-keys 59F29997