Write the manual's detailed guide for modus-themes-generate-palette

We can always refine the implementation details, but at least the
results are looking very promising. I think/hope users will benefit
from this enhancement.
This commit is contained in:
Protesilaos Stavrou 2025-11-24 19:39:38 +02:00
parent 80db306ddb
commit c15eea4125
No known key found for this signature in database
GPG key ID: 99BD6459CD5CA3EA
2 changed files with 834 additions and 135 deletions

View file

@ -197,6 +197,7 @@ Complete example of a Modus derivative theme
* Complete example of a package that is derived from Modus::
* Complete example of a private theme derived from Modus::
* Complete example of a custom theme with its own palette::
* Complete example that also uses modus-themes-generate-palette::
Face coverage
@ -4479,6 +4480,7 @@ do this for a package and for a private configuration:
* Complete example of a package that is derived from Modus::
* Complete example of a private theme derived from Modus::
* Complete example of a custom theme with its own palette::
* Complete example that also uses modus-themes-generate-palette::

File: modus-themes.info, Node: Complete example of a package that is derived from Modus, Next: Complete example of a private theme derived from Modus, Up: Complete example of a Modus derivative theme
@ -4605,7 +4607,7 @@ example of a custom theme with its own palette::):
nil)

File: modus-themes.info, Node: Complete example of a custom theme with its own palette, Prev: Complete example of a private theme derived from Modus, Up: Complete example of a Modus derivative theme
File: modus-themes.info, Node: Complete example of a custom theme with its own palette, Next: Complete example that also uses modus-themes-generate-palette, Prev: Complete example of a private theme derived from Modus, Up: Complete example of a Modus derivative theme
8.1.3 Complete example of a custom theme with its own palette
-------------------------------------------------------------
@ -4718,6 +4720,341 @@ this example, bg-ochre comes from the modus-operandi-palette though
it would work the same way if, say, prot-light-palette defined
bg-soil and then referenced it in prot-light-custom-faces.

