branch: externals/modus-operandi-theme
commit d6586a4f1d07a96cb3195e39f95e36353f220251
Author: Protesilaos Stavrou <i...@protesilaos.com>
Commit: Protesilaos Stavrou <i...@protesilaos.com>

    Refactor mapping of colours to faces. EXPERIMENTAL
    
    The design of the colour palette and of the macro that maps it to faces
    is copied from zenbern-theme.el, commit 7dd7968:
    https://github.com/bbatsov/zenburn-emacs
    
    With these changes it will be possible for users to override a subset of
    the palette (or the entirety of it for that matter).
    
    This change is an initial response to issue 39:
    https://gitlab.com/protesilaos/modus-themes/-/issues/39
---
 modus-operandi-theme.el | 422 +++++++++++++++++++++++++++++-------------------
 modus-vivendi-theme.el  | 422 +++++++++++++++++++++++++++++-------------------
 2 files changed, 510 insertions(+), 334 deletions(-)

diff --git a/modus-operandi-theme.el b/modus-operandi-theme.el
index 2c0a7b4..012aeae 100644
--- a/modus-operandi-theme.el
+++ b/modus-operandi-theme.el
@@ -504,188 +504,271 @@ AMOUNT is a customisation option."
 ;; Define colour palette.  Each colour must have a >= 7:1 contrast
 ;; ratio relative to the foreground/background colour it is rendered
 ;; against.
