The standard text-scale
mode provides functions to increase and
decrease font sizes. But as near as I can tell, it only works on the
default font. I often have buffers with several faces and find it
annoying that the standard functions don’t change all the faces.
It’s quite possible that someone else has done a better job of this. I found a stack overflow question that seemed relevant, but after playing with it for a bit, I couldn’t see how to apply it to an arbitrarily large set of faces.
This README file is a literate programming version of emacs-gfs.el
.
Do not edit the emacs lisp file directly.
So as an amusement this evening, I decided to write some functions that would “brute force” it. First, I work out a list of all the fonts that should be scaled: that’s all fonts that have an explicit height except the ones explicitly excluded.
(defun gfs/resizeable-faces ()
"Return the set of faces that can be resized.
A face can be resized if it is not in the list of ignorable
faces and has an explicit height."
(let ((faces (face-list))
(resize '()))
(while faces
(if (and (not (member (car faces) gfs/resizeable-ignore-faces))
(integerp (face-attribute (car faces) :height)))
(setq resize (append resize (list (car faces)))))
(setq faces (cdr faces)))
resize))
I added a list of excluded fonts in an effort to avoid scaling the mode line and the minibuffer. It’s only been a partial success because I haven’t yet worked out what face is used for the minibuffer.
(defvar gfs/resizeable-ignore-faces
'(mode-line-buffer-id
mode-line-emphasis
mode-line-highlight
mode-line-inactive
mode-line)
"Faces named in this list will not be scaled.")
Because faces inherit, if we want to avoid scaling some faces, we have to make sure that they have a fixed size. Generally, this means following the inheritance chain until we find a face with a specified size.
If we bottom out and don’t find any size, we have to have a default, so here it is:
(defvar gfs/default-face-height 180
"Default height for faces with no explicit height.")
I have no idea how generally useful “180” is. It works for me, but YMMV.
The gfs/magnify-factor
controls how much scaling is applied.
(defvar gfs/magnify-factor 1.2
"The scaling factor.
Scaling is accomplished by multiplying (or dividing) the face
:height by this factor.")
The gfs/face-min-height
and gfs/face-max-height
control the magnification
limits. These are aribrary values. The face-remap.el
library attempts to compute
practical limits from the font and display size, but I haven’t bothered.
(defvar gfs/face-min-height 100
"The minimum face :height.
If an attempt is made to scale the face height below this
threshold, this value will be used.")
(defvar gfs/face-max-height 1000
"The maximum face :height.
If an attempt is made to scale the face height above this
threshold, this value will be used.")
There’s a practical consideration in the scaling limits. Scaling by a common factor preserves the relative sizes of the faces until the limits are reached. Crossing either of the limits, normalizes faces to the same size and the relative scale is irretrievably lost.
(defun gfs/shrink-faces ()
"Shrink all applicable faces by the magnification factor."
(interactive)
(gfs--/magnify-faces (- gfs/magnify-factor)))
(defun gfs/magnify-faces ()
"Magnify all applicable faces by the magnification factor."
(interactive)
(gfs--/magnify-faces gfs/magnify-factor))
This code is assembled together with some boilerplate and private functions to build the final library.