Add color mixing
This commit is contained in:
@@ -8,34 +8,137 @@ USER_TEMPLATES_DIR="$HOME/.config/omarchy/themed"
|
|||||||
NEXT_THEME_DIR="$HOME/.config/omarchy/current/next-theme"
|
NEXT_THEME_DIR="$HOME/.config/omarchy/current/next-theme"
|
||||||
COLORS_FILE="$NEXT_THEME_DIR/colors.toml"
|
COLORS_FILE="$NEXT_THEME_DIR/colors.toml"
|
||||||
|
|
||||||
|
declare -A THEME_COLORS
|
||||||
|
|
||||||
# Convert hex color to decimal RGB (e.g., "#1e1e2e" -> "30,30,46")
|
# Convert hex color to decimal RGB (e.g., "#1e1e2e" -> "30,30,46")
|
||||||
hex_to_rgb() {
|
hex_to_rgb() {
|
||||||
local hex="${1#\#}"
|
local hex="${1#\#}"
|
||||||
printf "%d,%d,%d" "0x${hex:0:2}" "0x${hex:2:2}" "0x${hex:4:2}"
|
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
|
# 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)
|
||||||
|
|
||||||
|
shopt -s nullglob
|
||||||
|
template_files=("$USER_TEMPLATES_DIR"/*.tpl "$TEMPLATES_DIR"/*.tpl)
|
||||||
|
|
||||||
while IFS='=' read -r key value; do
|
while IFS='=' read -r key value; do
|
||||||
key="${key//[\"\' ]/}" # strip quotes and spaces from key
|
key="${key//[\"\' ]/}" # strip quotes and spaces from key
|
||||||
[[ $key && $key != \#* ]] || continue # skip empty lines and comments
|
[[ $key && $key != \#* ]] || continue # skip empty lines and comments
|
||||||
value="${value#*[\"\']}"
|
value="${value#*[\"\']}"
|
||||||
value="${value%%[\"\']*}" # extract value between quotes (ignores inline comments)
|
value="${value%%[\"\']*}" # extract value between quotes (ignores inline comments)
|
||||||
|
|
||||||
printf 's|{{ %s }}|%s|g\n' "$key" "$value" # {{ key }} -> value
|
THEME_COLORS[$key]="$value"
|
||||||
printf 's|{{ %s_strip }}|%s|g\n' "$key" "${value#\#}" # {{ key_strip }} -> value without leading #
|
add_template_value "$key" "$value"
|
||||||
if [[ $value =~ ^# ]]; then
|
done <"$COLORS_FILE"
|
||||||
rgb=$(hex_to_rgb "$value")
|
|
||||||
echo "s|{{ ${key}_rgb }}|${rgb}|g"
|
|
||||||
fi
|
|
||||||
done <"$COLORS_FILE" >"$sed_script"
|
|
||||||
|
|
||||||
shopt -s nullglob
|
add_mix_values
|
||||||
|
|
||||||
# Process user templates first, then built-in templates (user overrides built-in)
|
# 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)
|
filename=$(basename "$tpl" .tpl)
|
||||||
output_path="$NEXT_THEME_DIR/$filename"
|
output_path="$NEXT_THEME_DIR/$filename"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user