File: modus-themes.info, Node: Complete example that also uses modus-themes-generate-palette, Prev: Complete example of a custom theme with its own palette, Up: Complete example of a Modus derivative theme
8.1.4 Complete example that also uses modus-themes-generate-palette
---------------------------------------------------------------------
The guide herein is of use to those who plan to create their own
derivative themes (*note Complete example of a private theme derived
from Modus::).
The modus-themes-generate-palette defines a fully flegded Modus
palette that can be passed to modus-themes-theme without necessarily
depending on any of the core Modus palettes. I will walk you through
the steps of working with something like the following code block.
[ We use color values from Solarized as an example for the rest of
this entry, naming them according to our conventions. ]
(defvar modus-solarized-dark-palette
(modus-themes-generate-palette
'((bg-main "#073642")
(fg-main "#EEE8D5")
(red "#DC322F")
(red-warmer "#CB4B16")
(green "#859900")
(yellow "#B58900")
(blue "#268BD2")
(magenta "#D33682")
(magenta-cooler "#6C71C4")
(cyan "#2AA198"))))
(modus-themes-theme
'modus-solarized-dark
'modus-solarized-themes
"Sample of a basic Solarized port."
'dark
'modus-solarized-dark-palette
nil
nil)
The Modus themes define hundreds of entries in their palette. Some
are named colors while others are semantic mappings (*note Option for
palette overrides: Palette overrides.).
This gives users maximum control via overrides, though comes at the
considerable cost of making it harder to derive a custom palette from a
small set of colors. Color schemes, which are not themes in the sense
of ensuring consistency across all elements and interfaces, will
typically provide 8 or 16 colors. This is the case with terminal
emulators. For example, the widely known Solarized theme, originally
designed by Ethan Schoonover, defines 16 colors for terminal emulators.
Nothing else. Thus a hypothetical Modus+Solarized cannot work without
knowing how to complement the base with all the extra color definitions.
This is where the function modus-themes-generate-palette comes in.
In broad terms, it is meant to be used as a starting point. The user
may then decide which results need further tweaking. But at least they
will have something to create a fully fledged Modus palette right away.
The minimum modus-themes-generate-palette needs is a list of
BASE-COLORS. Each element is of the form (NAME VALUE) where NAME
is a symbol and VALUE is a string with a hexadecimal RGB color value
or a string with a name of a color among those listed in the output of
the command list-colors-display.
The BASE-COLORS can be as short as follows:
;; All missing palette entries will be derived automatically. This
;; will return a COMPLETE Modus themes palette.
(modus-themes-generate-palette
'((bg-main "#073642")
(fg-main "#EEE8D5")))
The only two mandatory entries in BASE-COLORS are bg-main and
fg-main as shown above. In this scenario, the derived palette will
get the job done, but will be very close to what Modus defines. The
more we add to the BASE-COLORS, the more well defined the character of
the new palette will be. For example:
(modus-themes-generate-palette
;; The two base colors of Solarized, plus all its accents.
'((bg-main "#073642")
(fg-main "#EEE8D5")
(red "#DC322F")
(red-warmer "#CB4B16")
(green "#859900")
(yellow "#B58900")
(blue "#268BD2")
(magenta "#D33682")
(magenta-cooler "#6C71C4")
(cyan "#2AA198")))
This is already going to be a tolerable port of Solarized. Though we
can go further and greatly improve the results.
The modus-themes-generate-palette will internally calculate colors
based on what it receives. Anything missing will be taken from a core
Modus palette, depending on the value of bg-main: if it is light, then
the modus-themes-operandi-palette is used, otherwise it is
modus-themes-vivendi-palette. What also plays a role in the interal
calculations is whether bg-main is a cool or warm color, meaning
whether it is closer to blue or red, respectively. If it is cool,
then the aforementioned palettes are used. Else the
modus-themes-operandi-tinted-palette and
modus-themes-vivendi-tinted-palette are picked. Internally, cool or
warm also influences the kind of color values and semantic mappings
that will go into the new palette.
The modus-themes-generate-palette accepts an optional parameter
called COOL-OR-WARM-PREFERENCE. This is a preference for the symbol
cool or warm: it make the decision explicit.
For example, Solarized can swap the values of bg-main and fg-main
to switch between its light and dark implementations (I understand this
is a smart trick for terminal emulators, but is otherwise not good
enough for thematic consistency as some accent values look out-of-place
and the contrasts vary considerably). The light color Solarized uses is
inherently warm (yellowish color means it is closer to red than blue)
while the dark color is cool, due to it being closer to pure blue.
Users may wish to experiment with a deviation from what would have been
the default output, such that the dark blue when used as a background
actually combines with warmer foreground hues, while the light cream
background goes together with cooler foreground values. Thus:
(modus-themes-generate-palette
'((bg-main "#073642") ; normally this is a `cool' theme
(fg-main "#EEE8D5")
(red "#DC322F")
(red-warmer "#CB4B16")
(green "#859900")
(yellow "#B58900")
(blue "#268BD2")
(magenta "#D33682")
(magenta-cooler "#6C71C4")
(cyan "#2AA198"))
'warm) ; but we want to use it with `warm' foregrounds
;; And here is the inverse of the above, now with the light version of
;; Solarized.
(modus-themes-generate-palette
'((bg-main "#EEE8D5") ; normally this is a `warm' theme
(fg-main "#073642")
(red "#DC322F")
(red-warmer "#CB4B16")
(green "#859900")
(yellow "#B58900")
(blue "#268BD2")
(magenta "#D33682")
(magenta-cooler "#6C71C4")
(cyan "#2AA198"))
'cool) ; but we want to use it with `cool' foregrounds
This is now getting better, but we can go further. At this point
users should be able to do the common work of taking a color scheme that
was originally designed for terminal emulators and quickly turning it
into a fully fledged Modus palette. All they need is to follow the
naming convention for bg-main, fg-main, and then
{red,green,yellow,blue,magenta,cyan}{,-warmer,-cooler}. Preview a
palette to get the complete list (*note Preview theme colors::). And,
again, remember that not all colors need to be defined in BASE-COLORS
(e.g. we could leave out magenta-cooler if we do not care about it).
The next optional parameter of modus-themes-generate-palette is the
CORE-PALETTE it should use. This is to make explicit the decision
that is otherwise handled internally on whether to fill in any missing
palette entries from Modus Operandi or Modus Vivendi (or their tinted
variants), as explained above.
The CORE-PALETTE is the symbol of a variable whose value is a
palette, like modus-themes-operandi-palette. Normally, users do not
need to ever set CORE-PALETTE. The only two scenaria where this is
likely helpful is (i) the theme is optimized for red-green or
blue-yellow color deficiency, in which case one of the Modus palettes
for deuteranopia and tritanopia is needed, or (ii) the user wants to use
a palette from a Modus derivative theme, such as my ef-themes and
standard-themes. In the latter scenario, users need to take care to
either copy the palette they want to use or, anyhow, load the relevant
files.
In the interest of clarity, here is how the CORE-PALETTE is passed,
but, again, users probably should leave this to nil:
(modus-themes-generate-palette
;; The two base colors of Solarized, plus all its accents.
'((bg-main "#073642")
(fg-main "#EEE8D5")
(red "#DC322F")
(red-warmer "#CB4B16")
(green "#859900")
(yellow "#B58900")
(blue "#268BD2")
(magenta "#D33682")
(magenta-cooler "#6C71C4")
(cyan "#2AA198"))
nil ; COOL-OR-WARM-PREFERENCE is derived internally based on `bg-main'
'modus-themes-vivendi-tritanopia-palette) ; we specifically want this as our CORE-PALETTE
With core Modus palettes, the CORE-PALETTE should not make much of
a difference. Though a completely custom Modus derivative, like one of
the ef-themes, will be defining colors values that differ
substantially from those of core Modus, as well as completely different
semantic mappings.
Finally, modus-themes-generate-palette has an optional MAPPINGS
parameter. This is a list of semantic mappings where each entry is of
the form (NAME OTHER-NAME) (*note Option for palette overrides:
Palette overrides.). The NAME has the same meaning as for the
BASE-COLORS we have been examining all along, while OTHER-NAME is
the symbol of another NAME that exists in the palette, hence the
mapping. This manual contains lots of examples along those lines (*note
DIY Stylistic variants using palette overrides::). For our purposes, we
will modify some of the obvious elements of the theme, namely, the
cursor, mode lines, current line highlight, and active region.
(modus-themes-generate-palette
;; The two base colors of Solarized, plus all its accents.
'((bg-main "#073642")
(fg-main "#EEE8D5")
(red "#DC322F")
(red-warmer "#CB4B16")
(green "#859900")
(yellow "#B58900")
(blue "#268BD2")
(magenta "#D33682")
(magenta-cooler "#6C71C4")
(cyan "#2AA198"))
nil ; COOL-OR-WARM-PREFERENCE is derived internally based on `bg-main'
nil ; as I explained at length, we normally do not want to specify CORE-PALETTE
'((cursor magenta-warmer) ; all the colors here are derived from the BASE-COLORS above
(bg-hl-line bg-cyan-nuanced)
(bg-region bg-green-intense)
(fg-region fg-dim)
(bg-mode-line-active bg-blue-subtle)
(fg-mode-line-active blue-cooler)
(border-mode-line-active fg-dim)))
The MAPPINGS can be as long as the user needs. Whatever is defined
here will take precedence of what the CORE-PALETTE (or its internally
derived equivalent) provides. At most, users can have a completely
custom palette. Though I expect that this will not be done at the
outset, but only after a long process of experimentation (if you already
knew how to do this, modus-themes-generate-palette would not be of
real value). The point is to start with something that works and then
refine it one small step at a time.
We are now ready to try our Solarized themes, using the example of
doing this in our private configuration (*note Complete example of a
package that is derived from Modus::).
• Create two files, one is called modus-solarized-dark-theme.el (or
however you want to identify it, but always keep -theme.el at the
end) and the other is modus-solarized-light-theme.
• Add their directory to the custom-theme-load-path, like
(add-to-list 'custom-theme-load-path
"~/.emacs.d/custom-themes/").
• Use the minimal code from the following two blocks to create your
new themes.
• Optionally activate modus-themes-include-derivatives-mode to have
all Modus commands recognize your themes.
• Load your themes with load-theme.
• Enjoy!
;; Modus+Solarized dark
(defvar modus-solarized-dark-palette
(modus-themes-generate-palette
;; The two base colors of Solarized, plus all its accents.
'((bg-main "#073642")
(fg-main "#EEE8D5")
(red "#DC322F")
(red-warmer "#CB4B16")
(green "#859900")
(yellow "#B58900")
(blue "#268BD2")
(magenta "#D33682")
(magenta-cooler "#6C71C4")
(cyan "#2AA198"))
nil ; COOL-OR-WARM-PREFERENCE is derived internally based on `bg-main'
nil ; as I explained at length, we normally do not want to specify CORE-PALETTE
'((cursor magenta-warmer) ; all the colors here are derived from the BASE-COLORS above
(bg-hl-line bg-cyan-nuanced)
(bg-region bg-green-intense)
(fg-region fg-dim)
(bg-mode-line-active bg-blue-subtle)
(fg-mode-line-active blue-cooler)
(border-mode-line-active fg-dim))))
(modus-themes-theme
'modus-solarized-dark
'modus-solarized-themes
"Sample of a basic Solarized dark port."
'dark
'modus-solarized-dark-palette
nil
nil)
And the light variant:
;; Modus+Solarized light
(defvar modus-solarized-light-palette
(modus-themes-generate-palette
;; The two base colors of Solarized, plus all its accents.
'((bg-main "#EEE8D5")
(fg-main "#073642")
(red "#DC322F")
(red-warmer "#CB4B16")
(green "#859900")
(yellow "#B58900")
(blue "#268BD2")
(magenta "#D33682")
(magenta-cooler "#6C71C4")
(cyan "#2AA198"))
nil ; COOL-OR-WARM-PREFERENCE is derived internally based on `bg-main'
nil ; as I explained at length, we normally do not want to specify CORE-PALETTE
'((cursor yellow-warmer) ; all the colors here are derived from the BASE-COLORS above
(bg-hl-line bg-red-nuanced)
(bg-region bg-blue-intense)
(fg-region fg-dim)
(bg-mode-line-active bg-cyan-subtle)
(fg-mode-line-active cyan-cooler)
(border-mode-line-active fg-dim))))
(modus-themes-theme
'modus-solarized-light
'modus-solarized-themes
"Sample of a basic Solarized light port."
'light
'modus-solarized-light-palette
nil
nil)

