5.5 Case-by-case face specs using the themes’ palette

This section is about tweaking individual faces. If you plan to do things at scale, consult the next section: Set multiple faces.

We already covered in previous sections how to toggle between the themes and how to configure options prior to loading. We also explained that some of the functions made available to users will fire up a hook that can be used to pass tweaks in the post-theme-load phase.

Now assume you wish to change a single face, say, the cursor. And you would like to get the standard “blue” color value of the active Modus theme, whether it is Modus Operandi or Modus Vivendi. To do that, you can use the modus-themes-color function. It accepts a symbol that is associated with a color in modus-themes-operandi-colors and modus-themes-vivendi-colors. Like this:

(modus-themes-color 'blue)

The function always extracts the color value of the active Modus theme.

(progn
  (load-theme 'modus-operandi t)
  (modus-themes-color 'blue))           ; "#0031a9" for `modus-operandi'

(progn
  (load-theme 'modus-vivendi t)
  (modus-themes-color 'blue))           ; "#2fafff" for `modus-vivendi'

Do C-h v on the aforementioned variables to check all the available symbols that can be passed to this function. Or simply invoke the command modus-themes-list-colors to produce a buffer with a preview of each entry in the palette.

Visualize the active Modus theme’s palette.

With that granted, let us expand the example to actually change the cursor face’s background property. We employ the built-in function of set-face-attribute:

(set-face-attribute 'cursor nil :background (modus-themes-color 'blue))

If you evaluate this form, your cursor will become blue. But if you change themes, such as with modus-themes-toggle, your edits will be lost, because the newly loaded theme will override the :background attribute you had assigned to that face.

For such changes to persist, we need to make them after loading the theme. So we rely on modus-themes-after-load-theme-hook, which gets called from modus-themes-load-operandi, modus-themes-load-vivendi, as well as the command modus-themes-toggle. Here is a sample function that tweaks two faces and then gets added to the hook:

(defun my-modus-themes-custom-faces ()
  (set-face-attribute 'cursor nil :background (modus-themes-color 'blue))
  (set-face-attribute 'font-lock-type-face nil :foreground (modus-themes-color 'magenta-alt)))

(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-custom-faces)

A theme-agnostic hook for theme loading.

Using this principle, it is possible to override the styles of faces without having to find color values for each case.

Another application is to control the precise weight for bold constructs. This is particularly useful if your typeface has several variants such as “heavy”, “extrabold”, “semibold”. All you have to do is edit the bold face. For example:

(set-face-attribute 'bold nil :weight 'semibold)

Remember to use the custom function and hook combo we demonstrated above. Because the themes do not hard-wire a specific weight, this simple form is enough to change the weight of all bold constructs throughout the interface.

Finally, there are cases where you want to tweak colors though wish to apply different ones to each theme, say, a blue hue for Modus Operandi and a shade of red for Modus Vivendi. To this end, we provide modus-themes-color-alts as a convenience function to save you from the trouble of writing separate wrappers for each theme. It still returns a single value by querying either of modus-themes-operandi-colors and modus-themes-vivendi-colors, only here you pass the two keys you want, first for modus-operandi then modus-vivendi.

Take the previous example with the cursor face:

;; Blue for `modus-operandi' and red for `modus-vivendi'
(set-face-attribute 'cursor nil :background (modus-themes-color-alts 'blue 'red))