From: Thierry Volpiatto <thierry.volpiatto@gmail.com>
To: emacs-devel@gnu.org
Subject: Re: Better indentation for elisp
Date: Mon, 18 Feb 2013 21:45:42 +0100 [thread overview]
Message-ID: <877gm5gxl5.fsf@gmail.com> (raw)
In-Reply-To: 1361217567226-278668.post@n5.nabble.com
Sergey Mozgovoy <egnartsms@gmail.com> 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
next prev parent reply other threads:[~2013-02-18 20:45 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-02-18 19:59 Better indentation for elisp Sergey Mozgovoy
2013-02-18 20:45 ` Thierry Volpiatto [this message]
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=877gm5gxl5.fsf@gmail.com \
--to=thierry.volpiatto@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.