“Smart” Quotes in Emacs

smart-quotes.el smartly enables automatic insertion of correctly curled single or double quotation marks in emacs.

This is typographically nice, but can be deadly in Unicode-enabled programming languages where a
"string starting with a dumb-quote, but terminated by a smart one”
is unterminated for the parser but looks terminated for the human reader. And pressing C-v at front/end of every string gets exhausting.

Disabling smart quotes for certain modes is easy:

 (defun my/smquoteoff () (smart-quote-mode 0))
 (add-hook 'emacs-lisp-mode 'my/smquoteoff)
 (add-hook 'python-mode 'my/smquoteoff)

But what about literate programming, as for example in org-babel codeblocks? The buffer is in org-mode, definitely not a programming mode, but the blocks inside #+begin/end_src are:

* About strings
[...] Some “smart” statement about /strings/
  s = "dumbly quoted string";

org-mode has a predicate to check if point is inside such a code block, named org-in-src-block-p, but how to use it without rewriting smart-quotes.el?

Emacs' lisp advice-add to the rescue! This is Aspect-oriented programming, where a function g is wrapped in another function f. It has a :before-until “combinator”, which evals g only if f returns nil when run with g's parameters.

In this case:

(defun _my/verb-double-quote (&rest r)
	(if (org-in-src-block-p) (progn (insert-char #x22) t) nil))
(advice-add 'smart-quotes-insert-double :before-until
smart-quotes-insert-double now depends on org-in-src-block-p being false, otherwise ASCII char 0x22, i.e ", is inserted.

Single quotes are left as an ‘exercise for the reader’.

Mon, 18 Mar 2024
[/quotes] permanent link