Variable-width Serif Fonts when editing plain text in Emacs
Published: July 06, 2015
I edit a lot of \(\LaTeX\) documents using AUCTeX in Emacs. Since I believe that
serif fonts like Times New Roman are a lot easier to read than monospaced
fonts, I wanted to be able to view and edit text in an emacs buffer using a
variable-width, serif font. After 20 minutes of elisp hacking during lunch, I
came up with toggle-serif
, a small elisp function that does exactly what I
want.
When invoked, toggle-serif
changes the default font family of the buffer to
Liberation Serif. The only problem I had was that I wanted to preserve the
default monospace fonts for some faces, for example verbatim code snippets or
markup commands.
For this reason, toggle-serif
keeps the default
font
family for every font that is listed in the variable
serif-preserve-default-list
. To set this variable, we need code like the
following in our emacs configuration:
(defvar serif-preserve-default-list nil "A list holding the faces that preserve the default family and height when TOGGLE-SERIF is used.") (setq serif-preserve-default-list '(;; LaTeX markup font-latex-math-face font-latex-sedate-face font-latex-warning-face ;; org markup org-latex-and-related org-meta-line org-verbatim org-block-begin-line ;; syntax highlighting using font-lock font-lock-builtin-face font-lock-comment-delimiter-face font-lock-comment-face font-lock-constant-face font-lock-doc-face font-lock-function-name-face font-lock-keyword-face font-lock-negation-char-face font-lock-preprocessor-face font-lock-regexp-grouping-backslash font-lock-regexp-grouping-construct font-lock-string-face font-lock-type-face font-lock-variable-name-face font-lock-warning-face))
After specifying the faces we want to preserve, we can use
toggle-serif
:
(defun toggle-serif () "Change the default face of the current buffer to use a serif family." (interactive) (when (display-graphic-p) ;; this is only for graphical emacs ;; the serif font familiy and height, save the default attributes (let ((serif-fam "Liberation Serif") (serif-height 120) (default-fam (face-attribute 'default :family)) (default-height (face-attribute 'default :height))) (if (not (bound-and-true-p default-cookie)) (progn (make-local-variable 'default-cookie) (make-local-variable 'preserve-default-cookies-list) (setq preserve-default-cookies-list nil) ;; remap default face to serif (setq default-cookie (face-remap-add-relative 'default :family serif-fam :height serif-height)) ;; keep previously defined monospace fonts the same (dolist (face serif-preserve-default-list) (add-to-list 'preserve-default-cookies-list (face-remap-add-relative face :family default-fam :height default-height))) (message "Turned on serif writing font.")) ;; undo changes (progn (face-remap-remove-relative default-cookie) (dolist (cookie preserve-default-cookies-list) (face-remap-remove-relative cookie)) (setq default-cookie nil) (setq preserve-default-cookies-list nil) (message "Restored default fonts."))))))
The end result is pretty cool: Regular text is shown using the serif font,
while code snippets and markup are still using the default monospaced font. A
picture is worth a thousand words, so here is a screenshot of me writing this
blog post using markdown-mode
:
Another small battle in the fight against word processors seems won…
Dennis