diff --git a/bin/omarchy-dev-theme-preview b/bin/omarchy-dev-theme-preview index 324cd69d..3c6c14bc 100755 --- a/bin/omarchy-dev-theme-preview +++ b/bin/omarchy-dev-theme-preview @@ -84,40 +84,38 @@ resolve_colors_file() { fi } -clean_toml_value() { - local value="$1" +omarchy_tool() { + local tool="$1" + shift - value="${value#*[\"\']}" - value="${value%%[\"\']*}" - printf '%s' "$value" + if [[ -x $OMARCHY_PATH/bin/$tool ]]; then + "$OMARCHY_PATH/bin/$tool" "$@" + else + "$tool" "$@" + fi } load_colors() { local colors_file="$1" local key value + local -A resolved=() - while IFS='=' read -r key value; do - key="${key//[\"\' ]/}" - [[ $key && $key != \#* ]] || continue - value=$(clean_toml_value "$value") - COLORS[$key]="$value" - done <"$colors_file" + while IFS=$'\t' read -r key value; do + resolved[$key]="$value" + done < <(omarchy_tool omarchy-theme-color --file "$colors_file" --all) - # Legacy semantic names win when present so older themes keep their intended - # primary text/background colors even if they also had dimmer fg/bg slots. - [[ ${COLORS[background]} ]] && COLORS[bg]="${COLORS[background]}" - [[ ${COLORS[foreground]} ]] && COLORS[fg]="${COLORS[foreground]}" - [[ ${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]}" + # Preview the palette the theme itself defines, at canonically resolved values. + while IFS=$'\t' read -r key value; do + COLORS[$key]="${resolved[$key]:-}" + done < <(omarchy_tool omarchy-theme-color --file "$colors_file" --raw) - if hex_valid "${COLORS[bg]}"; then - [[ ${COLORS[dark_bg]} ]] || COLORS[dark_bg]=$(mix_hex "${COLORS[bg]}" "#000000" 1 4) - [[ ${COLORS[darker_bg]} ]] || COLORS[darker_bg]=$(mix_hex "${COLORS[bg]}" "#000000" 1 2) - fi + # Plus the core slots every theme resolves, so sparse and legacy themes + # still render a complete preview. + for key in mode bg fg light_fg bright_fg selection_background selection_foreground dark_bg darker_bg; do + [[ -n ${resolved[$key]:-} ]] && COLORS[$key]="${resolved[$key]}" + done + + return 0 } hex_parts() { @@ -188,11 +186,7 @@ apply_terminal_osc() { ;; esac - if [[ -x $OMARCHY_PATH/bin/omarchy-theme-osc ]]; then - "$OMARCHY_PATH/bin/omarchy-theme-osc" "$colors_file" || true - else - omarchy-theme-osc "$colors_file" || true - fi + omarchy_tool omarchy-theme-osc "$colors_file" || true } swatch() { @@ -415,15 +409,7 @@ fi load_colors "$colors_file" -mode="${COLORS[mode]}" -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" +mode="${COLORS[mode]:-dark}" theme_label="$THEME_REF" if [[ -z $theme_label ]]; then diff --git a/bin/omarchy-theme-color b/bin/omarchy-theme-color new file mode 100755 index 00000000..fdc08e0c --- /dev/null +++ b/bin/omarchy-theme-color @@ -0,0 +1,270 @@ +#!/bin/bash + +# omarchy:summary=Resolve semantic colors from an Omarchy theme colors.toml +# omarchy:args=[--file ] (--all | --raw | [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 keyvalue pair (sorted by key) +# --raw print only the keyvalue pairs defined in the file +# [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 ] (--all | --raw | [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" diff --git a/bin/omarchy-theme-osc b/bin/omarchy-theme-osc index 05156885..04fe6c39 100755 --- a/bin/omarchy-theme-osc +++ b/bin/omarchy-theme-osc @@ -7,84 +7,27 @@ theme="${1:-$HOME/.local/state/omarchy/current/theme/colors.toml}" [[ -f $theme ]] || exit 0 -awk -F= ' - function clean(value) { - gsub(/^[[:space:]]+|[[:space:]]+$/, "", value) - if (value ~ /^"/) { - sub(/^"/, "", value) - sub(/".*$/, "", value) - } - return value - } +declare -A COLORS - function alias_color(target, source) { - if (colors[target] == "" && colors[source] != "") colors[target] = colors[source] - } +while IFS=$'\t' read -r key value; do + COLORS[$key]="$value" +done < <(omarchy-theme-color --file "$theme" --all) - function emit_color(color_index, key) { - if (colors[key] != "") printf "\033]4;%d;%s\007", color_index, colors[key] - } +emit_osc() { + local code="$1" + local key="$2" - { - key = $1 - gsub(/^[[:space:]]+|[[:space:]]+$/, "", key) - value = clean($2) - colors[key] = value - } + [[ -n ${COLORS[$key]:-} ]] || return 0 + printf '\033]%s;%s\007' "$code" "${COLORS[$key]}" +} - END { - if (colors["background"] != "") colors["bg"] = colors["background"] - if (colors["foreground"] != "") colors["fg"] = colors["foreground"] - if (colors["bg"] != "") colors["background"] = colors["bg"] - if (colors["fg"] != "") colors["foreground"] = colors["fg"] - if (colors["bg"] != "") colors["color0"] = colors["bg"] - if (colors["fg"] != "") colors["color7"] = colors["fg"] +emit_osc 10 foreground +emit_osc 11 background +emit_osc 12 cursor +emit_osc 17 selection_background +emit_osc 19 selection_foreground - alias_color("color0", "bg") - alias_color("color0", "background") - alias_color("color1", "red") - alias_color("color2", "green") - 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" +for i in {0..15}; do + [[ -n ${COLORS[color$i]:-} ]] || continue + printf '\033]4;%d;%s\007' "$i" "${COLORS[color$i]}" +done diff --git a/bin/omarchy-theme-set-gnome b/bin/omarchy-theme-set-gnome index 1d9708b9..ca298ffb 100755 --- a/bin/omarchy-theme-set-gnome +++ b/bin/omarchy-theme-set-gnome @@ -13,33 +13,9 @@ fi THEME_DIR=$HOME/.local/state/omarchy/current/theme COLORS_FILE="$THEME_DIR/colors.toml" -# In-tree light themes now declare `mode = "light"` in colors.toml instead of -# shipping a separate light.mode marker. Keep light.mode as a user-theme fallback. -theme_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 +# omarchy-theme-color resolves mode from colors.toml (`mode = "light"`), a +# legacy light.mode marker beside it, or background luminance for user themes. +mode=$(omarchy-theme-color --file "$COLORS_FILE" mode) if [[ $mode == "light" ]]; then gsettings set org.gnome.desktop.interface color-scheme "prefer-light" diff --git a/bin/omarchy-theme-set-templates b/bin/omarchy-theme-set-templates index 06069845..de4d5991 100755 --- a/bin/omarchy-theme-set-templates +++ b/bin/omarchy-theme-set-templates @@ -367,30 +367,6 @@ apply_shell_section_overrides() { 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 if [[ -f $COLORS_FILE ]]; then sed_script=$(mktemp) @@ -398,103 +374,11 @@ if [[ -f $COLORS_FILE ]]; then shopt -s nullglob template_files=("$USER_TEMPLATES_DIR"/*.tpl "$TEMPLATES_DIR"/*.tpl) - while IFS='=' read -r key value; do - key="${key//[\"\' ]/}" # strip quotes and spaces from key - [[ $key && $key != \#* ]] || continue # skip empty lines and comments - value="${value#*[\"\']}" - value="${value%%[\"\']*}" # extract value between quotes (ignores inline comments) - + # Parsing and alias/fallback resolution (legacy colorN names, derived + # shades, mode/theme_type) is shared with every other colors.toml consumer. + while IFS=$'\t' read -r key value; do THEME_COLORS[$key]="$value" - done <"$COLORS_FILE" - - # 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]}" + done < <(omarchy-theme-color --file "$COLORS_FILE" --all) for key in "${!THEME_COLORS[@]}"; do add_template_value "$key" "${THEME_COLORS[$key]}" diff --git a/bin/omarchy-theme-set-tmux b/bin/omarchy-theme-set-tmux index 3765a8ca..07fb6481 100755 --- a/bin/omarchy-theme-set-tmux +++ b/bin/omarchy-theme-set-tmux @@ -37,11 +37,10 @@ sync_theme_environment() { sync_colorfgbg() { local colorfgbg="15;0" - local mode - mode=$(theme_color mode) - - if [[ $mode == "light" ]] || [[ -z $mode && -f $CURRENT_THEME_PATH/light.mode ]]; then + # 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 [[ $(theme_color mode) == "light" ]]; then colorfgbg="0;15" fi @@ -53,34 +52,7 @@ theme_osc_sequences() { } theme_color() { - local key="$1" - 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" + omarchy-theme-color --file "$COLORS_TOML" "$@" } sync_tmux_window_style() { @@ -88,8 +60,8 @@ sync_tmux_window_style() { [[ -f $COLORS_TOML ]] || return - foreground=$(theme_color foreground fg) - background=$(theme_color background bg) + foreground=$(theme_color foreground) + background=$(theme_color background) [[ -n $foreground && -n $background ]] || return