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))))
3
  • 5
    Does this help? Elisp Formatting 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
    Sep 25, 2014 at 22:27
  • @King Thanks, it's certainly relevant.
    – Malabarba
    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.

3
  • 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, 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
    Sep 25, 2014 at 23:16
  • 2
    @Malabarba see elisp-autofmt in my answer, this wraps/unwraps lines, respecting the fill column.
    – ideasman42
    Apr 7, 2021 at 3: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 [.

2
  • (local-set-key (kbd "s-8") #'lispy-multiline) (local-set-key (kbd "s-*") #'lispy-oneline)
    – grettke
    Mar 28, 2018 at 2:57
  • Why is pressing M does different formatting from directly executing lispy-multiline?
    – Yuki
    Feb 12, 2021 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).
3
  • 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 6 at 0:38
  • @ideasman42 Can you please provide documentation link regarding "pp-emacs-lisp-code"? May 19 at 12:07
  • 2
    @RefaelSheinker pp-emacs-lisp-code in Emacs NEWS file (post edit is requested).
    – Y. E.
    May 19 at 12:24

Your Answer

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

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