Changing your workflow color palette can be useful in myriad situations. In my case, as a self-describing nomadic programmer I tend to move a lot. There is probably some deep-seated reasoning, but the change in work setting seems to help me reset and focus. Unfortunately, this means constant changes in light exposure and ambiance making it difficult to commit to a light or dark theme because they tend to be unusable in the wrong setting.

Constant switching between color palette themes often requires manually updating configuration files. This becomes increasingly cumbersome as the number of managed applications increases. In my daily driver environment this means a WM, terminal, application launcher, desktop notification system, etc.

To facilitate the management of system-wide color palette themeing I use a simple home-grown script called dye, which is a part of my scripts repository. At a very high level, this script atomically modifies a collection of static application configuration files with configurable color palettes. It relies on regex replacements so it can support any component with a static text-based configuration (ie. … like everything).

Usage

The script usage is very simple, containing just 5 commands. To begin, we call with help to display the script usage.

hamersaw@ragnarok:~$ dye help
USAGE: dye COMMAND
COMMAND:
    apply <theme>   update application(s) with the specified theme
    help            display this help menu
    list            display registered theme(s)
    validate        ensure correctness of configuration
    version         display the applications version

Using the list command we can see all of the available color palette theme configurations. These are defined using theme configuration (explored further below).

hamersaw@ragnarok:~$ dye list
altierforest.dark
altierforest.light
eighties.dark
eighties.light
mocha.dark
mocha.light
solarized.dark
solarized.light

We can use validate to “dry run” the theme application. This helps to ensure that updating the theme will not corrupt a configuration file.

hamersaw@ragnarok:~$ dye validate mocha.dark

And finally, the apply command modifies static application configuration files with the update theme color palette.

hamersaw@ragnarok:~$ dye apply mocha.dark

Configuration

Configuration is housed in two specific file types, namely themes and applications. Both of these types are true shell scripts that are sourced during dye execution.

Theme configuration is performed by initializing an associative array of colors. The keys are color names and values are a hex code. A sample for the mocha dark theme is provided below:

declare -A colors

colors[background]="f5eeeb"
colors[foreground]="645240"

colors[normal_black]="3b3228"
colors[normal_red]="cb6077"
colors[normal_green]="beb55b"
colors[normal_yellow]="f4bc87"
colors[normal_blue]="8ab3b5"
colors[normal_magenta]="a89bb9"
colors[normal_cyan]="7bbda4"
colors[normal_white]="d0c8c6"

colors[bright_black]="7e705a"
colors[bright_red]="cb6077"
colors[bright_green]="beb55b"
colors[bright_yellow]="f4bc87"
colors[bright_blue]="8ab3b5"
colors[bright_magenta]="a89bb9"
colors[bright_cyan]="7bbda4"
colors[bright_white]="f5eeeb"

An application configuration file requires initializing two separate variables. The config variable defines the path of the applications static configuration file and the updates associative array is keyed on a regular expression and each value is the color name which should be applied. The regular expression will replace the string “DYECOLOR” with the hex code of the corresponding theme color. A sample application configuration for alacritty is provided below:

#!/bin/bash

config=".config/alacritty/alacritty.yml"

declare -A updates
updates["background: '0xDYECOLOR' # dye enable"]="background"
updates["foreground: '0xDYECOLOR' # dye enable"]="foreground"

updates["black:   '0xDYECOLOR' # dye normal"]="normal_black"
updates["red:     '0xDYECOLOR' # dye normal"]="normal_red"
updates["green:   '0xDYECOLOR' # dye normal"]="normal_green"
updates["yellow:  '0xDYECOLOR' # dye normal"]="normal_yellow"
updates["blue:    '0xDYECOLOR' # dye normal"]="normal_blue"
updates["magenta: '0xDYECOLOR' # dye normal"]="normal_magenta"
updates["white:   '0xDYECOLOR' # dye normal"]="normal_white"

updates["black:   '0xDYECOLOR' # dye bright"]="bright_black"
updates["red:     '0xDYECOLOR' # dye bright"]="bright_red"
updates["green:   '0xDYECOLOR' # dye bright"]="bright_green"
updates["yellow:  '0xDYECOLOR' # dye bright"]="bright_yellow"
updates["blue:    '0xDYECOLOR' # dye bright"]="bright_blue"
updates["magenta: '0xDYECOLOR' # dye bright"]="bright_magenta"
updates["white:   '0xDYECOLOR' # dye bright"]="bright_white"

This post is part 4 / 5 of the Script Series:

  1. Introduction
  2. A Script for Managing Dotfiles
  3. Due: A Kanban TODO List Script
  4. Scripting Your UI Color-Palette
  5. Password Management with Stash

9 day(s) offloaded in the 100DaysToOffload challenge.