-(let ((class '((class color) (min-colors 89)))
-      (fg-main "#000000") (bg-main "#ffffff")
-      (fg-alt "#505050") (bg-alt "#f3f1f3")
-      (fg-dim "#282828") (bg-dim "#f8f8f8")
-      ;; specifically for on/off states (e.g. `mode-line')
-      ;;
-      ;; must be combined with themselves
-      (fg-active "#191919") (bg-active "#e0e0e0")
-      (fg-inactive "#424242") (bg-inactive "#efedef")
-      ;; special base values, used only for cases where the above
-      ;; fg-* or bg-* cannot or should not be used (to avoid confusion)
-      ;; must be combined with: {fg,bg}-{main,alt,dim}
-      (fg-special-cold "#093060") (bg-special-cold "#dde3f4")
-      (fg-special-mild "#184034") (bg-special-mild "#c4ede0")
-      (fg-special-warm "#5d3026") (bg-special-warm "#f0e0d4")
-      (fg-special-calm "#61284f") (bg-special-calm "#f8ddea")
-      ;; styles for the main constructs
-      ;;
-      ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
-      (red "#a80000") (green "#005f00")
-      (yellow "#8b3800") (blue "#0030a6")
-      (magenta "#721045") (cyan "#005589")
-      ;; styles for common, but still specialised constructs
-      ;;
-      ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
-      (red-alt "#972500") (green-alt "#305c00")
-      (yellow-alt "#714900") (blue-alt "#223fbf")
-      (magenta-alt "#8f0075") (cyan-alt "#185870")
-      ;; same purpose as above, just slight differences
-      ;;
-      ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
-      (red-alt-other "#a0132f") (green-alt-other "#095f1c")
-      (yellow-alt-other "#804000") (blue-alt-other "#0000bb")
-      (magenta-alt-other "#5317ac") (cyan-alt-other "#005a68")
-      ;; styles for elements that should be very subtle
-      ;;
-      ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
-      (red-nuanced "#4d0006") (green-nuanced "#003000")
-      (yellow-nuanced "#3a2a00") (blue-nuanced "#001170")
-      (magenta-nuanced "#381050") (cyan-nuanced "#003434")
-      ;; styles for slightly accented background
-      ;;
-      ;; must be combined with any of the above foreground values
-      (red-nuanced-bg "#fef2f2") (green-nuanced-bg "#f4faf4")
-      (yellow-nuanced-bg "#fcf6f1") (blue-nuanced-bg "#f4f4ff")
-      (magenta-nuanced-bg "#fff4fc") (cyan-nuanced-bg "#f0f6fa")
-      ;; styles for elements that should draw attention to themselves
-      ;;
-      ;; must be combined with: `bg-main'
-      (red-intense "#b60000") (green-intense "#006800")
-      (yellow-intense "#904200") (blue-intense "#1111ee")
-      (magenta-intense "#7000e0") (cyan-intense "#205b93")
-      ;; styles for background elements that should be visible yet
-      ;; subtle
-      ;;
-      ;; must be combined with: `fg-dim'
-      (red-subtle-bg "#f2b0a2") (green-subtle-bg "#aecf90")
-      (yellow-subtle-bg "#e4c340") (blue-subtle-bg "#b5d0ff")
-      (magenta-subtle-bg "#f0d3ff") (cyan-subtle-bg "#c0efff")
-      ;; styles for background elements that should be visible and
-      ;; distinguishable
-      ;;
-      ;; must be combined with: `fg-main'
-      (red-intense-bg "#ff8892") (green-intense-bg "#5ada88")
-      (yellow-intense-bg "#f5df23") (blue-intense-bg "#6aaeff")
-      (magenta-intense-bg "#d5baff") (cyan-intense-bg "#42cbd4")
-      ;; styles for refined git diffs and other contexts where both the
-      ;; foreground and the background need to have the same/similar hue
-      ;;
-      ;; must be combined with themselves OR the foregrounds can be
-      ;; combined with any of the base backgrounds
-      (red-refine-bg "#ffcccc") (green-refine-bg "#aceaac")
-      (yellow-refine-bg "#fff29a") (blue-refine-bg "#8ac7ff")
-      (magenta-refine-bg "#ffccff") (cyan-refine-bg "#8eecf4")
-      (red-refine-fg "#780000") (green-refine-fg "#004c00")
-      (yellow-refine-fg "#604000") (blue-refine-fg "#002288")
-      (magenta-refine-fg "#770077") (cyan-refine-fg "#004850")
-      ;; styles that are meant exclusively for the mode line
-      ;;
-      ;; must be combined with: `bg-active', `bg-inactive'
-      (red-active "#930000") (green-active "#005300")
-      (yellow-active "#703700") (blue-active "#0033c0")
-      (magenta-active "#6320a0") (cyan-active "#004882")
-      ;; styles that are meant exclusively for the fringes
-      ;;
-      ;; must have a minimum contrast ratio of 1.5:1 with `bg-inactive'
-      ;; and be combined with `fg-main' or `fg-dim'
-      (red-fringe-bg "#ff9a9a") (green-fringe-bg "#86cf86")
-      (yellow-fringe-bg "#e0c050") (blue-fringe-bg "#82afff")
-      (magenta-fringe-bg "#f0a3ff") (cyan-fringe-bg "#00d6e0")
+;;
+;; The design of the colour palette and of the macro that maps it to
+;; faces is copied from zenbern-theme.el from commit 7dd7968:
+;; https://github.com/bbatsov/zenburn-emacs
+(defvar modus-operandi-theme-default-colors-alist
+  '(;; base values
+    ("fg-main" . "#000000")
+    ("bg-main" . "#ffffff")
+    ("fg-alt" . "#505050")
+    ("bg-alt" . "#f3f1f3")
+    ("fg-dim" . "#282828")
+    ("bg-dim" . "#f8f8f8")
+    ;; specifically for on/off states (e.g. `mode-line')
+    ;;
+    ;; must be combined with themselves
+    ("fg-active" . "#191919")
+    ("bg-active" . "#e0e0e0")
+    ("fg-inactive" . "#424242")
+    ("bg-inactive" . "#efedef")
+    ;; special base values, used only for cases where the above
+    ;; fg-* or bg-* cannot or should not be used (to avoid confusion)
+    ;; must be combined with: {fg,bg}-{main,alt,dim}
+    ("fg-special-cold" . "#093060")
+    ("bg-special-cold" . "#dde3f4")
+    ("fg-special-mild" . "#184034")
+    ("bg-special-mild" . "#c4ede0")
+    ("fg-special-warm" . "#5d3026")
+    ("bg-special-warm" . "#f0e0d4")
+    ("fg-special-calm" . "#61284f")
+    ("bg-special-calm" . "#f8ddea")
+    ;; styles for the main constructs
+    ;;
+    ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
+    ("red" . "#a80000")
+    ("green" . "#005f00")
+    ("yellow" . "#8b3800")
+    ("blue" . "#0030a6")
+    ("magenta" . "#721045")
+    ("cyan" . "#005589")
+    ;; styles for common, but still specialised constructs
+    ;;
+    ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
+    ("red-alt" . "#972500")
+    ("green-alt" . "#305c00")
+    ("yellow-alt" . "#714900")
+    ("blue-alt" . "#223fbf")
+    ("magenta-alt" . "#8f0075")
+    ("cyan-alt" . "#185870")
+    ;; same purpose as above, just slight differences
+    ;;
+    ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
+    ("red-alt-other" . "#a0132f")
+    ("green-alt-other" . "#095f1c")
+    ("yellow-alt-other" . "#804000")
+    ("blue-alt-other" . "#0000bb")
+    ("magenta-alt-other" . "#5317ac")
+    ("cyan-alt-other" . "#005a68")
+    ;; styles for elements that should be very subtle
+    ;;
+    ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
+    ("red-nuanced" . "#4d0006")
+    ("green-nuanced" . "#003000")
+    ("yellow-nuanced" . "#3a2a00")
+    ("blue-nuanced" . "#001170")
+    ("magenta-nuanced" . "#381050")
+    ("cyan-nuanced" . "#003434")
+    ;; styles for slightly accented background
+    ;;
+    ;; must be combined with any of the above foreground values
+    ("red-nuanced-bg" . "#fef2f2")
+    ("green-nuanced-bg" . "#f4faf4")
+    ("yellow-nuanced-bg" . "#fcf6f1")
+    ("blue-nuanced-bg" . "#f4f4ff")
+    ("magenta-nuanced-bg" . "#fff4fc")
+    ("cyan-nuanced-bg" . "#f0f6fa")
+    ;; styles for elements that should draw attention to themselves
+    ;;
+    ;; must be combined with: `bg-main'
+    ("red-intense" . "#b60000")
+    ("green-intense" . "#006800")
+    ("yellow-intense" . "#904200")
+    ("blue-intense" . "#1111ee")
+    ("magenta-intense" . "#7000e0")
+    ("cyan-intense" . "#205b93")
+    ;; styles for background elements that should be visible yet
+    ;; subtle
+    ;;
+    ;; must be combined with: `fg-dim'
+    ("red-subtle-bg" . "#f2b0a2")
+    ("green-subtle-bg" . "#aecf90")
+    ("yellow-subtle-bg" . "#e4c340")
+    ("blue-subtle-bg" . "#b5d0ff")
+    ("magenta-subtle-bg" . "#f0d3ff")
+    ("cyan-subtle-bg" . "#c0efff")
+    ;; styles for background elements that should be visible and
+    ;; distinguishable
+    ;;
+    ;; must be combined with: `fg-main'
+    ("red-intense-bg" . "#ff8892")
+    ("green-intense-bg" . "#5ada88")
+    ("yellow-intense-bg" . "#f5df23")
+    ("blue-intense-bg" . "#6aaeff")
+    ("magenta-intense-bg" . "#d5baff")
+    ("cyan-intense-bg" . "#42cbd4")
+    ;; styles for refined git diffs and other contexts where both the
+    ;; foreground and the background need to have the same/similar hue
+    ;;
+    ;; must be combined with themselves OR the foregrounds can be
+    ;; combined with any of the base backgrounds
+    ("red-refine-bg" . "#ffcccc")
+    ("green-refine-bg" . "#aceaac")
+    ("yellow-refine-bg" . "#fff29a")
+    ("blue-refine-bg" . "#8ac7ff")
+    ("magenta-refine-bg" . "#ffccff")
+    ("cyan-refine-bg" . "#8eecf4")
+    ("red-refine-fg" . "#780000")
+    ("green-refine-fg" . "#004c00")
+    ("yellow-refine-fg" . "#604000")
+    ("blue-refine-fg" . "#002288")
+    ("magenta-refine-fg" . "#770077")
+    ("cyan-refine-fg" . "#004850")
+    ;; styles that are meant exclusively for the mode line
+    ;;
+    ;; must be combined with: `bg-active', `bg-inactive'
+    ("red-active" . "#930000")
+    ("green-active" . "#005300")
+    ("yellow-active" . "#703700")
+    ("blue-active" . "#0033c0")
+    ("magenta-active" . "#6320a0")
+    ("cyan-active" . "#004882")
+    ;; styles that are meant exclusively for the fringes
+    ;;
+    ;; must have a minimum contrast ratio of 1.5:1 with `bg-inactive'
+    ;; and be combined with `fg-main' or `fg-dim'
+    ("red-fringe-bg" . "#ff9a9a")
+    ("green-fringe-bg" . "#86cf86")
+    ("yellow-fringe-bg" . "#e0c050")
+    ("blue-fringe-bg" . "#82afff")
+    ("magenta-fringe-bg" . "#f0a3ff")
+    ("cyan-fringe-bg" . "#00d6e0")
+    ;; styles reserved for specific faces
+    ;;
+    ;; `bg-hl-line' is between `bg-dim' and `bg-alt', so it should
+    ;; work with all accents that cover those two, plus `bg-main'
+    ;;
+    ;; `bg-header' is between `bg-active' and `bg-inactive', so it
+    ;; can be combined with any of the "active" values, plus the
+    ;; "special" and base foreground colours
+    ;;
+    ;; `bg-paren-match', `bg-region' and `bg-tab-active' must be
+    ;; combined with `fg-main', while `bg-tab-inactive' should be
+    ;; combined with `fg-dim'
+    ;;
+    ;; `fg-tab-active' is meant to be combined with `bg-tab-active',
+    ;; though only for styling special elements, such as underlining
+    ;; the current tab
+    ;;
+    ;; `fg-escape-char-construct' and `fg-escape-char-backslash' can
+    ;; be combined `bg-main', `bg-dim', `bg-alt'
+    ;;
+    ;; `fg-lang-error', `fg-lang-warning', `fg-lang-note' can be
+    ;; combined with `bg-main', `bg-dim', `bg-alt'
+    ;;
+    ;; `fg-mark', `fg-mark-del', `fg-mark-other' can be combined with
+    ;; `bg-main', `bg-dim', `bg-alt', `bg-hl-line'
+    ;;
+    ;; `fg-unfocused' must be combined with `fg-main'
+    ;;
+    ;; the window divider colours apply to faces with just an fg value
+    ;;
+    ;; all pairs are combinable with themselves
+    ("bg-hl-line" . "#f1f2f6")
+    ("bg-paren-match" . "#efcabf")
+    ("bg-region" . "#bcbcbc")
 
-      ;; styles reserved for specific faces
-      ;;
-      ;; `bg-hl-line' is between `bg-dim' and `bg-alt', so it should
-      ;; work with all accents that cover those two, plus `bg-main'
-      ;;
-      ;; `bg-header' is between `bg-active' and `bg-inactive', so it
-      ;; can be combined with any of the "active" values, plus the
-      ;; "special" and base foreground colours
-      ;;
-      ;; `bg-paren-match', `bg-region' and `bg-tab-active' must be
-      ;; combined with `fg-main', while `bg-tab-inactive' should be
-      ;; combined with `fg-dim'
-      ;;
-      ;; `fg-tab-active' is meant to be combined with `bg-tab-active',
-      ;; though only for styling special elements, such as underlining
-      ;; the current tab
-      ;;
-      ;; `fg-escape-char-construct' and `fg-escape-char-backslash' can
-      ;; be combined `bg-main', `bg-dim', `bg-alt'
-      ;;
-      ;; `fg-lang-error', `fg-lang-warning', `fg-lang-note' can be
-      ;; combined with `bg-main', `bg-dim', `bg-alt'
-      ;;
-      ;; `fg-mark', `fg-mark-del', `fg-mark-other' can be combined with
-      ;; `bg-main', `bg-dim', `bg-alt', `bg-hl-line'
-      ;;
-      ;; `fg-unfocused' must be combined with `fg-main'
-      ;;
-      ;; the window divider colours apply to faces with just an fg value
-      ;;
-      ;; all pairs are combinable with themselves
-      (bg-hl-line "#f1f2f6")
-      (bg-paren-match "#efcabf")
-      (bg-region "#bcbcbc")
+    ("bg-tab-active" . "#ababab")
+    ("bg-tab-inactive" . "#dadada")
+    ("fg-tab-active" . "#000077")
 
-      (bg-tab-active "#ababab")
-      (bg-tab-inactive "#dadada")
-      (fg-tab-active "#000077")
+    ("fg-escape-char-construct" . "#8b1030")
+    ("fg-escape-char-backslash" . "#644f00")
 
-      (fg-escape-char-construct "#8b1030")
-      (fg-escape-char-backslash "#644f00")
+    ("fg-lang-error" . "#9f004f")
+    ("fg-lang-warning" . "#605000")
+    ("fg-lang-note" . "#4040ae")
 
-      (fg-lang-error "#9f004f")
-      (fg-lang-warning "#605000")
-      (fg-lang-note "#4040ae")
+    ("fg-window-divider-inner" . "#888888")
+    ("fg-window-divider-outer" . "#585858")
 
-      (fg-window-divider-inner "#888888")
-      (fg-window-divider-outer "#585858")
+    ("fg-unfocused" . "#56576d")
 
-      (fg-unfocused "#56576d")
+    ("fg-header" . "#2a2a2a")
+    ("bg-header" . "#e5e5e5")
 
-      (fg-header "#2a2a2a") (bg-header "#e5e5e5")
-      (fg-whitespace "#645060") (bg-whitespace "#fff8fc")
+    ("fg-whitespace" . "#645060")
+    ("bg-whitespace" . "#fff8fc")
 
-      (fg-diff-heading "#043355") (bg-diff-heading "#b7c2dd")
-      (fg-diff-added "#004500") (bg-diff-added "#d4fad4")
-      (fg-diff-changed "#524200") (bg-diff-changed "#fcefcf")
-      (fg-diff-removed "#691616") (bg-diff-removed "#ffe8ef")
+    ("fg-diff-heading" . "#043355")
+    ("bg-diff-heading" . "#b7c2dd")
+    ("fg-diff-added" . "#004500")
+    ("bg-diff-added" . "#d4fad4")
+    ("fg-diff-changed" . "#524200")
+    ("bg-diff-changed" . "#fcefcf")
+    ("fg-diff-removed" . "#691616")
+    ("bg-diff-removed" . "#ffe8ef")
 
-      (fg-diff-refine-added "#002a00") (bg-diff-refine-added "#94cf94")
-      (fg-diff-refine-changed "#302010") (bg-diff-refine-changed "#cccf8f")
-      (fg-diff-refine-removed "#400000") (bg-diff-refine-removed "#daa2b0")
+    ("fg-diff-refine-added" . "#002a00")
+    ("bg-diff-refine-added" . "#94cf94")
+    ("fg-diff-refine-changed" . "#302010")
+    ("bg-diff-refine-changed" . "#cccf8f")
+    ("fg-diff-refine-removed" . "#400000")
+    ("bg-diff-refine-removed" . "#daa2b0")
 
-      (fg-diff-focus-added "#002c00") (bg-diff-focus-added "#bbeabb")
-      (fg-diff-focus-changed "#392900") (bg-diff-focus-changed "#ecdfbf")
-      (fg-diff-focus-removed "#4a0000") (bg-diff-focus-removed "#efcbcf")
+    ("fg-diff-focus-added" . "#002c00")
+    ("bg-diff-focus-added" . "#bbeabb")
+    ("fg-diff-focus-changed" . "#392900")
+    ("bg-diff-focus-changed" . "#ecdfbf")
+    ("fg-diff-focus-removed" . "#4a0000")
+    ("bg-diff-focus-removed" . "#efcbcf")
 
-      (fg-diff-neutral-0 "#040404") (bg-diff-neutral-0 "#979797")
-      (fg-diff-neutral-1 "#252525") (bg-diff-neutral-1 "#b0b0b0")
-      (fg-diff-neutral-2 "#3a3a3a") (bg-diff-neutral-2 "#cccccc")
+    ("fg-diff-neutral-0" . "#040404")
+    ("bg-diff-neutral-0" . "#979797")
+    ("fg-diff-neutral-1" . "#252525")
+    ("bg-diff-neutral-1" . "#b0b0b0")
+    ("fg-diff-neutral-2" . "#3a3a3a")
+    ("bg-diff-neutral-2" . "#cccccc")
 
-      (fg-mark "#005040") (bg-mark "#a0f0cf")
-      (fg-mark-del "#840040") (bg-mark-del "#ffccbb")
-      (fg-mark-other "#782900") (bg-mark-other "#f5d88f")
+    ("fg-mark" . "#005040")
+    ("bg-mark" . "#a0f0cf")
+    ("fg-mark-del" . "#840040")
+    ("bg-mark-del" . "#ffccbb")
+    ("fg-mark-other" . "#782900")
+    ("bg-mark-other" . "#f5d88f"))
+  "The entire palette of `modus-operandi-theme'.
+Each element has the form (NAME . HEX).")
 
-      ;; conditional styles that evaluate user-facing customisation
-      ;; options
-      (modus-theme-slant
-       (if modus-operandi-theme-slanted-constructs
-           'italic
-         'normal))
+;;;###autoload
+(defcustom modus-operandi-theme-override-colors-alist '()
+  "Place to override default theme colors.
+You can override a subset of the theme's default colors by
+defining them in this alist."
+  :type '(alist
+          :key-type (string :tag "Name")
+          :value-type (string :tag " Hex")))
 
-      (modus-theme-bold
-       (if modus-operandi-theme-bold-constructs
-           'bold
-         'normal))
+(defmacro modus-operandi-theme-with-color-variables (&rest body)
+  "`let' bind all colours around BODY.
+Also bind `class' to ((class color) (min-colors 89))."
+  (declare (indent 0))
+  `(let ((class '((class color) (min-colors 89)))
+         ,@(mapcar (lambda (cons)
+                     (list (intern (car cons)) (cdr cons)))
+                   (append modus-operandi-theme-default-colors-alist
+                           modus-operandi-theme-override-colors-alist))
+         ;; conditional styles that evaluate user-facing customisation
+         ;; options
+         (modus-theme-slant
+          (if modus-operandi-theme-slanted-constructs 'italic 'normal))
+         (modus-theme-bold
+          (if modus-operandi-theme-bold-constructs 'bold 'normal))
+         (modus-theme-variable-pitch
+          (if modus-operandi-theme-proportional-fonts 'variable-pitch 
'default)))
+     ,@body))
 
-      (modus-theme-variable-pitch
-       (if modus-operandi-theme-proportional-fonts
-           'variable-pitch
-         'default)))
+(modus-operandi-theme-with-color-variables
   (custom-theme-set-faces
    'modus-operandi
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -3311,4 +3394,9 @@ AMOUNT is a customisation option."
 (provide-theme 'modus-operandi)
 
 (provide 'modus-operandi-theme)
+
+;; Local Variables:
+;; no-byte-compile: t
+;; indent-tabs-mode: nil
+;; End:
 ;;; modus-operandi-theme.el ends here
diff --git a/modus-vivendi-theme.el b/modus-vivendi-theme.el
index ccc49a8..836cb40 100644
--- a/modus-vivendi-theme.el
+++ b/modus-vivendi-theme.el
@@ -504,188 +504,271 @@ AMOUNT is a customisation option."
 ;; Define colour palette.  Each colour must have a >= 7:1 contrast
 ;; ratio relative to the foreground/background colour it is rendered
 ;; against.
-(let ((class '((class color) (min-colors 89)))
-      (fg-main "#ffffff") (bg-main "#000000")
-      (fg-alt "#a8a8a8") (bg-alt "#181a20")
-      (fg-dim "#e0e6f0") (bg-dim "#110b11")
-      ;; specifically for on/off states (e.g. `mode-line')
-      ;;
-      ;; must be combined with themselves
-      (fg-active "#f5f5f5") (bg-active "#2f2f2f")
-      (fg-inactive "#bebebe") (bg-inactive "#202020")
-      ;; special base values, used only for cases where the above
-      ;; fg-* or bg-* cannot or should not be used (to avoid confusion)
-      ;; must be combined with: {fg,bg}-{main,alt,dim}
-      (fg-special-cold "#c6eaff") (bg-special-cold "#203448")
-      (fg-special-mild "#bfebe0") (bg-special-mild "#00322e")
-      (fg-special-warm "#f8dec0") (bg-special-warm "#382f27")
-      (fg-special-calm "#fbd6f4") (bg-special-calm "#392a48")
-      ;; styles for the main constructs
-      ;;
-      ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
-      (red "#ff8059") (green "#44bc44")
-      (yellow "#eecc00") (blue "#33beff")
-      (magenta "#feacd0") (cyan "#00d3d0")
-      ;; styles for common, but still specialised constructs
-      ;;
-      ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
-      (red-alt "#f4923b") (green-alt "#58dd13")
-      (yellow-alt "#e5f040") (blue-alt "#72a4ff")
-      (magenta-alt "#f78fe7") (cyan-alt "#4ae8fc")
-      ;; same purpose as above, just slight differences
-      ;;
-      ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
-      (red-alt-other "#ff9977") (green-alt-other "#90d800")
-      (yellow-alt-other "#f0ce43") (blue-alt-other "#00baf4")
-      (magenta-alt-other "#b6a0ff") (cyan-alt-other "#6ae4b9")
-      ;; styles for elements that should be very subtle
-      ;;
-      ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
-      (red-nuanced "#ffcccc") (green-nuanced "#b0f0b0")
-      (yellow-nuanced "#e0e0bb") (blue-nuanced "#ccccff")
-      (magenta-nuanced "#eeccee") (cyan-nuanced "#aaeeee")
-      ;; styles for slightly accented background
-      ;;
-      ;; must be combined with any of the above foreground values
-      (red-nuanced-bg "#180505") (green-nuanced-bg "#061206")
-      (yellow-nuanced-bg "#18140a") (blue-nuanced-bg "#070722")
-      (magenta-nuanced-bg "#160616") (cyan-nuanced-bg "#091620")
-      ;; styles for elements that should draw attention to themselves
-      ;;
-      ;; must be combined with: `bg-main'
-      (red-intense "#fb6859") (green-intense "#00fc50")
-      (yellow-intense "#ffdd00") (blue-intense "#00a2ff")
-      (magenta-intense "#ff8bd4") (cyan-intense "#30ffc0")
-      ;; styles for background elements that should be visible yet
-      ;; subtle
-      ;;
-      ;; must be combined with: `fg-dim'
-      (red-subtle-bg "#762422") (green-subtle-bg "#2f4a00")
-      (yellow-subtle-bg "#604200") (blue-subtle-bg "#10387c")
-      (magenta-subtle-bg "#49366e") (cyan-subtle-bg "#00415e")
-      ;; styles for background elements that should be visible and
-      ;; distinguishable
-      ;;
-      ;; must be combined with: `fg-main'
-      (red-intense-bg "#a4202a") (green-intense-bg "#006800")
-      (yellow-intense-bg "#874900") (blue-intense-bg "#2a40b8")
-      (magenta-intense-bg "#7042a2") (cyan-intense-bg "#005f88")
-      ;; styles for refined git diffs and other contexts where both the
-      ;; foreground and the background need to have the same/similar hue
-      ;;
-      ;; must be combined with themselves OR the foregrounds can be
-      ;; combined with any of the base backgrounds
-      (red-refine-bg "#77002a") (green-refine-bg "#00422a")
-      (yellow-refine-bg "#705000") (blue-refine-bg "#242679")
-      (magenta-refine-bg "#71206a") (cyan-refine-bg "#004065")
-      (red-refine-fg "#ffb9ab") (green-refine-fg "#9ff0cf")
-      (yellow-refine-fg "#ffffac") (blue-refine-fg "#8ec6ff")
-      (magenta-refine-fg "#ffcaf0") (cyan-refine-fg "#8ae4f2")
-      ;; styles that are meant exclusively for the mode line
-      ;;
-      ;; must be combined with: `bg-active', `bg-inactive'
-      (red-active "#ffa49e") (green-active "#70e030")
-      (yellow-active "#efdf00") (blue-active "#00ccff")
-      (magenta-active "#d0acff") (cyan-active "#00ddc0")
-      ;; styles that are meant exclusively for the fringes
-      ;;
-      ;; must have a minimum contrast ratio of 1.5:1 with `bg-inactive'
-      ;; and be combined with `fg-main' or `fg-dim'
-      (red-fringe-bg "#8f0040") (green-fringe-bg "#006000")
-      (yellow-fringe-bg "#6f4a00") (blue-fringe-bg "#3a30ab")
-      (magenta-fringe-bg "#692089") (cyan-fringe-bg "#0068a0")
+;;
+;; The design of the colour palette and of the macro that maps it to
+;; faces is copied from zenbern-theme.el from commit 7dd7968:
+;; https://github.com/bbatsov/zenburn-emacs
+(defvar modus-vivendi-theme-default-colors-alist
+  '(;; base values
+    ("fg-main" . "#ffffff")
+    ("bg-main" . "#000000")
+    ("fg-alt" . "#a8a8a8")
+    ("bg-alt" . "#181a20")
+    ("fg-dim" . "#e0e6f0")
+    ("bg-dim" . "#110b11")
+    ;; specifically for on/off states (e.g. `mode-line')
+    ;;
+    ;; must be combined with themselves
+    ("fg-active" . "#f5f5f5")
+    ("bg-active" . "#2f2f2f")
+    ("fg-inactive" . "#bebebe")
+    ("bg-inactive" . "#202020")
+    ;; special base values, used only for cases where the above
+    ;; fg-* or bg-* cannot or should not be used (to avoid confusion)
+    ;; must be combined with: {fg,bg}-{main,alt,dim}
+    ("fg-special-cold" . "#c6eaff")
+    ("bg-special-cold" . "#203448")
+    ("fg-special-mild" . "#bfebe0")
+    ("bg-special-mild" . "#00322e")
+    ("fg-special-warm" . "#f8dec0")
+    ("bg-special-warm" . "#382f27")
+    ("fg-special-calm" . "#fbd6f4")
+    ("bg-special-calm" . "#392a48")
+    ;; styles for the main constructs
+    ;;
+    ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
+    ("red" . "#ff8059")
+    ("green" . "#44bc44")
+    ("yellow" . "#eecc00")
+    ("blue" . "#33beff")
+    ("magenta" . "#feacd0")
+    ("cyan" . "#00d3d0")
+    ;; styles for common, but still specialised constructs
+    ;;
+    ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
+    ("red-alt" . "#f4923b")
+    ("green-alt" . "#58dd13")
+    ("yellow-alt" . "#e5f040")
+    ("blue-alt" . "#72a4ff")
+    ("magenta-alt" . "#f78fe7")
+    ("cyan-alt" . "#4ae8fc")
+    ;; same purpose as above, just slight differences
+    ;;
+    ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
+    ("red-alt-other" . "#ff9977")
+    ("green-alt-other" . "#90d800")
+    ("yellow-alt-other" . "#f0ce43")
+    ("blue-alt-other" . "#00baf4")
+    ("magenta-alt-other" . "#b6a0ff")
+    ("cyan-alt-other" . "#6ae4b9")
+    ;; styles for elements that should be very subtle
+    ;;
+    ;; must be combined with: `bg-main', `bg-alt', `bg-dim'
+    ("red-nuanced" . "#ffcccc")
+    ("green-nuanced" . "#b0f0b0")
+    ("yellow-nuanced" . "#e0e0bb")
+    ("blue-nuanced" . "#ccccff")
+    ("magenta-nuanced" . "#eeccee")
+    ("cyan-nuanced" . "#aaeeee")
+    ;; styles for slightly accented background
+    ;;
+    ;; must be combined with any of the above foreground values
+    ("red-nuanced-bg" . "#180505")
+    ("green-nuanced-bg" . "#061206")
+    ("yellow-nuanced-bg" . "#18140a")
+    ("blue-nuanced-bg" . "#070722")
+    ("magenta-nuanced-bg" . "#160616")
+    ("cyan-nuanced-bg" . "#091620")
+    ;; styles for elements that should draw attention to themselves
+    ;;
+    ;; must be combined with: `bg-main'
+    ("red-intense" . "#fb6859")
+    ("green-intense" . "#00fc50")
+    ("yellow-intense" . "#ffdd00")
+    ("blue-intense" . "#00a2ff")
+    ("magenta-intense" . "#ff8bd4")
+    ("cyan-intense" . "#30ffc0")
+    ;; styles for background elements that should be visible yet
+    ;; subtle
+    ;;
+    ;; must be combined with: `fg-dim'
+    ("red-subtle-bg" . "#762422")
+    ("green-subtle-bg" . "#2f4a00")
+    ("yellow-subtle-bg" . "#604200")
+    ("blue-subtle-bg" . "#10387c")
+    ("magenta-subtle-bg" . "#49366e")
+    ("cyan-subtle-bg" . "#00415e")
+    ;; styles for background elements that should be visible and
+    ;; distinguishable
+    ;;
+    ;; must be combined with: `fg-main'
+    ("red-intense-bg" . "#a4202a")
+    ("green-intense-bg" . "#006800")
+    ("yellow-intense-bg" . "#874900")
+    ("blue-intense-bg" . "#2a40b8")
+    ("magenta-intense-bg" . "#7042a2")
+    ("cyan-intense-bg" . "#005f88")
+    ;; styles for refined git diffs and other contexts where both the
+    ;; foreground and the background need to have the same/similar hue
+    ;;
+    ;; must be combined with themselves OR the foregrounds can be
+    ;; combined with any of the base backgrounds
+    ("red-refine-bg" . "#77002a")
+    ("green-refine-bg" . "#00422a")
+    ("yellow-refine-bg" . "#705000")
+    ("blue-refine-bg" . "#242679")
+    ("magenta-refine-bg" . "#71206a")
+    ("cyan-refine-bg" . "#004065")
+    ("red-refine-fg" . "#ffb9ab")
+    ("green-refine-fg" . "#9ff0cf")
+    ("yellow-refine-fg" . "#ffffac")
+    ("blue-refine-fg" . "#8ec6ff")
+    ("magenta-refine-fg" . "#ffcaf0")
+    ("cyan-refine-fg" . "#8ae4f2")
+    ;; styles that are meant exclusively for the mode line
+    ;;
+    ;; must be combined with: `bg-active', `bg-inactive'
+    ("red-active" . "#ffa49e")
+    ("green-active" . "#70e030")
+    ("yellow-active" . "#efdf00")
+    ("blue-active" . "#00ccff")
+    ("magenta-active" . "#d0acff")
+    ("cyan-active" . "#00ddc0")
+    ;; styles that are meant exclusively for the fringes
+    ;;
+    ;; must have a minimum contrast ratio of 1.5:1 with `bg-inactive'
+    ;; and be combined with `fg-main' or `fg-dim'
+    ("red-fringe-bg" . "#8f0040")
+    ("green-fringe-bg" . "#006000")
+    ("yellow-fringe-bg" . "#6f4a00")
+    ("blue-fringe-bg" . "#3a30ab")
+    ("magenta-fringe-bg" . "#692089")
+    ("cyan-fringe-bg" . "#0068a0")
+    ;; styles reserved for specific faces
+    ;;
+    ;; `bg-hl-line' is between `bg-dim' and `bg-alt', so it should
+    ;; work with all accents that cover those two, plus `bg-main'
+    ;;
+    ;; `bg-header' is between `bg-active' and `bg-inactive', so it
+    ;; can be combined with any of the "active" values, plus the
+    ;; "special" and base foreground colours
+    ;;
+    ;; `bg-paren-match', `bg-region' and `bg-tab-active' must be
+    ;; combined with `fg-main', while `bg-tab-inactive' should be
+    ;; combined with `fg-dim'
+    ;;
+    ;; `fg-tab-active' is meant to be combined with `bg-tab-active',
+    ;; though only for styling special elements, such as underlining
+    ;; the current tab
+    ;;
+    ;; `fg-escape-char-construct' and `fg-escape-char-backslash' can
+    ;; be combined `bg-main', `bg-dim', `bg-alt'
+    ;;
+    ;; `fg-lang-error', `fg-lang-warning', `fg-lang-note' can be
+    ;; combined with `bg-main', `bg-dim', `bg-alt'
+    ;;
+    ;; `fg-mark', `fg-mark-del', `fg-mark-other' can be combined with
+    ;; `bg-main', `bg-dim', `bg-alt', `bg-hl-line'
+    ;;
+    ;; `fg-unfocused' must be combined with `fg-main'
+    ;;
+    ;; the window divider colours apply to faces with just an fg value
+    ;;
+    ;; all pairs are combinable with themselves
+    ("bg-hl-line" . "#151823")
+    ("bg-paren-match" . "#6e3a50")
+    ("bg-region" . "#3c3c3c")
 
-      ;; styles reserved for specific faces
-      ;;
-      ;; `bg-hl-line' is between `bg-dim' and `bg-alt', so it should
-      ;; work with all accents that cover those two, plus `bg-main'
-      ;;
-      ;; `bg-header' is between `bg-active' and `bg-inactive', so it
-      ;; can be combined with any of the "active" values, plus the
-      ;; "special" and base foreground colours
-      ;;
-      ;; `bg-paren-match', `bg-region' and `bg-tab-active' must be
-      ;; combined with `fg-main', while `bg-tab-inactive' should be
-      ;; combined with `fg-dim'
-      ;;
-      ;; `fg-tab-active' is meant to be combined with `bg-tab-active',
-      ;; though only for styling special elements, such as underlining
-      ;; the current tab
-      ;;
-      ;; `fg-escape-char-construct' and `fg-escape-char-backslash' can
-      ;; be combined `bg-main', `bg-dim', `bg-alt'
-      ;;
-      ;; `fg-lang-error', `fg-lang-warning', `fg-lang-note' can be
-      ;; combined with `bg-main', `bg-dim', `bg-alt'
-      ;;
-      ;; `fg-mark', `fg-mark-del', `fg-mark-other' can be combined with
-      ;; `bg-main', `bg-dim', `bg-alt', `bg-hl-line'
-      ;;
-      ;; `fg-unfocused' must be combined with `fg-main'
-      ;;
-      ;; the window divider colours apply to faces with just an fg value
-      ;;
-      ;; all pairs are combinable with themselves
-      (bg-hl-line "#151823")
-      (bg-paren-match "#6e3a50")
-      (bg-region "#3c3c3c")
+    ("bg-tab-active" . "#484848")
+    ("bg-tab-inactive" . "#2f2f2f")
+    ("fg-tab-active" . "#99efff")
 
-      (bg-tab-active "#484848")
-      (bg-tab-inactive "#2f2f2f")
-      (fg-tab-active "#99efff")
+    ("fg-escape-char-construct" . "#e7a59a")
+    ("fg-escape-char-backslash" . "#abab00")
 
-      (fg-escape-char-construct "#e7a59a")
-      (fg-escape-char-backslash "#abab00")
+    ("fg-lang-error" . "#ef8690")
+    ("fg-lang-warning" . "#b0aa00")
+    ("fg-lang-note" . "#9d9def")
 
-      (fg-lang-error "#ef8690")
-      (fg-lang-warning "#b0aa00")
-      (fg-lang-note "#9d9def")
+    ("fg-window-divider-inner" . "#646464")
+    ("fg-window-divider-outer" . "#969696")
 
-      (fg-window-divider-inner "#646464")
-      (fg-window-divider-outer "#969696")
+    ("fg-unfocused" . "#93959b")
 
-      (fg-unfocused "#93959b")
+    ("fg-header" . "#dddddd")
+    ("bg-header" . "#2a2a2a")
 
-      (fg-header "#dddddd") (bg-header "#2a2a2a")
-      (fg-whitespace "#a4959f") (bg-whitespace "#170016")
+    ("fg-whitespace" . "#a4959f")
+    ("bg-whitespace" . "#170016")
 
-      (fg-diff-heading "#dadffe") (bg-diff-heading "#304466")
-      (fg-diff-added "#94ba94") (bg-diff-added "#0a280a")
-      (fg-diff-changed "#b0ba9f") (bg-diff-changed "#2a2000")
-      (fg-diff-removed "#c6adaa") (bg-diff-removed "#40160f")
+    ("fg-diff-heading" . "#dadffe")
+    ("bg-diff-heading" . "#304466")
+    ("fg-diff-added" . "#94ba94")
+    ("bg-diff-added" . "#0a280a")
+    ("fg-diff-changed" . "#b0ba9f")
+    ("bg-diff-changed" . "#2a2000")
+    ("fg-diff-removed" . "#c6adaa")
+    ("bg-diff-removed" . "#40160f")
 
-      (fg-diff-refine-added "#e0f6e0") (bg-diff-refine-added "#005a36")
-      (fg-diff-refine-changed "#ffffcc") (bg-diff-refine-changed "#585800")
-      (fg-diff-refine-removed "#ffd9eb") (bg-diff-refine-removed "#852828")
+    ("fg-diff-refine-added" . "#e0f6e0")
+    ("bg-diff-refine-added" . "#005a36")
+    ("fg-diff-refine-changed" . "#ffffcc")
+    ("bg-diff-refine-changed" . "#585800")
+    ("fg-diff-refine-removed" . "#ffd9eb")
+    ("bg-diff-refine-removed" . "#852828")
 
-      (fg-diff-focus-added "#b4ddb4") (bg-diff-focus-added "#203d20")
-      (fg-diff-focus-changed "#d0daaf") (bg-diff-focus-changed "#4a3a10")
-      (fg-diff-focus-removed "#eebdba") (bg-diff-focus-removed "#5e2526")
+    ("fg-diff-focus-added" . "#b4ddb4")
+    ("bg-diff-focus-added" . "#203d20")
+    ("fg-diff-focus-changed" . "#d0daaf")
+    ("bg-diff-focus-changed" . "#4a3a10")
+    ("fg-diff-focus-removed" . "#eebdba")
+    ("bg-diff-focus-removed" . "#5e2526")
 
-      (fg-diff-neutral-0 "#fcfcfc") (bg-diff-neutral-0 "#575757")
-      (fg-diff-neutral-1 "#dddddd") (bg-diff-neutral-1 "#454545")
-      (fg-diff-neutral-2 "#bfbfbf") (bg-diff-neutral-2 "#313131")
+    ("fg-diff-neutral-0" . "#fcfcfc")
+    ("bg-diff-neutral-0" . "#575757")
+    ("fg-diff-neutral-1" . "#dddddd")
+    ("bg-diff-neutral-1" . "#454545")
+    ("fg-diff-neutral-2" . "#bfbfbf")
+    ("bg-diff-neutral-2" . "#313131")
 
-      (fg-mark "#60cfa2") (bg-mark "#002f2f")
-      (fg-mark-del "#ff99aa") (bg-mark-del "#5a0000")
-      (fg-mark-other "#f0aa20") (bg-mark-other "#3f2210")
+    ("fg-mark" . "#60cfa2")
+    ("bg-mark" . "#002f2f")
+    ("fg-mark-del" . "#ff99aa")
+    ("bg-mark-del" . "#5a0000")
+    ("fg-mark-other" . "#f0aa20")
+    ("bg-mark-other" . "#3f2210"))
+  "The entire palette of `modus-vivendi-theme'.
+Each element has the form (NAME . HEX).")
 
-      ;; conditional styles that evaluate user-facing customisation
-      ;; options
-      (modus-theme-slant
-       (if modus-vivendi-theme-slanted-constructs
-           'italic
-         'normal))
+;;;###autoload
+(defcustom modus-vivendi-theme-override-colors-alist '()
+  "Place to override default theme colors.
+You can override a subset of the theme's default colors by
+defining them in this alist."
+  :type '(alist
+          :key-type (string :tag "Name")
+          :value-type (string :tag " Hex")))
 
-      (modus-theme-bold
-       (if modus-vivendi-theme-bold-constructs
-           'bold
-         'normal))
+(defmacro modus-vivendi-theme-with-color-variables (&rest body)
+  "`let' bind all colours around BODY.
+Also bind `class' to ((class color) (min-colors 89))."
+  (declare (indent 0))
+  `(let ((class '((class color) (min-colors 89)))
+         ,@(mapcar (lambda (cons)
+                     (list (intern (car cons)) (cdr cons)))
+                   (append modus-vivendi-theme-default-colors-alist
+                           modus-vivendi-theme-override-colors-alist))
+         ;; conditional styles that evaluate user-facing customisation
+         ;; options
+         (modus-theme-slant
+          (if modus-vivendi-theme-slanted-constructs 'italic 'normal))
+         (modus-theme-bold
+          (if modus-vivendi-theme-bold-constructs 'bold 'normal))
+         (modus-theme-variable-pitch
+          (if modus-vivendi-theme-proportional-fonts 'variable-pitch 
'default)))
+     ,@body))
 
-      (modus-theme-variable-pitch
-       (if modus-vivendi-theme-proportional-fonts
-           'variable-pitch
-         'default)))
+(modus-vivendi-theme-with-color-variables
   (custom-theme-set-faces
    'modus-vivendi
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -3311,4 +3394,9 @@ AMOUNT is a customisation option."
 (provide-theme 'modus-vivendi)
 
 (provide 'modus-vivendi-theme)
+
+;; Local Variables:
+;; no-byte-compile: t
+;; indent-tabs-mode: nil
+;; End:
 ;;; modus-vivendi-theme.el ends here

Reply via email to