From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Sergey Mozgovoy Newsgroups: gmane.emacs.devel Subject: Better indentation for elisp Date: Mon, 18 Feb 2013 11:59:27 -0800 (PST) Message-ID: <1361217567226-278668.post@n5.nabble.com> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-Trace: ger.gmane.org 1361217575 12861 80.91.229.3 (18 Feb 2013 19:59:35 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Mon, 18 Feb 2013 19:59:35 +0000 (UTC) To: Emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Feb 18 20:59:57 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 1U7WsX-0001Fw-Gi for ged-emacs-devel@m.gmane.org; Mon, 18 Feb 2013 20:59:57 +0100 Original-Received: from localhost ([::1]:40539 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U7WsD-0001nz-Ke for ged-emacs-devel@m.gmane.org; Mon, 18 Feb 2013 14:59:37 -0500 Original-Received: from eggs.gnu.org ([208.118.235.92]:59460) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U7Ws7-0001nH-Ul for Emacs-devel@gnu.org; Mon, 18 Feb 2013 14:59:35 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1U7Ws5-0004WO-6O for Emacs-devel@gnu.org; Mon, 18 Feb 2013 14:59:31 -0500 Original-Received: from sam.nabble.com ([216.139.236.26]:43543) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U7Ws4-0004W7-W0 for Emacs-devel@gnu.org; Mon, 18 Feb 2013 14:59:29 -0500 Original-Received: from [192.168.236.26] (helo=sam.nabble.com) by sam.nabble.com with esmtp (Exim 4.72) (envelope-from ) id 1U7Ws3-0004Jt-7Z for Emacs-devel@gnu.org; Mon, 18 Feb 2013 11:59:27 -0800 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 216.139.236.26 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:157142 Archived-At: 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. -- View this message in context: http://emacs.1067599.n5.nabble.com/Better-indentation-for-elisp-tp278668.html Sent from the Emacs - Dev mailing list archive at Nabble.com.