File: modus-themes.info, Node: Determine what counts as a Modus theme, Next: Create convenience commands to load a derivative theme, Prev: Complete example of a Modus derivative theme, Up: Build on top of the Modus themes
@ -6998,6 +7335,8 @@ B.1 Function index
(line 6)
* modus-themes-define-derivative-command: Create convenience commands to load a derivative theme.
(line 10)
* modus-themes-generate-palette: Complete example that also uses modus-themes-generate-palette.
(line 54)
* modus-themes-get-all-known-themes: Determine what counts as a Modus theme.
(line 10)
* modus-themes-get-color-value: Get a single color from the palette with modus-themes-get-color-value.
@ -7096,6 +7435,8 @@ B.2 Variable index
* modus-themes-items: Option for which themes to rotate.
(line 15)
* modus-themes-mixed-fonts: Mixed fonts. (line 6)
* modus-themes-operandi-palette: Complete example that also uses modus-themes-generate-palette.
(line 95)
* modus-themes-org-blocks: Org mode blocks. (line 6)
* modus-themes-post-load-hook: Enable and load. (line 86)
* modus-themes-preset-overrides-cooler: DIY Palette override presets.
@ -7116,6 +7457,8 @@ B.2 Variable index
* modus-themes-to-toggle: Option for which themes to toggle.
(line 9)
* modus-themes-variable-pitch-ui: UI typeface. (line 6)
* modus-themes-vivendi-palette: Complete example that also uses modus-themes-generate-palette.
(line 95)
* modus-vivendi-deuteranopia-palette-overrides: Palette overrides.
(line 38)
* modus-vivendi-deuteranopia-palette-user: Palette extension. (line 32)
@ -7151,6 +7494,8 @@ B.3 Concept index
* Contributing: Issues you can help with.
(line 6)
* Contributors: Acknowledgements. (line 6)
* Easily define a fully fledged Modus palette: Complete example that also uses modus-themes-generate-palette.
(line 6)
* Essential configuration: Enable and load. (line 6)
* Explicitly supported packages: Supported packages. (line 6)
* Font configurations: DIY Font configurations for Org and others.
@ -7196,140 +7541,141 @@ B.3 Concept index

