# Variable-width Serif Fonts when editing plain text in Emacs

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)))
;; remap default face to serif
'default :family serif-fam :height serif-height))
;; keep previously defined monospace fonts the same
(dolist (face serif-preserve-default-list)
face :family default-fam :height default-height)))
(message "Turned on serif writing font."))
;; undo changes

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: