diff --git a/bin/omarchy-theme-set-templates b/bin/omarchy-theme-set-templates index 92236d19..a7266490 100755 --- a/bin/omarchy-theme-set-templates +++ b/bin/omarchy-theme-set-templates @@ -8,34 +8,137 @@ USER_TEMPLATES_DIR="$HOME/.config/omarchy/themed" NEXT_THEME_DIR="$HOME/.config/omarchy/current/next-theme" COLORS_FILE="$NEXT_THEME_DIR/colors.toml" +declare -A THEME_COLORS + # Convert hex color to decimal RGB (e.g., "#1e1e2e" -> "30,30,46") hex_to_rgb() { local hex="${1#\#}" printf "%d,%d,%d" "0x${hex:0:2}" "0x${hex:2:2}" "0x${hex:4:2}" } +# 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 + } + ' +} + +add_template_value() { + local key="$1" + local value="$2" + local rgb + + printf 's|{{ %s }}|%s|g\n' "$key" "$value" >>"$sed_script" + printf 's|{{ %s_strip }}|%s|g\n' "$key" "${value#\#}" >>"$sed_script" + + if [[ $value =~ ^#[0-9A-Fa-f]{6}$ ]]; then + rgb=$(hex_to_rgb "$value") + printf 's|{{ %s_rgb }}|%s|g\n' "$key" "$rgb" >>"$sed_script" + fi +} + +add_mix_value() { + local token="$1" + local content fn start_key end_key amount start end value + + content="${token#\{\{}" + content="${content%\}\}}" + read -r fn start_key end_key amount <<<"$content" + + start="${THEME_COLORS[$start_key]:-}" + end="${THEME_COLORS[$end_key]:-}" + + [[ $start =~ ^#[0-9A-Fa-f]{6}$ && $end =~ ^#[0-9A-Fa-f]{6}$ ]] || return + + value=$(mix_color "$start" "$end" "$amount") + + case "$fn" in + mix) + ;; + mix_strip) + value="${value#\#}" + ;; + mix_rgb) + value=$(hex_to_rgb "$value") + ;; + *) + return + ;; + esac + + printf 's|%s|%s|g\n' "$token" "$value" >>"$sed_script" +} + +add_mix_values() { + local tpl token + local -A seen=() + + for tpl in "${template_files[@]}"; do + while IFS= read -r token; do + [[ -n ${seen[$token]:-} ]] && continue + seen[$token]=1 + add_mix_value "$token" + done < <(grep -hEo '\{\{[[:space:]]*mix(_strip|_rgb)?[[:space:]]+[A-Za-z0-9_]+[[:space:]]+[A-Za-z0-9_]+[[:space:]]+[0-9]+([.][0-9]+)?%?[[:space:]]*\}\}' "$tpl" 2>/dev/null || true) + done +} + # Only generate dynamic templates for themes with a colors.toml definition if [[ -f $COLORS_FILE ]]; then sed_script=$(mktemp) + 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) - printf 's|{{ %s }}|%s|g\n' "$key" "$value" # {{ key }} -> value - printf 's|{{ %s_strip }}|%s|g\n' "$key" "${value#\#}" # {{ key_strip }} -> value without leading # - if [[ $value =~ ^# ]]; then - rgb=$(hex_to_rgb "$value") - echo "s|{{ ${key}_rgb }}|${rgb}|g" - fi - done <"$COLORS_FILE" >"$sed_script" + THEME_COLORS[$key]="$value" + add_template_value "$key" "$value" + done <"$COLORS_FILE" - shopt -s nullglob + add_mix_values # Process user templates first, then built-in templates (user overrides built-in) - for tpl in "$USER_TEMPLATES_DIR"/*.tpl "$TEMPLATES_DIR"/*.tpl; do + for tpl in "${template_files[@]}"; do filename=$(basename "$tpl" .tpl) output_path="$NEXT_THEME_DIR/$filename"