Faces
We can play a few cool tricks with different faces in Emacs. This is mainly interesting in graphical emacs. This file holds most of the faces-related configuration.
Defaults
The following variables (when set in, i.e., ~/.emacs-site.el
) let us override the face attributes for some faces:
do.faces/default-face-attrs
do.faces/comment-face-attrs
do.faces/sans-face-attrs
do.faces/serif-face-attrs
(defvar do.faces/serif-face-attrs nil "An optional list of face attributes for the serif face used in the `toggle-serif' function.") (defvar do.faces/sans-face-attrs nil "An optional list of face attributes for the sans face used in the `sans-font' function.") (defvar do.faces/default-face-attrs nil "An optional list of face attributes for the default face.") (defvar do.faces/default-face-attrs nil "An optional list of face attributes for the comment face.")
This next block sets up the default face and the comment face
(defun do.faces/set-face-attrs-global (face attrs) "Set all attributes of FACE to as defined in ATTRS." (apply #'set-face-attribute (append `(,face nil) attrs))) (let ((default-attrs (if (bound-and-true-p do.faces/default-face-attrs) do.faces/default-face-attrs (list :family "DejaVu Sans Mono" :height 120))) (comment-attrs (if (bound-and-true-p do.faces/comment-face-attrs) do.faces/comment-face-attrs (list :slant 'italic :weight 'semibold)))) ;; configure the default and comment face (do.faces/set-face-attrs-global 'default default-attrs) (do.faces/set-face-attrs-global 'font-lock-comment-face comment-attrs) ;; make doc face less offensive (setq font-lock-doc-face font-lock-comment-face))
Minibuffer
(set-face-attribute 'minibuffer-prompt nil :weight 'bold :slant 'italic :foreground (face-attribute 'font-lock-keyword-face :foreground))
Serif font for text
I want to be able to toggle a variable-width "writing font" with serifs for a
buffer in which I'm mainly composing text. This is particularly comfortable
when editing \(\LaTeX\) or org-mode
source files.
First, whenever we turn on the serif font, there could be faces where we want
to preserve the monospace font (usually all of the markup commands and math
blocks). These should be listed in the variable
do.faces/serif-preserve-defaults-list
.
(defvar do.faces/serif-preserve-defaults-list nil "A list holding the faces that preserve the default family and height when TOGGLE-SERIF is used.") (setq do.faces/serif-preserve-defaults-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 org-block-end-line org-block org-date org-property-value ;; 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))
The following interactive function can then be used to toggle the faces of the
current buffer to a mix of serif and monospace fonts. Remember, the face that
is used for serifs is specified using do.faces/serif-face-attrs
.
(defun do.util/get-plist-keys (plist &rest k) "Return a list of all the keys of plist PLIST." (if plist (do.util/get-plist-keys (cddr plist) (append (car k) (list (car plist)))) (car k))) (defun toggle-serif (&optional show-echo) "Change the default face of the current buffer to the serif face specified by `do.faces/serif-face-attrs'." (interactive) (when (display-graphic-p) ;; this is only for graphical emacs ;; the serif font familiy and height, save the default attributes (let* ((serif-attrs (if (bound-and-true-p do.faces/serif-face-attrs) do.faces/serif-face-attrs (list :family "Source Serif Pro" :height (round (* 1.2 (face-attribute 'default :height)))))) (default-attrs (mapcan #'(lambda (key) (list key (face-attribute 'default key))) (do.util/get-plist-keys serif-attrs)))) (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 (apply #'face-remap-add-relative (cons 'default serif-attrs))) ;; keep previously defined monospace fonts the same (dolist (face do.faces/serif-preserve-defaults-list) (add-to-list 'preserve-default-cookies-list (apply #'face-remap-add-relative (cons face default-attrs)))) (when show-echo (message "Turned on serif writing font."))) ;; else 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) (when show-echo (message "Restored default fonts.")))))))
Sans-serif font for code
Sometimes I just want to write code with a variable-width Sans Serif font. This
function is very similar to the one above. the only difference here is that we
are not doing the re-mapping business. Instead, every face gets remapped to the
one specified in do.faces/sans-face-attrs
.
(defun sans-font () "Change the default face of this buffer to use the sans face specified by `do.faces/sans-face-attrs'." (interactive) (when (display-graphic-p) (let ((sans-attrs (if (bound-and-true-p do.faces/sans-face-attrs) do.faces/sans-face-attrs (list :family "Fira Sans" :height (round (* 1.1 (face-attribute 'default :height))) :weight 'bold)))) (if (not (bound-and-true-p default-cookie-sans)) ;; remap default face to serif (progn (make-local-variable 'default-cookie-sans) (setq default-cookie-sans (apply #'face-remap-add-relative (cons 'default do.faces/sans-face-attrs)))) ;; else undo changes (progn (face-remap-remove-relative default-cookie-sans) (setq default-cookie-sans nil) (message "Restored default fonts."))))))