Tag Table:
Node: Top874
Node: Overview9039
Node: How do the themes look like11805
Node: Learn about the latest changes12164
Node: Installation12552
Node: Install manually from source13463
Node: Install from the archives14286
Node: Install on GNU/Linux14885
Node: Debian 11 Bullseye15376
Node: GNU Guix15784
Node: Dealing with byte compilation errors16067
Node: Enable and load17225
Node: The require-theme for built-in Emacs themes21504
Node: Sample configuration22421
Node: Differences between loading and enabling24697
Node: Customization options26762
Node: Disable other themes30531
Node: Bold constructs31885
Node: Italic constructs32757
Node: Option for which themes to toggle33585
Node: Option for which themes to rotate34348
Node: Mixed fonts35345
Node: Command prompts36399
Node: Completion UIs38240
Node: Org mode blocks41089
Node: Heading styles41732
Node: UI typeface46158
Node: Palette overrides47131
Node: Palette extension51488
Node: Preview theme colors53964
Node: Commands for the preview palette buffer55619
Node: Use colors from the Modus themes palette57697
Node: Get a single color from the palette with modus-themes-get-color-value58561
Node: Use theme colors in code with modus-themes-with-colors60922
Node: Advanced customization63176
Node: DIY Palette override presets64954
Node: DIY Add support for engrave-faces67788
Node: DIY Stylistic variants using palette overrides77771
Node: DIY Make the mode line borderless79830
Node: DIY Make the active mode line colorful81205
Node: DIY Make the tab bar more or less colorful83423
Node: DIY Make the fringe invisible or another color85360
Node: DIY Make links use subtle or no underlines86557
Node: DIY Make prompts more or less colorful87675
Node: DIY Make completion matches more or less colorful88998
Node: DIY Make comments yellow and strings green92557
Node: DIY Make code syntax use the old alt-syntax style94264
Node: DIY Make use of alternative styles for code syntax97377
Node: DIY Make matching parenthesis more or less intense100839
Node: DIY Make box buttons more or less gray102211
Node: DIY Make TODO and DONE more or less intense103224
Node: DIY Make headings more or less colorful104725
Node: DIY Make Org block colors more or less colorful106842
Node: DIY Make Org agenda more or less colorful111214
Node: DIY Make inline code in prose use alternative styles114389
Node: DIY Make mail citations and headers more or less colorful116629
Node: DIY Make the region preserve text colors plus other styles119029
Node: DIY Make mouse highlights more or less colorful120585
Node: DIY Make language underlines less colorful121598
Node: DIY Make line numbers use alternative styles122750
Node: DIY Make diffs use only a foreground124393
Node: DIY Make deuteranopia diffs red and blue instead of yellow and blue127280
Node: DIY More accurate colors in terminal emulators129752
Node: DIY Range of color with terminal emulators131060
Node: DIY Per-theme customization settings133847
Node: DIY Do not extend the region background135280
Node: DIY Add padding to the mode line136078
Node: DIY Remap face with local value139006
Node: DIY Font configurations for Org and others141545
Ref: DIY Font configurations for Org and others-Footnote-1144528
Node: DIY Configure bold and italic faces144715
Node: DIY Custom Org todo keyword and priority faces149337
Node: DIY Custom Org emphasis faces153078
Node: DIY Use colored Org source blocks per language157955
Node: DIY Measure color contrast162595
Node: DIY Load theme depending on time of day165312
Node: DIY Backdrop for pdf-tools166340
Node: DIY Toggle themes without reloading them169501
Node: DIY Use more spacious margins or padding in Emacs frames170810
Node: DIY Custom hl-todo colors175047
Node: DIY Add support for solaire-mode176864
Node: DIY Add support for meow-mode179956
Node: DIY Add support for combobulate181766
Node: DIY Use a hook at the post-load-theme phase185389
Node: DIY A theme-agnostic hook for theme loading187510
Node: Build on top of the Modus themes190141
Node: Complete example of a Modus derivative theme196314
Node: Complete example of a package that is derived from Modus197254
Node: Complete example of a private theme derived from Modus200193
Node: Complete example of a custom theme with its own palette201759
Node: Determine what counts as a Modus theme206300
Node: Create convenience commands to load a derivative theme209710
Node: Face coverage211927
Node: Supported packages212389
Node: Indirectly covered packages218255
Node: Notes on individual packages219611
Node: Note on calendarel weekday and weekend colors220713
Node: Note on git-gutter in Doom Emacs221863
Node: Note on php-mode multiline comments224365
Node: Note on underlines in compilation buffers225127
Node: Note on inline Latex in Org buffers226001
Node: Note on dimmerel226613
Node: Note on display-fill-column-indicator-mode228100
Node: Note on highlight-parenthesesel229553
Node: Note on mmm-modeel background colors235632
Node: Note for prism237986
Node: Note on company-mode overlay pop-up241200
Ref: Note on company-mode overlay pop-up-Footnote-1241930
Ref: Note on company-mode overlay pop-up-Footnote-2241997
Node: Note on ERC escaped color sequences242052
Ref: Note on ERC escaped color sequences-Footnote-1243482
Node: Note on powerline or spaceline243592
Node: Note on SHR colors244008
Node: Note on SHR fonts244430
Node: Note on Ement colors and fonts245119
Node: Note on pdf-tools link hints246625
Node: Note on the Notmuch logo249083
Node: Note on goto-address-mode faces249617
Node: Frequently Asked Questions250737
Node: Is the contrast ratio about adjacent colors?251368
Node: What does it mean to avoid exaggerations?252877
Node: Why are colors mostly variants of blue magenta cyan?254727
Node: What is the best setup for legibility?259061
Node: Are these color schemes?261703
Node: Port the Modus themes to other platforms?265357
Node: Contributing268191
Node: Sources of the themes268590
Node: Issues you can help with269486
Node: Patches require copyright assignment to the FSF270878
Node: Acknowledgements273100
Node: GNU Free Documentation License277720
Node: Indices302883
Node: Function index303062
Node: Variable index308043
Node: Concept index312406
Node: Overview9105
Node: How do the themes look like11871
Node: Learn about the latest changes12230
Node: Installation12618
Node: Install manually from source13529
Node: Install from the archives14352
Node: Install on GNU/Linux14951
Node: Debian 11 Bullseye15442
Node: GNU Guix15850
Node: Dealing with byte compilation errors16133
Node: Enable and load17291
Node: The require-theme for built-in Emacs themes21570
Node: Sample configuration22487
Node: Differences between loading and enabling24763
Node: Customization options26828
Node: Disable other themes30597
Node: Bold constructs31951
Node: Italic constructs32823
Node: Option for which themes to toggle33651
Node: Option for which themes to rotate34414
Node: Mixed fonts35411
Node: Command prompts36465
Node: Completion UIs38306
Node: Org mode blocks41155
Node: Heading styles41798
Node: UI typeface46224
Node: Palette overrides47197
Node: Palette extension51554
Node: Preview theme colors54030
Node: Commands for the preview palette buffer55685
Node: Use colors from the Modus themes palette57763
Node: Get a single color from the palette with modus-themes-get-color-value58627
Node: Use theme colors in code with modus-themes-with-colors60988
Node: Advanced customization63242
Node: DIY Palette override presets65020
Node: DIY Add support for engrave-faces67854
Node: DIY Stylistic variants using palette overrides77837
Node: DIY Make the mode line borderless79896
Node: DIY Make the active mode line colorful81271
Node: DIY Make the tab bar more or less colorful83489
Node: DIY Make the fringe invisible or another color85426
Node: DIY Make links use subtle or no underlines86623
Node: DIY Make prompts more or less colorful87741
Node: DIY Make completion matches more or less colorful89064
Node: DIY Make comments yellow and strings green92623
Node: DIY Make code syntax use the old alt-syntax style94330
Node: DIY Make use of alternative styles for code syntax97443
Node: DIY Make matching parenthesis more or less intense100905
Node: DIY Make box buttons more or less gray102277
Node: DIY Make TODO and DONE more or less intense103290
Node: DIY Make headings more or less colorful104791
Node: DIY Make Org block colors more or less colorful106908
Node: DIY Make Org agenda more or less colorful111280
Node: DIY Make inline code in prose use alternative styles114455
Node: DIY Make mail citations and headers more or less colorful116695
Node: DIY Make the region preserve text colors plus other styles119095
Node: DIY Make mouse highlights more or less colorful120651
Node: DIY Make language underlines less colorful121664
Node: DIY Make line numbers use alternative styles122816
Node: DIY Make diffs use only a foreground124459
Node: DIY Make deuteranopia diffs red and blue instead of yellow and blue127346
Node: DIY More accurate colors in terminal emulators129818
Node: DIY Range of color with terminal emulators131126
Node: DIY Per-theme customization settings133913
Node: DIY Do not extend the region background135346
Node: DIY Add padding to the mode line136144
Node: DIY Remap face with local value139072
Node: DIY Font configurations for Org and others141611
Ref: DIY Font configurations for Org and others-Footnote-1144594
Node: DIY Configure bold and italic faces144781
Node: DIY Custom Org todo keyword and priority faces149403
Node: DIY Custom Org emphasis faces153144
Node: DIY Use colored Org source blocks per language158021
Node: DIY Measure color contrast162661
Node: DIY Load theme depending on time of day165378
Node: DIY Backdrop for pdf-tools166406
Node: DIY Toggle themes without reloading them169567
Node: DIY Use more spacious margins or padding in Emacs frames170876
Node: DIY Custom hl-todo colors175113
Node: DIY Add support for solaire-mode176930
Node: DIY Add support for meow-mode180022
Node: DIY Add support for combobulate181832
Node: DIY Use a hook at the post-load-theme phase185455
Node: DIY A theme-agnostic hook for theme loading187576
Node: Build on top of the Modus themes190207
Node: Complete example of a Modus derivative theme196380
Node: Complete example of a package that is derived from Modus197386
Node: Complete example of a private theme derived from Modus200325
Node: Complete example of a custom theme with its own palette201891
Node: Complete example that also uses modus-themes-generate-palette206502
Node: Determine what counts as a Modus theme221240
Node: Create convenience commands to load a derivative theme224650
Node: Face coverage226867
Node: Supported packages227329
Node: Indirectly covered packages233195
Node: Notes on individual packages234551
Node: Note on calendarel weekday and weekend colors235653
Node: Note on git-gutter in Doom Emacs236803
Node: Note on php-mode multiline comments239305
Node: Note on underlines in compilation buffers240067
Node: Note on inline Latex in Org buffers240941
Node: Note on dimmerel241553
Node: Note on display-fill-column-indicator-mode243040
Node: Note on highlight-parenthesesel244493
Node: Note on mmm-modeel background colors250572
Node: Note for prism252926
Node: Note on company-mode overlay pop-up256140
Ref: Note on company-mode overlay pop-up-Footnote-1256870
Ref: Note on company-mode overlay pop-up-Footnote-2256937
Node: Note on ERC escaped color sequences256992
Ref: Note on ERC escaped color sequences-Footnote-1258422
Node: Note on powerline or spaceline258532
Node: Note on SHR colors258948
Node: Note on SHR fonts259370
Node: Note on Ement colors and fonts260059
Node: Note on pdf-tools link hints261565
Node: Note on the Notmuch logo264023
Node: Note on goto-address-mode faces264557
Node: Frequently Asked Questions265677
Node: Is the contrast ratio about adjacent colors?266308
Node: What does it mean to avoid exaggerations?267817
Node: Why are colors mostly variants of blue magenta cyan?269667
Node: What is the best setup for legibility?274001
Node: Are these color schemes?276643
Node: Port the Modus themes to other platforms?280297
Node: Contributing283131
Node: Sources of the themes283530
Node: Issues you can help with284426
Node: Patches require copyright assignment to the FSF285818
Node: Acknowledgements288040
Node: GNU Free Documentation License292660
Node: Indices317823
Node: Function index318002
Node: Variable index323160
Node: Concept index327877

