41

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))))
3
  • 5
    Does this help? Elisp Formatting Commented Sep 25, 2014 at 22:23
  • Formatting is necessarily subjective. I'm not sure you could do better than a slightly better version of pp.
    – shosti
    Commented Sep 25, 2014 at 22:27
  • @King Thanks, it's certainly relevant.
    – Malabarba
    Commented Sep 25, 2014 at 23:22

3 Answers 3

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.

4
  • 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
    Commented Sep 25, 2014 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
    Commented Sep 25, 2014 at 23:16
  • 2
    @Malabarba see elisp-autofmt in my answer, this wraps/unwraps lines, respecting the fill column.
    – ideasman42
    Commented Apr 7, 2021 at 3:32
  • Let's say I just did C-x h to mark the whole buffer. Now what might one use? Commented May 31 at 4:03
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 [.

2
  • (local-set-key (kbd "s-8") #'lispy-multiline) (local-set-key (kbd "s-*") #'lispy-oneline)
    – grettke
    Commented Mar 28, 2018 at 2:57
  • Why is pressing M does different formatting from directly executing lispy-multiline?
    – Yuki
    Commented Feb 12, 2021 at 19:40
11

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).
4
  • 1
    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
    Commented Jan 6, 2023 at 0:38
  • 1
    @ideasman42 Can you please provide documentation link regarding "pp-emacs-lisp-code"? Commented May 19, 2023 at 12:07
  • 3
    @RefaelSheinker pp-emacs-lisp-code in Emacs NEWS file (post edit is requested).
    – Y. E.
    Commented May 19, 2023 at 12:24
  • Well it turns out pp-emacs-lisp-code exists, but is not even an interactive function. Commented May 31 at 4:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.