Theresa O’Connor

Emacs Lisp: spotlight on format-spec

Just a quick warning: this is more for the Emacs Lisp library developer audience out there—yes, all three of you—and not really for Emacs end-users. Wait, you’re still here? OK, read on!

Emacs Lisp’s format, like C’s sprintf, allows programmers to produce formatted strings based on an input template. For example, suppose you have a variable name and you’d like to produce a string Hello, name! The relevant elisp looks very similar to the relevant C:

(format "Hello, %s!" name)

instead of

sprintf("Hello, %s!", name);

The set of valid format specifications is fixed in both C and elisp, but what if you would like to provide some kind of custom string formatting? Consider popular MUAs mutt and Gnus. Both allow their users to customize the listing of emails in a mailbox with sprintf-like syntax.1 So %s, for instance, might mean the subject of the email, and %a might mean the email’s author.

Gnus accomplishes this using format-spec.el, which ships with Gnus (and thus with Emacs). It’s really easy to use; here’s our example from before re-cast into format-spec:

* (format-spec "Hello, %u!" '((?u . "ted")))
"Hello, ted!"

Of course, the idea isn’t to use it directly like that. Your library can expose the format string as a user-customizable option, like so:

(defvar hello-format "Hello, %u!"
  "How this library should greet users.

The following characters are replaced:
%u: The username of the current user")

Several larger Emacs-based applications (like Gnus, ERC, etc.) make heavy use of format-spec; it’s a great tool for putting a lot of formatting power in your users’ hands, without scaring them too much with arcane elisp snippets for their ~/.emacs files. Try it today!


  1. For Mutt, see the documentation of index_format in §6.3 Configuration variables of the manual. For Gnus, see §8.4 Formatting Variables of the manual.