End Tag Table

View file

@ -4551,6 +4551,359 @@ this example, =bg-ochre= comes from the ~modus-operandi-palette~
though it would work the same way if, say, ~prot-light-palette~
defined ~bg-soil~ and then referenced it in ~prot-light-custom-faces~.
*** Complete example that also uses ~modus-themes-generate-palette~
:PROPERTIES:
:CUSTOM_ID: h:3a7ede17-f0d4-4322-8e69-1804ed69012b
:END:
#+cindex: Easily define a fully fledged Modus palette
The guide herein is of use to those who plan to create their own
derivative themes ([[#h:48e391a6-831b-48ec-b92d-4e7e6871b043][Complete example of a private theme derived from Modus]]).
The ~modus-themes-generate-palette~ defines a fully flegded Modus
palette that can be passed to ~modus-themes-theme~ without necessarily
depending on any of the core Modus palettes. I will walk you through
the steps of working with something like the following code block.
[ We use color values from Solarized as an example for the rest of
this entry, naming them according to our conventions. ]
#+begin_src emacs-lisp
(defvar modus-solarized-dark-palette
(modus-themes-generate-palette
'((bg-main "#073642")
(fg-main "#EEE8D5")
(red "#DC322F")
(red-warmer "#CB4B16")
(green "#859900")
(yellow "#B58900")
(blue "#268BD2")
(magenta "#D33682")
(magenta-cooler "#6C71C4")
(cyan "#2AA198"))))
(modus-themes-theme
'modus-solarized-dark
'modus-solarized-themes
"Sample of a basic Solarized port."
'dark
'modus-solarized-dark-palette
nil
nil)
#+end_src
The Modus themes define hundreds of entries in their palette. Some are
named colors while others are semantic mappings ([[#h:34c7a691-19bb-4037-8d2f-67a07edab150][Option for palette overrides]]).
This gives users maximum control via overrides, though comes at the
considerable cost of making it harder to derive a custom palette from
a small set of colors. Color schemes, which are not themes in the
sense of ensuring consistency across all elements and interfaces, will
typically provide 8 or 16 colors. This is the case with terminal
emulators. For example, the widely known Solarized theme, originally
designed by Ethan Schoonover, defines 16 colors for terminal
emulators. Nothing else. Thus a hypothetical Modus+Solarized cannot
work without knowing how to complement the base with all the extra
color definitions.
#+findex: modus-themes-generate-palette
This is where the function ~modus-themes-generate-palette~ comes in.
In broad terms, it is meant to be used as a starting point. The user
may then decide which results need further tweaking. But at least they
will have something to create a fully fledged Modus palette right
away.
The minimum ~modus-themes-generate-palette~ needs is a list of
=BASE-COLORS=. Each element is of the form =(NAME VALUE)= where =NAME=
is a symbol and =VALUE= is a string with a hexadecimal RGB color value
or a string with a name of a color among those listed in the output of
the command ~list-colors-display~.
The =BASE-COLORS= can be as short as follows:
#+begin_src emacs-lisp
;; All missing palette entries will be derived automatically. This
;; will return a COMPLETE Modus themes palette.
(modus-themes-generate-palette
'((bg-main "#073642")
(fg-main "#EEE8D5")))
#+end_src
The only two mandatory entries in =BASE-COLORS= are =bg-main= and
=fg-main= as shown above. In this scenario, the derived palette will
get the job done, but will be very close to what Modus defines. The
more we add to the =BASE-COLORS=, the more well defined the character
of the new palette will be. For example:
#+begin_src emacs-lisp
(modus-themes-generate-palette
;; The two base colors of Solarized, plus all its accents.
'((bg-main "#073642")
(fg-main "#EEE8D5")
(red "#DC322F")
(red-warmer "#CB4B16")
(green "#859900")
(yellow "#B58900")
(blue "#268BD2")
(magenta "#D33682")
(magenta-cooler "#6C71C4")
(cyan "#2AA198")))
#+end_src
This is already going to be a tolerable port of Solarized. Though we
can go further and greatly improve the results.
#+vindex: modus-themes-operandi-palette
#+vindex: modus-themes-vivendi-palette
The ~modus-themes-generate-palette~ will internally calculate colors
based on what it receives. Anything missing will be taken from a core
Modus palette, depending on the value of =bg-main=: if it is light,
then the ~modus-themes-operandi-palette~ is used, otherwise it is
~modus-themes-vivendi-palette~. What also plays a role in the interal
calculations is whether =bg-main= is a =cool= or =warm= color, meaning
whether it is closer to blue or red, respectively. If it is =cool=,
then the aforementioned palettes are used. Else the
~modus-themes-operandi-tinted-palette~ and
~modus-themes-vivendi-tinted-palette~ are picked. Internally, =cool=
or =warm= also influences the kind of color values and semantic
mappings that will go into the new palette.
The ~modus-themes-generate-palette~ accepts an optional parameter
called =COOL-OR-WARM-PREFERENCE=. This is a preference for the symbol
=cool= or =warm=: it make the decision explicit.
For example, Solarized can swap the values of =bg-main= and =fg-main=
to switch between its light and dark implementations (I understand
this is a smart trick for terminal emulators, but is otherwise not
good enough for thematic consistency as some accent values look
out-of-place and the contrasts vary considerably). The light color
Solarized uses is inherently =warm= (yellowish color means it is
closer to red than blue) while the dark color is =cool=, due to it
being closer to pure blue. Users may wish to experiment with a
deviation from what would have been the default output, such that the
dark blue when used as a background actually combines with warmer
foreground hues, while the light cream background goes together with
cooler foreground values. Thus:
#+begin_src emacs-lisp
(modus-themes-generate-palette
'((bg-main "#073642") ; normally this is a `cool' theme
(fg-main "#EEE8D5")
(red "#DC322F")
(red-warmer "#CB4B16")
(green "#859900")
(yellow "#B58900")
(blue "#268BD2")
(magenta "#D33682")
(magenta-cooler "#6C71C4")
(cyan "#2AA198"))
'warm) ; but we want to use it with `warm' foregrounds
;; And here is the inverse of the above, now with the light version of
;; Solarized.
(modus-themes-generate-palette
'((bg-main "#EEE8D5") ; normally this is a `warm' theme
(fg-main "#073642")
(red "#DC322F")
(red-warmer "#CB4B16")
(green "#859900")
(yellow "#B58900")
(blue "#268BD2")
(magenta "#D33682")
(magenta-cooler "#6C71C4")
(cyan "#2AA198"))
'cool) ; but we want to use it with `cool' foregrounds
#+end_src
This is now getting better, but we can go further. At this point users
should be able to do the common work of taking a color scheme that was
originally designed for terminal emulators and quickly turning it into
a fully fledged Modus palette. All they need is to follow the naming
convention for =bg-main=, =fg-main=, and then
={red,green,yellow,blue,magenta,cyan}{,-warmer,-cooler}=. Preview a
palette to get the complete list ([[#h:f4d4b71b-2ca5-4c3d-b0b4-9bfd7aa7fb4d][Preview theme colors]]). And, again,
remember that not all colors need to be defined in =BASE-COLORS= (e.g.
we could leave out ~magenta-cooler~ if we do not care about it).
The next optional parameter of ~modus-themes-generate-palette~ is the
=CORE-PALETTE= it should use. This is to make explicit the decision
that is otherwise handled internally on whether to fill in any missing
palette entries from Modus Operandi or Modus Vivendi (or their tinted
variants), as explained above.
The =CORE-PALETTE= is the symbol of a variable whose value is a
palette, like ~modus-themes-operandi-palette~. Normally, users do not
need to ever set =CORE-PALETTE=. The only two scenaria where this is
likely helpful is (i) the theme is optimized for red-green or
blue-yellow color deficiency, in which case one of the Modus palettes
for deuteranopia and tritanopia is needed, or (ii) the user wants to
use a palette from a Modus derivative theme, such as my ~ef-themes~
and ~standard-themes~. In the latter scenario, users need to take care
to either copy the palette they want to use or, anyhow, ~load~ the
relevant files.
In the interest of clarity, here is how the =CORE-PALETTE= is passed,
but, again, users probably should leave this to ~nil~:
#+begin_src emacs-lisp
(modus-themes-generate-palette
;; The two base colors of Solarized, plus all its accents.
'((bg-main "#073642")
(fg-main "#EEE8D5")
(red "#DC322F")
(red-warmer "#CB4B16")
(green "#859900")
(yellow "#B58900")
(blue "#268BD2")
(magenta "#D33682")
(magenta-cooler "#6C71C4")
(cyan "#2AA198"))
nil ; COOL-OR-WARM-PREFERENCE is derived internally based on `bg-main'
'modus-themes-vivendi-tritanopia-palette) ; we specifically want this as our CORE-PALETTE
#+end_src
With core Modus palettes, the =CORE-PALETTE= should not make much of a
difference. Though a completely custom Modus derivative, like one of
the ~ef-themes~, will be defining colors values that differ
substantially from those of core Modus, as well as completely
different semantic mappings.
Finally, ~modus-themes-generate-palette~ has an optional =MAPPINGS=
parameter. This is a list of semantic mappings where each entry is of
the form =(NAME OTHER-NAME)= ([[#h:34c7a691-19bb-4037-8d2f-67a07edab150][Option for palette overrides]]). The
=NAME= has the same meaning as for the =BASE-COLORS= we have been
examining all along, while =OTHER-NAME= is the symbol of another
=NAME= that exists in the palette, hence the mapping. This manual
contains lots of examples along those lines ([[#h:df1199d8-eaba-47db-805d-6b568a577bf3][DIY Stylistic variants using palette overrides]]).
For our purposes, we will modify some of the obvious elements of the
theme, namely, the cursor, mode lines, current line highlight, and
active region.
#+begin_src emacs-lisp
(modus-themes-generate-palette
;; The two base colors of Solarized, plus all its accents.
'((bg-main "#073642")
(fg-main "#EEE8D5")
(red "#DC322F")
(red-warmer "#CB4B16")
(green "#859900")
(yellow "#B58900")
(blue "#268BD2")
(magenta "#D33682")
(magenta-cooler "#6C71C4")
(cyan "#2AA198"))
nil ; COOL-OR-WARM-PREFERENCE is derived internally based on `bg-main'
nil ; as I explained at length, we normally do not want to specify CORE-PALETTE
'((cursor magenta-warmer) ; all the colors here are derived from the BASE-COLORS above
(bg-hl-line bg-cyan-nuanced)
(bg-region bg-green-intense)
(fg-region fg-dim)
(bg-mode-line-active bg-blue-subtle)
(fg-mode-line-active blue-cooler)
(border-mode-line-active fg-dim)))
#+end_src
The =MAPPINGS= can be as long as the user needs. Whatever is defined
here will take precedence of what the =CORE-PALETTE= (or its
internally derived equivalent) provides. At most, users can have a
completely custom palette. Though I expect that this will not be done
at the outset, but only after a long process of experimentation (if
you already knew how to do this, ~modus-themes-generate-palette~ would
not be of real value). The point is to start with something that works
and then refine it one small step at a time.
We are now ready to try our Solarized themes, using the example of
doing this in our private configuration ([[#h:f2757848-ea41-4cd7-a04d-7e650555a59b][Complete example of a package that is derived from Modus]]).
- Create two files, one is called =modus-solarized-dark-theme.el= (or
however you want to identify it, but always keep =-theme.el= at the
end) and the other is =modus-solarized-light-theme=.
- Add their directory to the ~custom-theme-load-path~, like
~(add-to-list 'custom-theme-load-path "~/.emacs.d/custom-themes/")~.
- Use the minimal code from the following two blocks to create your
new themes.
- Optionally activate ~modus-themes-include-derivatives-mode~ to have
all Modus commands recognize your themes.
- Load your themes with ~load-theme~.
- Enjoy!
#+begin_src emacs-lisp
;; Modus+Solarized dark
(defvar modus-solarized-dark-palette
(modus-themes-generate-palette
;; The two base colors of Solarized, plus all its accents.
'((bg-main "#073642")
(fg-main "#EEE8D5")
(red "#DC322F")
(red-warmer "#CB4B16")
(green "#859900")
(yellow "#B58900")
(blue "#268BD2")
(magenta "#D33682")
(magenta-cooler "#6C71C4")
(cyan "#2AA198"))
nil ; COOL-OR-WARM-PREFERENCE is derived internally based on `bg-main'
nil ; as I explained at length, we normally do not want to specify CORE-PALETTE
'((cursor magenta-warmer) ; all the colors here are derived from the BASE-COLORS above
(bg-hl-line bg-cyan-nuanced)
(bg-region bg-green-intense)
(fg-region fg-dim)
(bg-mode-line-active bg-blue-subtle)
(fg-mode-line-active blue-cooler)
(border-mode-line-active fg-dim))))
(modus-themes-theme
'modus-solarized-dark
'modus-solarized-themes
"Sample of a basic Solarized dark port."
'dark
'modus-solarized-dark-palette
nil
nil)
#+end_src
And the light variant:
#+begin_src emacs-lisp
;; Modus+Solarized light
(defvar modus-solarized-light-palette
(modus-themes-generate-palette
;; The two base colors of Solarized, plus all its accents.
'((bg-main "#EEE8D5")
(fg-main "#073642")
(red "#DC322F")
(red-warmer "#CB4B16")
(green "#859900")
(yellow "#B58900")
(blue "#268BD2")
(magenta "#D33682")
(magenta-cooler "#6C71C4")
(cyan "#2AA198"))
nil ; COOL-OR-WARM-PREFERENCE is derived internally based on `bg-main'
nil ; as I explained at length, we normally do not want to specify CORE-PALETTE
'((cursor yellow-warmer) ; all the colors here are derived from the BASE-COLORS above
(bg-hl-line bg-red-nuanced)
(bg-region bg-blue-intense)
(fg-region fg-dim)
(bg-mode-line-active bg-cyan-subtle)
(fg-mode-line-active cyan-cooler)
(border-mode-line-active fg-dim))))
(modus-themes-theme
'modus-solarized-light
'modus-solarized-themes
"Sample of a basic Solarized light port."
'light
'modus-solarized-light-palette
nil
nil)
#+end_src
** Determine what counts as a Modus theme
:PROPERTIES:
:CUSTOM_ID: h:412e3017-81fe-4a95-97a6-225de1867757