technicolor
offers a uniform API to access a specified collection of colors
defined in your currently-enabled theme.
See this accompanying blog post detailing the problem, solution, and example usage.
Let’s say you use DOOM themes and you use the foreground color from the doom
theme palette somewhere in elisp. That’s great! DOOM themes offer an API for that:
(doom-color 'fg)
.
But you also use modus-themes
sometimes, and you want to use the modus
foreground color. No problem, modus offers an API too:
(modus-themes-get-color-value 'fg-main)
. Oops, the symbol of the color is
different, and the function to access the color is different. I guess you can
add some branches in your elisp that determine if the current theme is a DOOM or
modus theme…
..except you also sometimes use catppuccin-theme
, and ef-themes
, and…
What to do? Add branches ad nauseam to cover every possible theme you might have active?
technicolor hopes to solve this issue by letting users define a “universal color palette” in which they can access these colors from any currently-set theme coming from a list of themes the user specifies with a single API.
Configured properly, the above situation would reduce to (technicolor-get-color 'foreground)
.
technicolor comes with some limited configuration associated to a few popular theme packs:
- DOOM themes
- Prot’s themes (modus-, ef-, standard-)
- catppuccin theme
These are good starting points, but the user should still peer into the color palettes and decide how they want to map colors. Here is an example:
Let’s say you want to access the foreground color in elisp for the DOOM themes
and modus themes. You can set this in the technicolor-colors
list:
(setq technicolor-colors '(foreground))
The theme’s above have the following accessors we can use:
- Doom themes
doom-color
- Prot themes
*-themes-get-color-value
The DOOM themes use fg
for the foreground color, while Prot uses fg-main
, so we
map our “universal” palette name foreground
to these symbols in their
configurations.
(setq technicolor-themes '(("^doom-.*" doom-color '((foreground . fg)))
("^modus-.*" modus-themes-get-color-value
'((foreground . fg-main)))
...))
You can now access the current foreground color with (technicolor-get-color 'foreground)
provided your theme matches one of the above. Note we have
reproduced a subset of the default config provided.
That configuration will match all doom themes and all modus themes; you can set per-theme rules on color mappings from the universal palette by refining the regex:
' ...
("^modus-operandi" modus-themes-get-color-value '((mappings . here)))
(("^modus-vivendi" modus-themes-get-color-value '((different . mappings)))
...)
Extend the value of technicolor-colors
to any colors that you’d like to
use. If you give appropriate mappings for each group of themes, technicolor will
find them.
Note that if all of your themes provide the same symbol for a certain color, as
is common for generic colors like “red”, “blue”, etc, you don’t need to specify
the mapping from the universal palette (but they should still be in technicolor-colors
).
technicolor depends on a theme’s accessor to retrieve colors. An accessor for a
color should take in a color symbol and return the hexadecimal color that the
theme defines for that color, or nil
or unspecified
if no such color exists in
the palette. DOOM themes and Prot’s themes ship with their own accessors.
If the theme you want to include does include one, you will have to write
your own. With varying degrees of munging, this is possible (e.g. the
catppuccin color accessor defined in technicolor.el
).
Via straight
:
(straight-use-package
'(technicolor :type git :host github :repo "aatmunbaxi/technicolor"))
or for DOOM emacs users in your packages.el
:
(package! technicolor :recipe (:host github :repo "aatmunbaxi/technicolor"))
If your package manager does not support git recipes and you use use-package
, you can clone the repo and place the following in your configuration:
(use-package technicolor
:load-path "path/to/cloned/technicolor")
along with any use-package
configuration.
technicolor can also perform basic manipulation of colors, using the same ethos
of accessing the colors via technicolor-get-color
. They are listed below.
Essentially, they wrap the color
library.
technicolor-darken
technicolor-lighten
technicolor-complement
technicolor-gradient
technicolor-saturate
technicolor-desaturate
technicolor-blend