In the previous section we documented how one can override color values
manually (Override colors). Here we use a programmatic approach which
leverages the built-in color-saturate-name
function to adjust the
saturation of all color values used by the active Modus theme. Our goal
is to prepare a counterpart of the active theme’s palette that holds
modified color values, adjusted for a percent change in saturation. A
positive number amplifies the effect, while a negative one will move
towards a grayscale spectrum.
We start with a function that can be either called from Lisp or invoked
interactively. In the former scenario, we pass to it the rate of change
we want. While in the latter, a minibuffer prompt asks for a number to
apply the desired effect. In either case, we intend to assign anew the
value of modus-themes-operandi-color-overrides
(light theme) and the
same for modus-themes-vivendi-color-overrides
(dark theme).
(defun my-modus-themes-saturate (percent) "Saturate current Modus theme palette overrides by PERCENT." (interactive (list (read-number "Saturation by percent: "))) (let* ((theme (modus-themes--current-theme)) (palette (pcase theme ('modus-operandi modus-themes-operandi-colors) ('modus-vivendi modus-themes-vivendi-colors) (_ (error "No Modus theme is active")))) (overrides (pcase theme ('modus-operandi 'modus-themes-operandi-color-overrides) ('modus-vivendi 'modus-themes-vivendi-color-overrides) (_ (error "No Modus theme is active"))))) (let (name cons colors) (dolist (cons palette) (setq name (color-saturate-name (cdr cons) percent)) (setq name (format "%s" name)) (setq cons `(,(car cons) . ,name)) (push cons colors)) (set overrides colors)) (pcase theme ('modus-operandi (modus-themes-load-operandi)) ('modus-vivendi (modus-themes-load-vivendi))))) ;; sample Elisp calls (or call `my-modus-themes-saturate' interactively) (my-modus-themes-saturate 50) (my-modus-themes-saturate -75)
Using the above has an immediate effect, as it reloads the active Modus theme.
The ‘my-modus-themes-saturate’ function stores new color values in the
variables modus-themes-operandi-color-overrides
and
modus-themes-vivendi-color-overrides
, meaning that it undoes changes
implemented by the user on individual colors. To have both automatic
saturation adjustment across the board and retain per-case edits to the
palette, some tweaks to the above function are required. For example:
(defvar my-modus-themes-vivendi-extra-color-overrides '((fg-main . "#ead0c0") (bg-main . "#050515")) "My bespoke colors for `modus-vivendi'.") (defvar my-modus-themes-operandi-extra-color-overrides '((fg-main . "#1a1a1a") (bg-main . "#fefcf4")) "My bespoke colors for `modus-operandi'.") (defun my-modus-themes-saturate (percent) "Saturate current Modus theme palette overrides by PERCENT. Preserve the color values stored in `my-modus-themes-operandi-extra-color-overrides', `my-modus-themes-vivendi-extra-color-overrides'." (interactive (list (read-number "Saturation by percent: "))) (let* ((theme (modus-themes--current-theme)) (palette (pcase theme ('modus-operandi modus-themes-operandi-colors) ('modus-vivendi modus-themes-vivendi-colors) (_ (error "No Modus theme is active")))) (overrides (pcase theme ('modus-operandi 'modus-themes-operandi-color-overrides) ('modus-vivendi 'modus-themes-vivendi-color-overrides) (_ (error "No Modus theme is active")))) (extra-overrides (pcase theme ('modus-operandi my-modus-themes-operandi-extra-color-overrides) ('modus-vivendi my-modus-themes-vivendi-extra-color-overrides) (_ (error "No Modus theme is active"))))) (let (name cons colors) (dolist (cons palette) (setq name (color-saturate-name (cdr cons) percent)) (setq name (format "%s" name)) (setq cons `(,(car cons) . ,name)) (push cons colors)) (set overrides (append extra-overrides colors))) (pcase theme ('modus-operandi (modus-themes-load-operandi)) ('modus-vivendi (modus-themes-load-vivendi)))))
To disable the effect, one must reset the aforementioned variables of
the themes to nil
. Or specify a command for it, such as by taking
inspiration from the modus-themes-toggle
we already provide:
(defun my-modus-themes-revert-overrides () "Reset palette overrides and reload active Modus theme." (interactive) (setq modus-themes-operandi-color-overrides nil modus-themes-vivendi-color-overrides nil) (pcase (modus-themes--current-theme) ('modus-operandi (modus-themes-load-operandi)) ('modus-vivendi (modus-themes-load-vivendi))))