all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Sergey Mozgovoy <egnartsms@gmail.com>
To: Emacs-devel@gnu.org
Subject: Better indentation for elisp
Date: Mon, 18 Feb 2013 11:59:27 -0800 (PST)	[thread overview]
Message-ID: <1361217567226-278668.post@n5.nabble.com> (raw)

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.



             reply	other threads:[~2013-02-18 19:59 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-02-18 19:59 Sergey Mozgovoy [this message]
2013-02-18 20:45 ` Better indentation for elisp Thierry Volpiatto
2013-02-19  6:23   ` Sergey Mozgovoy
2013-02-19  6:55     ` Thierry Volpiatto
2013-02-19 13:53 ` Stefan Monnier
2013-02-19 15:41   ` João Távora
2013-02-20 14:55   ` Sergey Mozgovoy
2013-02-20 15:47     ` Stefan Monnier
2013-02-21 10:51       ` Sergey Mozgovoy
2013-02-21 15:31         ` Stefan Monnier
2013-02-21 15:54 ` Didier Verna
2013-02-24  8:29   ` Sergey Mozgovoy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1361217567226-278668.post@n5.nabble.com \
    --to=egnartsms@gmail.com \
    --cc=Emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.