Emacs, scripting and anything text oriented.

Straight and Curved Quotes in Emacs Lisp

Kaushal Modi

A short guide for getting the single quotes rendered as expected (straight or curved) in Emacs Lisp function and variable documentation strings and message outputs.

This post is related to the curved quotes feature from Emacs 25 (September 2016), but I got inspired to write this as I was reading the NEWS file of the recently released Emacs 28.1 ✨ .. this specific part related to the shortdoc library. Turns out that I had never used shortdoc  If you also haven’t used this library before, it’s basically a “cheat sheet generator” or an aggregator of related functions grouped together with code examples and their outputs – for example, functions related to string manipulation, buffer operations, etc. It is like https://tldr.sh/ but for Emacs Lisp functions. . So as I was reading through the help for various user-facing shortdoc functions, C-h f shortdoc-add-function led me to this:

Figure 1: Notice the curved closing single quotations in the Emacs Lisp example in that doc string

Figure 1: Notice the curved closing single quotations in the Emacs Lisp example in that doc string

We don’t have curved quotes in Emacs Lisp syntax 🧐 .. So I look up the source of shortdoc-add-function:

1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
(defun shortdoc-add-function (group section elem)
  "Add ELEM to shortdoc GROUP in SECTION.
If GROUP doesn't exist, it will be created.
If SECTION doesn't exist, it will be added.

Example:

  (shortdoc-add-function
    'file \"Predicates\"
    '(file-locked-p :no-eval (file-locked-p \"/tmp\")))"
Code Snippet 1: Unescaped single quotes in Emacs Lisp documentation strings

The documentation looks correct at first glance, but there’s a minor problem. This post talks about how to fix that documentation and then a bit more on how to deal with auto-conversion to curved quotes.

Emacs 25 – Curved quotes rendering feature #

Emacs 25 had landed with one of my favorite new features — the auto-rendering of grave accents (`) and straight quotes ('​) to curved (or curly) quotes (, ). From its NEWS file:

New variable ’text-quoting-style’ to control how Emacs translates quotes. Set it to ‘curve’ for curved single quotes, to ‘straight’ for straight apostrophes, and to ‘grave’ for grave accent and apostrophe. The default value nil acts like ‘curve’ if curved single quotes are displayable, and like ‘grave’ otherwise. The new variable affects display of diagnostics and help, but not of info. As the variable is not intended for casual use, it is not a user option.

I like the rendering to curved quotes because it improves the readability of documentation strings in the ∗Help∗ buffers (C-h v, C-h f, etc.), and they look great in ∗Messages∗ buffer. It helps differentiate between typographical use of quotes like in ‘Hello’ versus the straight quotes used in Emacs Lisp syntax like (setq foo 'some-symbol) or the usage of grave accents like (setq foo `(,(+ 1 1))).

This feature renders grave accents (`) to and straight quotes ('​) to by default. But there would be times when you would want to literally print grave accents or straight quotes in ∗Help∗ and ∗Messages∗ buffers.

Preventing curved quotes in documentation strings #

In documentation strings, some times you would want to show literal straight quotes or grave accents, for instance, when showing some example Emacs Lisp code snippets in there. Above image shows one of such examples.

More than the visual inaccuracy of seeing curved quoted where straight quotes should be, if someone copies that code to try it out, it will not work !

This should be fixed by escaping the ' characters.

Emacs Lisp uses a special escaping sequence in documentation strings: \\=.

  • Escape ` using \\=`.
  • Escape ' using \\='.

Below we see Code Snippet 1 after this fix:

1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
(defun shortdoc-add-function (group section elem)
  "Add ELEM to shortdoc GROUP in SECTION.
If GROUP doesn't exist, it will be created.
If SECTION doesn't exist, it will be added.

Example:

  (shortdoc-add-function
    \\='file \"Predicates\"
    \\='(file-locked-p :no-eval (file-locked-p \"/tmp\")))"
Code Snippet 2: Correctly escaped single quotes in Emacs Lisp documentation strings

.. and now the straight quotes get rendered as straight quotes:

Figure 2: Correctly escaped single quotes in documentation strings

Figure 2: Correctly escaped single quotes in documentation strings

Preventing curved quotes in messages #

The same auto-rendering of curved quotes happens in the messages that get printed to the ∗Messages∗ buffer and Echo Area as well. So the below behavior where ‘Hi’ gets printed is expected and nice:

(message "`Hi'")      ;=> "‘Hi’"
Code Snippet 3: message auto-converting `Hi' to ‘Hi’

But if someone does below, the rendered ’Hi’ looks pretty odd:

(message "'Hi'")      ;=> "’Hi’"
Code Snippet 4: message auto-converting 'Hi' to ’Hi’ 😮

I had come across this surprise rendering in Emacs 25 and had raised this issue then. From Paul Eggert’s reply, I learned that to prevent this curved quote conversion, we should make the message function print the string processed by the format function and not the string directly. You could do this ..

(message "%s" (format "%s" "'Hi'")) ;=>"'Hi'"
Code Snippet 5: Passing format formatted string to message

But below will do the same thing and is much easier to type:

(message "%s" "'Hi'") ;=> "'Hi'"
(message "%s" "`Hi'") ;=> "`Hi'"
Code Snippet 6: Implicit passing of a string to format for formatting, before getting printed by message

Summary #

Table 1: Summary of techniques for enforcing straight quotes and grave accents in printed messages and documentation strings
DescriptionSolutionOutcome
Render ' in docstringdoc string snippet: "foo \\='bar"foo 'bar
Render ` in docstringdoc string snippet: "foo \\=`bar"foo `bar
Print ' as '(message "%s" "'foo")'foo
Print ` as `(message "%s" "`foo")`foo

By the way, I submitted a patch for fixing the escaping of straight quotes in shortdoc-add-function documentation string  I planned to fix just this straight quote escaping issue, but then I also ended up slightly improving the documentation of the (FUNC :eval EVAL) and other forms used for adding a function’s documentation to shortdoc. in debbugs # 54782 and now it’s in the emacs master branch! 🎉

References #

Fixing curved quotes conversion in documentation strings
Fixing curved quotes conversion in printed messages