38

Let's say I have a function that looks like the following (as is often the case when printing elisp output).

(defun my-example-function () (let ((a (do-something)) (b (do-something))) (setq someone me) (with-current-buffer b (do-that (or this (and that those))) (format "%s" a))))

I would like a command that can turn that into something a human would write, such as the following.

(defun my-example-function ()
  (let ((a (do-something))
        (b (do-something)))
    (setq someone me)
    (with-current-buffer b
      (do-that (or this (and that those)))
      (format "%s" a))))

I understand that there's more than one way to format a piece of elisp code, and different human beings do it differently. Furthermore, I understand it's somewhat subjective. But it should be fairly easy to come up with a set of rules that results in code that is at least decent.

I actually tought of doing this myself a while ago, but I figured it's better to ask before I reinvent the wheel.

Note, I'm aware of the pp function, but it doesn't quite get there:

(defun my-example-function nil
  (let
      ((a
        (do-something))
       (b
        (do-something)))
    (setq someone me)
    (with-current-buffer b
      (do-that
       (or this
           (and that those)))
      (format "%s" a))))
Mark Karpov
  • 4,893
  • 1
  • 24
  • 53
Malabarba
  • 22,878
  • 6
  • 78
  • 163

3 Answers3

16

As others have suggested in comments, "formatting" can mean different things.

For indentation that is pretty conventional, try using C-M-q (command indent-pp-sexp in Lisp modes) with the cursor somewhere inside the top-level sexp that you want to re-indent (e.g. the defun sexp).

No, this is not "automatic" indentation, but it can become a habit to use it. ;-)

For things other than indentation you will need to either do it manually or roll your own "formatting" command(s) or find some existing such.

See also the Emacs manual, node Multi-line Indent and the Elisp manual, node Mode-Specific Indent.

Drew
  • 75,699
  • 9
  • 109
  • 225
  • 3
    Thanks, I'm quite happy with elisp indentation, I'm looking for something that knows when to break lines. :-) And yes I understand it's subjective. :-( – Malabarba Sep 25 '14 at 23:06
  • `M-q` (`fill-paragraph`) can sometimes be useful for line-breaking in Emacs-Lisp mode, depending on the context. But you are probably looking for alignment as well... – Drew Sep 25 '14 at 23:16
  • 2
    @Malabarba see elisp-autofmt in my answer, this wraps/unwraps lines, respecting the fill column. – ideasman42 Apr 07 '21 at 03:32
14

Here's how lispy re-formatted it for me (by pressing M at either end of the expression):

(defun my-example-function ()
  (let ((a (do-something))
        (b (do-something)))
    (setq someone me)
    (with-current-buffer b (do-that (or this (and that those)))
                         (format "%s" a))))

To get from this to the formatting that you specified, press qk C-m [.

abo-abo
  • 13,943
  • 1
  • 29
  • 43
  • ```(local-set-key (kbd "s-8") #'lispy-multiline) (local-set-key (kbd "s-*") #'lispy-oneline)``` – grettke Mar 28 '18 at 02:57
  • Why is pressing `M` does different formatting from directly executing `lispy-multiline`? – Yuki Feb 12 '21 at 19:40
8

Listing Elisp formatting tools here for completeness:

  • Elisp-Autofmt Emacs integration to run on-save.
    Formats files following this style by default (available on melpa).
  • lispy includes auto-formatting functionality (lispy on melpa)
  • ElispFormat produces idiomatic elisp, but seems to have right-shift problems - going over the fill column width (elisp-format on melpa).
  • Grind no Emacs integration (not on melpa).
  • Semantic Refactor (srefactor on melpa)
  • Emacs 29+ pp-emacs-lisp-code (built-in, an extended pretty printer intended for use with code).
Y. E.
  • 668
  • 4
  • 8
ideasman42
  • 8,375
  • 1
  • 28
  • 105
  • Has anyone tried Emacs 29 `pp-emacs-lisp-code` in macros to generate a docstring that includes the generate elisp code? It only seems able to insert text in the current buffer. – PRouleau Jan 06 '23 at 00:38
  • @ideasman42 Can you please provide documentation link regarding "pp-emacs-lisp-code"? – Refael Sheinker May 19 '23 at 12:07
  • 2
    @RefaelSheinker [pp-emacs-lisp-code in Emacs NEWS file](https://github.com/emacs-mirror/emacs/blob/156973639cc57dec47705f76f63c2ef3dc00a61d/etc/NEWS.29#L4554) (post edit is requested). – Y. E. May 19 '23 at 12:24