Share one theme color resolver across consumers
Five scripts each hand-rolled colors.toml parsing plus their own alias/fallback cascade, and the tables had drifted: theme-osc grew a divergent color8/color9 chain, tmux and gnome carried private mode detection, and the preview tool duplicated the lot. The differences never mattered for shipped themes but were a standing bug factory for sparse user themes. omarchy-theme-color is now the single resolver. Its cascade is a verbatim port of the canonical theme-set-templates logic (semantic keys, legacy colorN aliases, derived shades, selection/cursor derivation, mode precedence), exposed as --all, --raw, or single-key lookup with fallback. Generated output is byte-identical across all 21 shipped themes on every surface: 17 template files, OSC byte stream, tmux and gsettings command logs, and previews. Sparse legacy themes now resolve the same palette everywhere instead of five slightly different ones. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
03f7420d72
commit
3bd6e72211
@@ -84,40 +84,38 @@ resolve_colors_file() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
clean_toml_value() {
|
omarchy_tool() {
|
||||||
local value="$1"
|
local tool="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
value="${value#*[\"\']}"
|
if [[ -x $OMARCHY_PATH/bin/$tool ]]; then
|
||||||
value="${value%%[\"\']*}"
|
"$OMARCHY_PATH/bin/$tool" "$@"
|
||||||
printf '%s' "$value"
|
else
|
||||||
|
"$tool" "$@"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
load_colors() {
|
load_colors() {
|
||||||
local colors_file="$1"
|
local colors_file="$1"
|
||||||
local key value
|
local key value
|
||||||
|
local -A resolved=()
|
||||||
|
|
||||||
while IFS='=' read -r key value; do
|
while IFS=$'\t' read -r key value; do
|
||||||
key="${key//[\"\' ]/}"
|
resolved[$key]="$value"
|
||||||
[[ $key && $key != \#* ]] || continue
|
done < <(omarchy_tool omarchy-theme-color --file "$colors_file" --all)
|
||||||
value=$(clean_toml_value "$value")
|
|
||||||
COLORS[$key]="$value"
|
|
||||||
done <"$colors_file"
|
|
||||||
|
|
||||||
# Legacy semantic names win when present so older themes keep their intended
|
# Preview the palette the theme itself defines, at canonically resolved values.
|
||||||
# primary text/background colors even if they also had dimmer fg/bg slots.
|
while IFS=$'\t' read -r key value; do
|
||||||
[[ ${COLORS[background]} ]] && COLORS[bg]="${COLORS[background]}"
|
COLORS[$key]="${resolved[$key]:-}"
|
||||||
[[ ${COLORS[foreground]} ]] && COLORS[fg]="${COLORS[foreground]}"
|
done < <(omarchy_tool omarchy-theme-color --file "$colors_file" --raw)
|
||||||
[[ ${COLORS[bg]} ]] || COLORS[bg]="${COLORS[color0]}"
|
|
||||||
[[ ${COLORS[fg]} ]] || COLORS[fg]="${COLORS[color7]}"
|
|
||||||
[[ ${COLORS[light_fg]} ]] || COLORS[light_fg]="${COLORS[color7]:-${COLORS[fg]}}"
|
|
||||||
[[ ${COLORS[bright_fg]} ]] || COLORS[bright_fg]="${COLORS[color15]:-${COLORS[fg]}}"
|
|
||||||
[[ ${COLORS[selection_background]} ]] || COLORS[selection_background]="${COLORS[selection]}"
|
|
||||||
[[ ${COLORS[selection_foreground]} ]] || COLORS[selection_foreground]="${COLORS[bright_fg]}"
|
|
||||||
|
|
||||||
if hex_valid "${COLORS[bg]}"; then
|
# Plus the core slots every theme resolves, so sparse and legacy themes
|
||||||
[[ ${COLORS[dark_bg]} ]] || COLORS[dark_bg]=$(mix_hex "${COLORS[bg]}" "#000000" 1 4)
|
# still render a complete preview.
|
||||||
[[ ${COLORS[darker_bg]} ]] || COLORS[darker_bg]=$(mix_hex "${COLORS[bg]}" "#000000" 1 2)
|
for key in mode bg fg light_fg bright_fg selection_background selection_foreground dark_bg darker_bg; do
|
||||||
fi
|
[[ -n ${resolved[$key]:-} ]] && COLORS[$key]="${resolved[$key]}"
|
||||||
|
done
|
||||||
|
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
hex_parts() {
|
hex_parts() {
|
||||||
@@ -188,11 +186,7 @@ apply_terminal_osc() {
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
if [[ -x $OMARCHY_PATH/bin/omarchy-theme-osc ]]; then
|
omarchy_tool omarchy-theme-osc "$colors_file" || true
|
||||||
"$OMARCHY_PATH/bin/omarchy-theme-osc" "$colors_file" || true
|
|
||||||
else
|
|
||||||
omarchy-theme-osc "$colors_file" || true
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
swatch() {
|
swatch() {
|
||||||
@@ -415,15 +409,7 @@ fi
|
|||||||
|
|
||||||
load_colors "$colors_file"
|
load_colors "$colors_file"
|
||||||
|
|
||||||
mode="${COLORS[mode]}"
|
mode="${COLORS[mode]:-dark}"
|
||||||
if [[ -z $mode && ${COLORS[bg]} =~ ^#[0-9A-Fa-f]{6}$ ]]; then
|
|
||||||
if (( $(luma_sum "${COLORS[bg]}") > 1275000 )); then
|
|
||||||
mode="light"
|
|
||||||
else
|
|
||||||
mode="dark"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
[[ -n $mode ]] || mode="dark"
|
|
||||||
|
|
||||||
theme_label="$THEME_REF"
|
theme_label="$THEME_REF"
|
||||||
if [[ -z $theme_label ]]; then
|
if [[ -z $theme_label ]]; then
|
||||||
|
|||||||
Executable
+270
@@ -0,0 +1,270 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# omarchy:summary=Resolve semantic colors from an Omarchy theme colors.toml
|
||||||
|
# omarchy:args=[--file <colors.toml>] (--all | --raw | <key> [fallback])
|
||||||
|
# omarchy:hidden=true
|
||||||
|
|
||||||
|
# Shared colors.toml parser/resolver. The alias/fallback cascade mirrors what
|
||||||
|
# omarchy-theme-set-templates bakes into the generated configs at theme-set
|
||||||
|
# time, so every consumer (templates, OSC sequences, tmux, GNOME, previews)
|
||||||
|
# resolves the exact same palette.
|
||||||
|
#
|
||||||
|
# --all print every resolved key<TAB>value pair (sorted by key)
|
||||||
|
# --raw print only the key<TAB>value pairs defined in the file
|
||||||
|
# <key> [fallback] print one resolved value; the fallback is tried as
|
||||||
|
# another palette key first, then used verbatim
|
||||||
|
#
|
||||||
|
# Theme mode precedence: `mode` key, legacy `theme_type` key, a light.mode
|
||||||
|
# file beside the colors.toml, background luminance auto-detect, dark.
|
||||||
|
|
||||||
|
COLORS_FILE="$HOME/.local/state/omarchy/current/theme/colors.toml"
|
||||||
|
OUTPUT=""
|
||||||
|
QUERY_KEY=""
|
||||||
|
QUERY_FALLBACK=""
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: omarchy-theme-color [--file <colors.toml>] (--all | --raw | <key> [fallback])"
|
||||||
|
}
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--file)
|
||||||
|
COLORS_FILE="${2:-}"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--all)
|
||||||
|
OUTPUT="all"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--raw)
|
||||||
|
OUTPUT="raw"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-h | --help)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if [[ -z $QUERY_KEY ]]; then
|
||||||
|
QUERY_KEY="$1"
|
||||||
|
elif [[ -z $QUERY_FALLBACK ]]; then
|
||||||
|
QUERY_FALLBACK="$1"
|
||||||
|
else
|
||||||
|
usage >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z $OUTPUT && -z $QUERY_KEY ]] || [[ -n $OUTPUT && -n $QUERY_KEY ]]; then
|
||||||
|
usage >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
COLORS_DIR=$(dirname "$COLORS_FILE")
|
||||||
|
|
||||||
|
declare -A THEME_COLORS
|
||||||
|
|
||||||
|
# Mix two hex colors. Amount may be a fraction (0.30) or percentage (30%).
|
||||||
|
mix_color() {
|
||||||
|
local start="${1#\#}"
|
||||||
|
local end="${2#\#}"
|
||||||
|
local amount="$3"
|
||||||
|
|
||||||
|
awk -v start="$start" -v end="$end" -v amount="$amount" '
|
||||||
|
function hex_value(char) {
|
||||||
|
return index("0123456789abcdef", tolower(char)) - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function hex_pair_to_int(hex, idx) {
|
||||||
|
return hex_value(substr(hex, idx, 1)) * 16 + hex_value(substr(hex, idx + 1, 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
if (amount ~ /%$/) {
|
||||||
|
sub(/%$/, "", amount)
|
||||||
|
amount = amount / 100
|
||||||
|
} else {
|
||||||
|
amount += 0
|
||||||
|
if (amount > 1) amount = amount / 100
|
||||||
|
}
|
||||||
|
|
||||||
|
if (amount < 0) amount = 0
|
||||||
|
if (amount > 1) amount = 1
|
||||||
|
|
||||||
|
start_r = hex_pair_to_int(start, 1)
|
||||||
|
start_g = hex_pair_to_int(start, 3)
|
||||||
|
start_b = hex_pair_to_int(start, 5)
|
||||||
|
end_r = hex_pair_to_int(end, 1)
|
||||||
|
end_g = hex_pair_to_int(end, 3)
|
||||||
|
end_b = hex_pair_to_int(end, 5)
|
||||||
|
|
||||||
|
red = int(start_r * (1 - amount) + end_r * amount + 0.5)
|
||||||
|
green = int(start_g * (1 - amount) + end_g * amount + 0.5)
|
||||||
|
blue = int(start_b * (1 - amount) + end_b * amount + 0.5)
|
||||||
|
|
||||||
|
printf "#%02x%02x%02x\n", red, green, blue
|
||||||
|
}
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
|
alias_theme_color() {
|
||||||
|
local key="$1"
|
||||||
|
local fallback="$2"
|
||||||
|
|
||||||
|
[[ ${THEME_COLORS[$key]} ]] || THEME_COLORS[$key]="${THEME_COLORS[$fallback]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve_theme_mode() {
|
||||||
|
local bg_hex lum
|
||||||
|
|
||||||
|
[[ ${THEME_COLORS[mode]} ]] || THEME_COLORS[mode]="${THEME_COLORS[theme_type]}"
|
||||||
|
[[ ${THEME_COLORS[mode]} ]] && return
|
||||||
|
|
||||||
|
if [[ -f $COLORS_DIR/light.mode ]]; then
|
||||||
|
THEME_COLORS[mode]="light"
|
||||||
|
elif [[ ${THEME_COLORS[bg]} =~ ^#[0-9A-Fa-f]{6}$ ]]; then
|
||||||
|
bg_hex="${THEME_COLORS[bg]#\#}"
|
||||||
|
lum=$(( $(printf "%d" "0x${bg_hex:0:2}") + $(printf "%d" "0x${bg_hex:2:2}") + $(printf "%d" "0x${bg_hex:4:2}") ))
|
||||||
|
(( lum > 382 )) && THEME_COLORS[mode]="light" || THEME_COLORS[mode]="dark"
|
||||||
|
else
|
||||||
|
THEME_COLORS[mode]="dark"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_colors_file() {
|
||||||
|
local key value
|
||||||
|
|
||||||
|
[[ -f $COLORS_FILE ]] || return 0
|
||||||
|
|
||||||
|
while IFS='=' read -r key value; do
|
||||||
|
key="${key//[\"\' ]/}" # strip quotes and spaces from key
|
||||||
|
[[ $key && $key != \#* ]] || continue # skip empty lines and comments
|
||||||
|
|
||||||
|
if [[ $value == *[\"\']* ]]; then
|
||||||
|
value="${value#*[\"\']}"
|
||||||
|
value="${value%%[\"\']*}" # extract value between quotes (ignores inline comments)
|
||||||
|
else
|
||||||
|
value="${value#"${value%%[![:space:]]*}"}"
|
||||||
|
value="${value%"${value##*[![:space:]]}"}" # trim unquoted values
|
||||||
|
fi
|
||||||
|
|
||||||
|
THEME_COLORS[$key]="$value"
|
||||||
|
[[ $OUTPUT == "raw" ]] && printf '%s\t%s\n' "$key" "$value"
|
||||||
|
done <"$COLORS_FILE"
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve_theme_colors() {
|
||||||
|
local key
|
||||||
|
|
||||||
|
# Canonical palette keys are bg/fg. Preserve older themes that still define
|
||||||
|
# background/foreground by treating those semantic values as the source of
|
||||||
|
# truth, then expose the old names as aliases for legacy consumers.
|
||||||
|
[[ ${THEME_COLORS[background]} ]] && THEME_COLORS[bg]="${THEME_COLORS[background]}"
|
||||||
|
[[ ${THEME_COLORS[foreground]} ]] && THEME_COLORS[fg]="${THEME_COLORS[foreground]}"
|
||||||
|
[[ ${THEME_COLORS[bg]} ]] || THEME_COLORS[bg]="${THEME_COLORS[color0]}"
|
||||||
|
[[ ${THEME_COLORS[fg]} ]] || THEME_COLORS[fg]="${THEME_COLORS[color7]}"
|
||||||
|
[[ ${THEME_COLORS[bg]} ]] && THEME_COLORS[background]="${THEME_COLORS[bg]}"
|
||||||
|
[[ ${THEME_COLORS[fg]} ]] && THEME_COLORS[foreground]="${THEME_COLORS[fg]}"
|
||||||
|
[[ ${THEME_COLORS[bg]} ]] && THEME_COLORS[color0]="${THEME_COLORS[bg]}"
|
||||||
|
[[ ${THEME_COLORS[fg]} ]] && THEME_COLORS[color7]="${THEME_COLORS[fg]}"
|
||||||
|
|
||||||
|
# Legacy compatibility: map ANSI color0..color15 to semantic names.
|
||||||
|
declare -A legacy_alias=(
|
||||||
|
[red]=color1
|
||||||
|
[green]=color2
|
||||||
|
[yellow]=color3
|
||||||
|
[blue]=color4
|
||||||
|
[magenta]=color5
|
||||||
|
[cyan]=color6
|
||||||
|
[bright_red]=color9
|
||||||
|
[bright_green]=color10
|
||||||
|
[bright_yellow]=color11
|
||||||
|
[bright_blue]=color12
|
||||||
|
[bright_magenta]=color13
|
||||||
|
[bright_cyan]=color14
|
||||||
|
)
|
||||||
|
for key in "${!legacy_alias[@]}"; do
|
||||||
|
alias_theme_color "$key" "${legacy_alias[$key]}"
|
||||||
|
done
|
||||||
|
alias_theme_color magenta purple
|
||||||
|
alias_theme_color bright_magenta bright_purple
|
||||||
|
|
||||||
|
[[ ${THEME_COLORS[light_fg]} ]] || THEME_COLORS[light_fg]="${THEME_COLORS[color7]:-${THEME_COLORS[fg]}}"
|
||||||
|
[[ ${THEME_COLORS[bright_fg]} ]] || THEME_COLORS[bright_fg]="${THEME_COLORS[color15]:-${THEME_COLORS[fg]}}"
|
||||||
|
THEME_COLORS[cursor]="${THEME_COLORS[bright_fg]}"
|
||||||
|
[[ ${THEME_COLORS[lighter_bg]} ]] || THEME_COLORS[lighter_bg]="${THEME_COLORS[color0]:-${THEME_COLORS[bg]}}"
|
||||||
|
[[ ${THEME_COLORS[dark_fg]} ]] || THEME_COLORS[dark_fg]="${THEME_COLORS[color8]:-${THEME_COLORS[fg]}}"
|
||||||
|
[[ ${THEME_COLORS[muted]} ]] || THEME_COLORS[muted]="${THEME_COLORS[color8]:-${THEME_COLORS[dark_fg]}}"
|
||||||
|
[[ ${THEME_COLORS[selection]} ]] || THEME_COLORS[selection]="${THEME_COLORS[selection_background]:-${THEME_COLORS[color8]:-${THEME_COLORS[color0]:-${THEME_COLORS[bg]}}}}"
|
||||||
|
[[ ${THEME_COLORS[selection_background]} ]] || THEME_COLORS[selection_background]="${THEME_COLORS[selection]}"
|
||||||
|
[[ ${THEME_COLORS[selection_foreground]} ]] || THEME_COLORS[selection_foreground]="${THEME_COLORS[bright_fg]}"
|
||||||
|
[[ ${THEME_COLORS[orange]} ]] || THEME_COLORS[orange]="${THEME_COLORS[yellow]}"
|
||||||
|
[[ ${THEME_COLORS[brown]} ]] || THEME_COLORS[brown]=$(mix_color "${THEME_COLORS[orange]}" "#000000" 50%)
|
||||||
|
|
||||||
|
# Auto-derive shades from base accents when not defined and not aliased from colorN
|
||||||
|
[[ ${THEME_COLORS[dark_bg]} ]] || THEME_COLORS[dark_bg]=$(mix_color "${THEME_COLORS[bg]}" "#000000" 25%)
|
||||||
|
[[ ${THEME_COLORS[darker_bg]} ]] || THEME_COLORS[darker_bg]=$(mix_color "${THEME_COLORS[bg]}" "#000000" 50%)
|
||||||
|
[[ ${THEME_COLORS[bright_red]} ]] || THEME_COLORS[bright_red]=$(mix_color "${THEME_COLORS[red]}" "#ffffff" 20%)
|
||||||
|
[[ ${THEME_COLORS[bright_yellow]} ]] || THEME_COLORS[bright_yellow]=$(mix_color "${THEME_COLORS[yellow]}" "#ffffff" 20%)
|
||||||
|
[[ ${THEME_COLORS[bright_green]} ]] || THEME_COLORS[bright_green]=$(mix_color "${THEME_COLORS[green]}" "#ffffff" 20%)
|
||||||
|
[[ ${THEME_COLORS[bright_cyan]} ]] || THEME_COLORS[bright_cyan]=$(mix_color "${THEME_COLORS[cyan]}" "#ffffff" 20%)
|
||||||
|
[[ ${THEME_COLORS[bright_blue]} ]] || THEME_COLORS[bright_blue]=$(mix_color "${THEME_COLORS[blue]}" "#ffffff" 20%)
|
||||||
|
[[ ${THEME_COLORS[bright_magenta]} ]] || THEME_COLORS[bright_magenta]=$(mix_color "${THEME_COLORS[magenta]}" "#ffffff" 20%)
|
||||||
|
alias_theme_color purple magenta
|
||||||
|
alias_theme_color bright_purple bright_magenta
|
||||||
|
|
||||||
|
# Keep semantic themes compatible with consumers that still reference the
|
||||||
|
# legacy ANSI names directly.
|
||||||
|
declare -A ansi_alias=(
|
||||||
|
[color0]=bg
|
||||||
|
[color1]=red
|
||||||
|
[color2]=green
|
||||||
|
[color3]=yellow
|
||||||
|
[color4]=blue
|
||||||
|
[color5]=magenta
|
||||||
|
[color6]=cyan
|
||||||
|
[color7]=fg
|
||||||
|
[color8]=muted
|
||||||
|
[color9]=bright_red
|
||||||
|
[color10]=bright_green
|
||||||
|
[color11]=bright_yellow
|
||||||
|
[color12]=bright_blue
|
||||||
|
[color13]=bright_magenta
|
||||||
|
[color14]=bright_cyan
|
||||||
|
[color15]=bright_fg
|
||||||
|
)
|
||||||
|
for key in "${!ansi_alias[@]}"; do
|
||||||
|
alias_theme_color "$key" "${ansi_alias[$key]}"
|
||||||
|
done
|
||||||
|
|
||||||
|
resolve_theme_mode
|
||||||
|
THEME_COLORS[theme_type]="${THEME_COLORS[mode]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_colors_file
|
||||||
|
|
||||||
|
if [[ $OUTPUT == "raw" ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
resolve_theme_colors
|
||||||
|
|
||||||
|
if [[ $OUTPUT == "all" ]]; then
|
||||||
|
while IFS= read -r key; do
|
||||||
|
printf '%s\t%s\n' "$key" "${THEME_COLORS[$key]}"
|
||||||
|
done < <(printf '%s\n' "${!THEME_COLORS[@]}" | LC_ALL=C sort)
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
value="${THEME_COLORS[$QUERY_KEY]:-}"
|
||||||
|
if [[ -z $value && -n $QUERY_FALLBACK ]]; then
|
||||||
|
value="${THEME_COLORS[$QUERY_FALLBACK]:-$QUERY_FALLBACK}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
[[ -n $value ]] || exit 1
|
||||||
|
printf '%s\n' "$value"
|
||||||
+19
-76
@@ -7,84 +7,27 @@ theme="${1:-$HOME/.local/state/omarchy/current/theme/colors.toml}"
|
|||||||
|
|
||||||
[[ -f $theme ]] || exit 0
|
[[ -f $theme ]] || exit 0
|
||||||
|
|
||||||
awk -F= '
|
declare -A COLORS
|
||||||
function clean(value) {
|
|
||||||
gsub(/^[[:space:]]+|[[:space:]]+$/, "", value)
|
|
||||||
if (value ~ /^"/) {
|
|
||||||
sub(/^"/, "", value)
|
|
||||||
sub(/".*$/, "", value)
|
|
||||||
}
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
function alias_color(target, source) {
|
while IFS=$'\t' read -r key value; do
|
||||||
if (colors[target] == "" && colors[source] != "") colors[target] = colors[source]
|
COLORS[$key]="$value"
|
||||||
}
|
done < <(omarchy-theme-color --file "$theme" --all)
|
||||||
|
|
||||||
function emit_color(color_index, key) {
|
emit_osc() {
|
||||||
if (colors[key] != "") printf "\033]4;%d;%s\007", color_index, colors[key]
|
local code="$1"
|
||||||
}
|
local key="$2"
|
||||||
|
|
||||||
{
|
[[ -n ${COLORS[$key]:-} ]] || return 0
|
||||||
key = $1
|
printf '\033]%s;%s\007' "$code" "${COLORS[$key]}"
|
||||||
gsub(/^[[:space:]]+|[[:space:]]+$/, "", key)
|
}
|
||||||
value = clean($2)
|
|
||||||
colors[key] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
END {
|
emit_osc 10 foreground
|
||||||
if (colors["background"] != "") colors["bg"] = colors["background"]
|
emit_osc 11 background
|
||||||
if (colors["foreground"] != "") colors["fg"] = colors["foreground"]
|
emit_osc 12 cursor
|
||||||
if (colors["bg"] != "") colors["background"] = colors["bg"]
|
emit_osc 17 selection_background
|
||||||
if (colors["fg"] != "") colors["foreground"] = colors["fg"]
|
emit_osc 19 selection_foreground
|
||||||
if (colors["bg"] != "") colors["color0"] = colors["bg"]
|
|
||||||
if (colors["fg"] != "") colors["color7"] = colors["fg"]
|
|
||||||
|
|
||||||
alias_color("color0", "bg")
|
for i in {0..15}; do
|
||||||
alias_color("color0", "background")
|
[[ -n ${COLORS[color$i]:-} ]] || continue
|
||||||
alias_color("color1", "red")
|
printf '\033]4;%d;%s\007' "$i" "${COLORS[color$i]}"
|
||||||
alias_color("color2", "green")
|
done
|
||||||
alias_color("color3", "yellow")
|
|
||||||
alias_color("color4", "blue")
|
|
||||||
alias_color("color5", "magenta")
|
|
||||||
alias_color("color5", "purple")
|
|
||||||
alias_color("color6", "cyan")
|
|
||||||
alias_color("color7", "fg")
|
|
||||||
alias_color("color7", "foreground")
|
|
||||||
alias_color("color8", "muted")
|
|
||||||
alias_color("color8", "dark_fg")
|
|
||||||
alias_color("color8", "foreground")
|
|
||||||
alias_color("color9", "bright_red")
|
|
||||||
alias_color("color9", "red")
|
|
||||||
alias_color("color10", "bright_green")
|
|
||||||
alias_color("color10", "green")
|
|
||||||
alias_color("color11", "bright_yellow")
|
|
||||||
alias_color("color11", "yellow")
|
|
||||||
alias_color("color12", "bright_blue")
|
|
||||||
alias_color("color12", "blue")
|
|
||||||
alias_color("color13", "bright_magenta")
|
|
||||||
alias_color("color13", "bright_purple")
|
|
||||||
alias_color("color13", "magenta")
|
|
||||||
alias_color("color13", "purple")
|
|
||||||
alias_color("color14", "bright_cyan")
|
|
||||||
alias_color("color14", "cyan")
|
|
||||||
alias_color("color15", "bright_fg")
|
|
||||||
alias_color("color15", "foreground")
|
|
||||||
alias_color("light_fg", "color7")
|
|
||||||
alias_color("light_fg", "fg")
|
|
||||||
alias_color("bright_fg", "color15")
|
|
||||||
alias_color("bright_fg", "fg")
|
|
||||||
if (colors["bright_fg"] != "") colors["cursor"] = colors["bright_fg"]
|
|
||||||
|
|
||||||
if (colors["selection_background"] == "" && colors["selection"] != "") colors["selection_background"] = colors["selection"]
|
|
||||||
if (colors["selection_foreground"] == "") colors["selection_foreground"] = colors["bright_fg"]
|
|
||||||
|
|
||||||
if (colors["foreground"] != "") printf "\033]10;%s\007", colors["foreground"]
|
|
||||||
if (colors["background"] != "") printf "\033]11;%s\007", colors["background"]
|
|
||||||
if (colors["cursor"] != "") printf "\033]12;%s\007", colors["cursor"]
|
|
||||||
if (colors["selection_background"] != "") printf "\033]17;%s\007", colors["selection_background"]
|
|
||||||
if (colors["selection_foreground"] != "") printf "\033]19;%s\007", colors["selection_foreground"]
|
|
||||||
|
|
||||||
for (i = 0; i <= 15; i++) emit_color(i, "color" i)
|
|
||||||
}
|
|
||||||
' "$theme"
|
|
||||||
|
|||||||
@@ -13,33 +13,9 @@ fi
|
|||||||
THEME_DIR=$HOME/.local/state/omarchy/current/theme
|
THEME_DIR=$HOME/.local/state/omarchy/current/theme
|
||||||
COLORS_FILE="$THEME_DIR/colors.toml"
|
COLORS_FILE="$THEME_DIR/colors.toml"
|
||||||
|
|
||||||
# In-tree light themes now declare `mode = "light"` in colors.toml instead of
|
# omarchy-theme-color resolves mode from colors.toml (`mode = "light"`), a
|
||||||
# shipping a separate light.mode marker. Keep light.mode as a user-theme fallback.
|
# legacy light.mode marker beside it, or background luminance for user themes.
|
||||||
theme_mode() {
|
mode=$(omarchy-theme-color --file "$COLORS_FILE" mode)
|
||||||
[[ -f $COLORS_FILE ]] || return
|
|
||||||
|
|
||||||
awk -F= '
|
|
||||||
{
|
|
||||||
field = $1
|
|
||||||
gsub(/^[[:space:]]+|[[:space:]]+$/, "", field)
|
|
||||||
if (field == "mode") {
|
|
||||||
value = $2
|
|
||||||
gsub(/^[[:space:]]+|[[:space:]]+$/, "", value)
|
|
||||||
if (value ~ /^"/) {
|
|
||||||
sub(/^"/, "", value)
|
|
||||||
sub(/".*$/, "", value)
|
|
||||||
}
|
|
||||||
print value
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
' "$COLORS_FILE"
|
|
||||||
}
|
|
||||||
|
|
||||||
mode=$(theme_mode)
|
|
||||||
if [[ -z $mode && -f $THEME_DIR/light.mode ]]; then
|
|
||||||
mode="light"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $mode == "light" ]]; then
|
if [[ $mode == "light" ]]; then
|
||||||
gsettings set org.gnome.desktop.interface color-scheme "prefer-light"
|
gsettings set org.gnome.desktop.interface color-scheme "prefer-light"
|
||||||
|
|||||||
@@ -367,30 +367,6 @@ apply_shell_section_overrides() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
alias_theme_color() {
|
|
||||||
local key="$1"
|
|
||||||
local fallback="$2"
|
|
||||||
|
|
||||||
[[ ${THEME_COLORS[$key]} ]] || THEME_COLORS[$key]="${THEME_COLORS[$fallback]}"
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve_theme_mode() {
|
|
||||||
local bg_hex lum
|
|
||||||
|
|
||||||
[[ ${THEME_COLORS[mode]} ]] || THEME_COLORS[mode]="${THEME_COLORS[theme_type]}"
|
|
||||||
[[ ${THEME_COLORS[mode]} ]] && return
|
|
||||||
|
|
||||||
if [[ -f $NEXT_THEME_DIR/light.mode ]]; then
|
|
||||||
THEME_COLORS[mode]="light"
|
|
||||||
elif [[ ${THEME_COLORS[bg]} =~ ^#[0-9A-Fa-f]{6}$ ]]; then
|
|
||||||
bg_hex="${THEME_COLORS[bg]#\#}"
|
|
||||||
lum=$(( $(printf "%d" "0x${bg_hex:0:2}") + $(printf "%d" "0x${bg_hex:2:2}") + $(printf "%d" "0x${bg_hex:4:2}") ))
|
|
||||||
(( lum > 382 )) && THEME_COLORS[mode]="light" || THEME_COLORS[mode]="dark"
|
|
||||||
else
|
|
||||||
THEME_COLORS[mode]="dark"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Only generate dynamic templates for themes with a colors.toml definition
|
# Only generate dynamic templates for themes with a colors.toml definition
|
||||||
if [[ -f $COLORS_FILE ]]; then
|
if [[ -f $COLORS_FILE ]]; then
|
||||||
sed_script=$(mktemp)
|
sed_script=$(mktemp)
|
||||||
@@ -398,103 +374,11 @@ if [[ -f $COLORS_FILE ]]; then
|
|||||||
shopt -s nullglob
|
shopt -s nullglob
|
||||||
template_files=("$USER_TEMPLATES_DIR"/*.tpl "$TEMPLATES_DIR"/*.tpl)
|
template_files=("$USER_TEMPLATES_DIR"/*.tpl "$TEMPLATES_DIR"/*.tpl)
|
||||||
|
|
||||||
while IFS='=' read -r key value; do
|
# Parsing and alias/fallback resolution (legacy colorN names, derived
|
||||||
key="${key//[\"\' ]/}" # strip quotes and spaces from key
|
# shades, mode/theme_type) is shared with every other colors.toml consumer.
|
||||||
[[ $key && $key != \#* ]] || continue # skip empty lines and comments
|
while IFS=$'\t' read -r key value; do
|
||||||
value="${value#*[\"\']}"
|
|
||||||
value="${value%%[\"\']*}" # extract value between quotes (ignores inline comments)
|
|
||||||
|
|
||||||
THEME_COLORS[$key]="$value"
|
THEME_COLORS[$key]="$value"
|
||||||
done <"$COLORS_FILE"
|
done < <(omarchy-theme-color --file "$COLORS_FILE" --all)
|
||||||
|
|
||||||
# Canonical palette keys are bg/fg. Preserve older themes that still define
|
|
||||||
# background/foreground by treating those semantic values as the source of
|
|
||||||
# truth, then expose the old names as template aliases for user templates.
|
|
||||||
[[ ${THEME_COLORS[background]} ]] && THEME_COLORS[bg]="${THEME_COLORS[background]}"
|
|
||||||
[[ ${THEME_COLORS[foreground]} ]] && THEME_COLORS[fg]="${THEME_COLORS[foreground]}"
|
|
||||||
[[ ${THEME_COLORS[bg]} ]] || THEME_COLORS[bg]="${THEME_COLORS[color0]}"
|
|
||||||
[[ ${THEME_COLORS[fg]} ]] || THEME_COLORS[fg]="${THEME_COLORS[color7]}"
|
|
||||||
[[ ${THEME_COLORS[bg]} ]] && THEME_COLORS[background]="${THEME_COLORS[bg]}"
|
|
||||||
[[ ${THEME_COLORS[fg]} ]] && THEME_COLORS[foreground]="${THEME_COLORS[fg]}"
|
|
||||||
[[ ${THEME_COLORS[bg]} ]] && THEME_COLORS[color0]="${THEME_COLORS[bg]}"
|
|
||||||
[[ ${THEME_COLORS[fg]} ]] && THEME_COLORS[color7]="${THEME_COLORS[fg]}"
|
|
||||||
|
|
||||||
# Legacy compatibility: map ANSI color0..color15 to semantic names.
|
|
||||||
declare -A legacy_alias=(
|
|
||||||
[red]=color1
|
|
||||||
[green]=color2
|
|
||||||
[yellow]=color3
|
|
||||||
[blue]=color4
|
|
||||||
[magenta]=color5
|
|
||||||
[cyan]=color6
|
|
||||||
[bright_red]=color9
|
|
||||||
[bright_green]=color10
|
|
||||||
[bright_yellow]=color11
|
|
||||||
[bright_blue]=color12
|
|
||||||
[bright_magenta]=color13
|
|
||||||
[bright_cyan]=color14
|
|
||||||
)
|
|
||||||
for key in "${!legacy_alias[@]}"; do
|
|
||||||
alias_theme_color "$key" "${legacy_alias[$key]}"
|
|
||||||
done
|
|
||||||
alias_theme_color magenta purple
|
|
||||||
alias_theme_color bright_magenta bright_purple
|
|
||||||
|
|
||||||
[[ ${THEME_COLORS[light_fg]} ]] || THEME_COLORS[light_fg]="${THEME_COLORS[color7]:-${THEME_COLORS[fg]}}"
|
|
||||||
[[ ${THEME_COLORS[bright_fg]} ]] || THEME_COLORS[bright_fg]="${THEME_COLORS[color15]:-${THEME_COLORS[fg]}}"
|
|
||||||
THEME_COLORS[cursor]="${THEME_COLORS[bright_fg]}"
|
|
||||||
[[ ${THEME_COLORS[lighter_bg]} ]] || THEME_COLORS[lighter_bg]="${THEME_COLORS[color0]:-${THEME_COLORS[bg]}}"
|
|
||||||
[[ ${THEME_COLORS[dark_fg]} ]] || THEME_COLORS[dark_fg]="${THEME_COLORS[color8]:-${THEME_COLORS[fg]}}"
|
|
||||||
[[ ${THEME_COLORS[muted]} ]] || THEME_COLORS[muted]="${THEME_COLORS[color8]:-${THEME_COLORS[dark_fg]}}"
|
|
||||||
[[ ${THEME_COLORS[selection]} ]] || THEME_COLORS[selection]="${THEME_COLORS[selection_background]:-${THEME_COLORS[color8]:-${THEME_COLORS[color0]:-${THEME_COLORS[bg]}}}}"
|
|
||||||
[[ ${THEME_COLORS[selection_background]} ]] || THEME_COLORS[selection_background]="${THEME_COLORS[selection]}"
|
|
||||||
[[ ${THEME_COLORS[selection_foreground]} ]] || THEME_COLORS[selection_foreground]="${THEME_COLORS[bright_fg]}"
|
|
||||||
[[ ${THEME_COLORS[orange]} ]] || THEME_COLORS[orange]="${THEME_COLORS[yellow]}"
|
|
||||||
[[ ${THEME_COLORS[brown]} ]] || THEME_COLORS[brown]=$(mix_color "${THEME_COLORS[orange]}" "#000000" 50%)
|
|
||||||
|
|
||||||
# Auto-derive shades from base accents when not defined and not aliased from colorN
|
|
||||||
[[ ${THEME_COLORS[dark_bg]} ]] || THEME_COLORS[dark_bg]=$(mix_color "${THEME_COLORS[bg]}" "#000000" 25%)
|
|
||||||
[[ ${THEME_COLORS[darker_bg]} ]] || THEME_COLORS[darker_bg]=$(mix_color "${THEME_COLORS[bg]}" "#000000" 50%)
|
|
||||||
[[ ${THEME_COLORS[bright_red]} ]] || THEME_COLORS[bright_red]=$(mix_color "${THEME_COLORS[red]}" "#ffffff" 20%)
|
|
||||||
[[ ${THEME_COLORS[bright_yellow]} ]] || THEME_COLORS[bright_yellow]=$(mix_color "${THEME_COLORS[yellow]}" "#ffffff" 20%)
|
|
||||||
[[ ${THEME_COLORS[bright_green]} ]] || THEME_COLORS[bright_green]=$(mix_color "${THEME_COLORS[green]}" "#ffffff" 20%)
|
|
||||||
[[ ${THEME_COLORS[bright_cyan]} ]] || THEME_COLORS[bright_cyan]=$(mix_color "${THEME_COLORS[cyan]}" "#ffffff" 20%)
|
|
||||||
[[ ${THEME_COLORS[bright_blue]} ]] || THEME_COLORS[bright_blue]=$(mix_color "${THEME_COLORS[blue]}" "#ffffff" 20%)
|
|
||||||
[[ ${THEME_COLORS[bright_magenta]} ]] || THEME_COLORS[bright_magenta]=$(mix_color "${THEME_COLORS[magenta]}" "#ffffff" 20%)
|
|
||||||
alias_theme_color purple magenta
|
|
||||||
alias_theme_color bright_purple bright_magenta
|
|
||||||
|
|
||||||
# Keep semantic themes compatible with user templates that still reference
|
|
||||||
# the legacy ANSI placeholders directly.
|
|
||||||
declare -A ansi_alias=(
|
|
||||||
[color0]=bg
|
|
||||||
[color1]=red
|
|
||||||
[color2]=green
|
|
||||||
[color3]=yellow
|
|
||||||
[color4]=blue
|
|
||||||
[color5]=magenta
|
|
||||||
[color6]=cyan
|
|
||||||
[color7]=fg
|
|
||||||
[color8]=muted
|
|
||||||
[color9]=bright_red
|
|
||||||
[color10]=bright_green
|
|
||||||
[color11]=bright_yellow
|
|
||||||
[color12]=bright_blue
|
|
||||||
[color13]=bright_magenta
|
|
||||||
[color14]=bright_cyan
|
|
||||||
[color15]=bright_fg
|
|
||||||
)
|
|
||||||
for key in "${!ansi_alias[@]}"; do
|
|
||||||
alias_theme_color "$key" "${ansi_alias[$key]}"
|
|
||||||
done
|
|
||||||
|
|
||||||
# Resolve theme mode (dark|light) with this precedence:
|
|
||||||
# 1. `mode` key in colors.toml
|
|
||||||
# 2. legacy `light.mode` file shipped beside the theme
|
|
||||||
# 3. background luminance auto-detect
|
|
||||||
# `theme_type` is kept as an alias so existing templates ({{ theme_type }}) keep working.
|
|
||||||
resolve_theme_mode
|
|
||||||
THEME_COLORS[theme_type]="${THEME_COLORS[mode]}"
|
|
||||||
|
|
||||||
for key in "${!THEME_COLORS[@]}"; do
|
for key in "${!THEME_COLORS[@]}"; do
|
||||||
add_template_value "$key" "${THEME_COLORS[$key]}"
|
add_template_value "$key" "${THEME_COLORS[$key]}"
|
||||||
|
|||||||
@@ -37,11 +37,10 @@ sync_theme_environment() {
|
|||||||
|
|
||||||
sync_colorfgbg() {
|
sync_colorfgbg() {
|
||||||
local colorfgbg="15;0"
|
local colorfgbg="15;0"
|
||||||
local mode
|
|
||||||
|
|
||||||
mode=$(theme_color mode)
|
# theme_color resolves mode from colors.toml, a legacy light.mode file, or
|
||||||
|
# background luminance, so a bare light check covers all theme styles.
|
||||||
if [[ $mode == "light" ]] || [[ -z $mode && -f $CURRENT_THEME_PATH/light.mode ]]; then
|
if [[ $(theme_color mode) == "light" ]]; then
|
||||||
colorfgbg="0;15"
|
colorfgbg="0;15"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -53,34 +52,7 @@ theme_osc_sequences() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
theme_color() {
|
theme_color() {
|
||||||
local key="$1"
|
omarchy-theme-color --file "$COLORS_TOML" "$@"
|
||||||
local fallback="${2:-}"
|
|
||||||
|
|
||||||
awk -F= -v key="$key" -v fallback="$fallback" '
|
|
||||||
function clean(raw) {
|
|
||||||
gsub(/^[[:space:]]+|[[:space:]]+$/, "", raw)
|
|
||||||
if (raw ~ /^"/) {
|
|
||||||
sub(/^"/, "", raw)
|
|
||||||
sub(/".*$/, "", raw)
|
|
||||||
}
|
|
||||||
return raw
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
field = $1
|
|
||||||
gsub(/^[[:space:]]+|[[:space:]]+$/, "", field)
|
|
||||||
if (field == key) {
|
|
||||||
print clean($2)
|
|
||||||
found = 1
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
if (fallback != "" && field == fallback) fallback_value = clean($2)
|
|
||||||
}
|
|
||||||
|
|
||||||
END {
|
|
||||||
if (!found && fallback_value != "") print fallback_value
|
|
||||||
}
|
|
||||||
' "$COLORS_TOML"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sync_tmux_window_style() {
|
sync_tmux_window_style() {
|
||||||
@@ -88,8 +60,8 @@ sync_tmux_window_style() {
|
|||||||
|
|
||||||
[[ -f $COLORS_TOML ]] || return
|
[[ -f $COLORS_TOML ]] || return
|
||||||
|
|
||||||
foreground=$(theme_color foreground fg)
|
foreground=$(theme_color foreground)
|
||||||
background=$(theme_color background bg)
|
background=$(theme_color background)
|
||||||
|
|
||||||
[[ -n $foreground && -n $background ]] || return
|
[[ -n $foreground && -n $background ]] || return
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user