1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-05 21:15:38 -05:00
Files
DankMaterialShell/quickshell/scripts/matugen-worker.sh
Saurabh de8f2e6a68 feat/matugen3 (#771)
* added matugen 3 terminal templates and logic

fixed version check and light terminal check

refactored json generation

fixed syntax

keep tmp debug

fixed file outputs

fixed syntax issues and implicit passing

added debug stderr output

* moved calls to matugen after template is built correctly

added --json hex

disabled debug message

cleaned up code into modular functions, re-added second full matugen call

fixed args

added shift

commented vs code section

debug changes

* arg format fixes

fixed json import flag

fixed string quotation

fix arg order

* cleaned up

fix cfg naming

* removed mt2.0 templates and refactored worker

removed/replaced matugen 2 templates

fix formatter diffs + consistent styling

* fixed last json output

* fixed syntax error

* vs code templates

* matugen: inject all stock/custom theme colors as overrides
- also some general architectural changes

* dank16: remove vscode enrich option

---------

Co-authored-by: bbedward
2025-11-26 16:34:53 -05:00

276 lines
9.9 KiB
Bash
Executable File

#!/usr/bin/env bash
set -uo pipefail
log() { echo "[matugen-worker] $*" >&2; }
err() { echo "[matugen-worker] ERROR: $*" >&2; }
[[ $# -lt 6 ]] && { echo "Usage: $0 STATE_DIR SHELL_DIR CONFIG_DIR SYNC_MODE_WITH_PORTAL TERMINALS_ALWAYS_DARK --run" >&2; exit 1; }
STATE_DIR="$1"
SHELL_DIR="$2"
CONFIG_DIR="$3"
SYNC_MODE_WITH_PORTAL="$4"
TERMINALS_ALWAYS_DARK="$5"
shift 5
[[ "${1:-}" != "--run" ]] && { echo "Usage: $0 ... --run" >&2; exit 1; }
[[ ! -d "$STATE_DIR" ]] && { err "STATE_DIR '$STATE_DIR' does not exist"; exit 1; }
[[ ! -d "$SHELL_DIR" ]] && { err "SHELL_DIR '$SHELL_DIR' does not exist"; exit 1; }
[[ ! -d "$CONFIG_DIR" ]] && { err "CONFIG_DIR '$CONFIG_DIR' does not exist"; exit 1; }
DESIRED_JSON="$STATE_DIR/matugen.desired.json"
BUILT_KEY="$STATE_DIR/matugen.key"
LOCK="$STATE_DIR/matugen-worker.lock"
COLORS_OUTPUT="$STATE_DIR/dms-colors.json"
exec 9>"$LOCK"
flock 9
rm -f "$BUILT_KEY"
read_json_field() {
local json="$1" field="$2"
echo "$json" | sed -n "s/.*\"$field\"[[:space:]]*:[[:space:]]*\"\([^\"]*\)\".*/\1/p" | head -1
}
read_json_escaped_field() {
local json="$1" field="$2"
local after="${json#*\"$field\":\"}"
[[ "$after" == "$json" ]] && return
local result=""
while [[ -n "$after" ]]; do
local char="${after:0:1}"
after="${after:1}"
[[ "$char" == '"' ]] && break
[[ "$char" == '\' ]] && { result+="${after:0:1}"; after="${after:1}"; continue; }
result+="$char"
done
echo "$result"
}
read_json_bool() {
local json="$1" field="$2"
echo "$json" | sed -n "s/.*\"$field\"[[:space:]]*:[[:space:]]*\([^,}]*\).*/\1/p" | head -1 | tr -d ' '
}
compute_key() {
local json="$1"
local kind=$(read_json_field "$json" "kind")
local value=$(read_json_field "$json" "value")
local mode=$(read_json_field "$json" "mode")
local icon=$(read_json_field "$json" "iconTheme")
local mtype=$(read_json_field "$json" "matugenType")
local run_user=$(read_json_bool "$json" "runUserTemplates")
local stock_colors=$(read_json_escaped_field "$json" "stockColors")
echo "${kind}|${value}|${mode}|${icon:-default}|${mtype:-scheme-tonal-spot}|${run_user:-true}|${stock_colors:-}" | sha256sum | cut -d' ' -f1
}
append_config() {
local check_cmd="$1" file_name="$2" cfg_file="$3"
local target="$SHELL_DIR/matugen/configs/$file_name"
[[ ! -f "$target" ]] && return
[[ "$check_cmd" != "skip" ]] && ! command -v "$check_cmd" >/dev/null 2>&1 && return
sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" "$target" >> "$cfg_file"
echo "" >> "$cfg_file"
}
build_merged_config() {
local mode="$1" run_user="$2" cfg_file="$3"
if [[ "$run_user" == "true" && -f "$CONFIG_DIR/matugen/config.toml" ]]; then
awk '/^\[config\]/{p=1} /^\[templates\]/{p=0} p' "$CONFIG_DIR/matugen/config.toml" >> "$cfg_file"
else
echo "[config]" >> "$cfg_file"
fi
echo "" >> "$cfg_file"
grep -v '^\[config\]' "$SHELL_DIR/matugen/configs/base.toml" | sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" >> "$cfg_file"
echo "" >> "$cfg_file"
cat >> "$cfg_file" << EOF
[templates.dank]
input_path = '$SHELL_DIR/matugen/templates/dank.json'
output_path = '$COLORS_OUTPUT'
EOF
[[ "$mode" == "light" ]] && append_config "skip" "gtk3-light.toml" "$cfg_file" || append_config "skip" "gtk3-dark.toml" "$cfg_file"
append_config "niri" "niri.toml" "$cfg_file"
append_config "qt5ct" "qt5ct.toml" "$cfg_file"
append_config "qt6ct" "qt6ct.toml" "$cfg_file"
append_config "firefox" "firefox.toml" "$cfg_file"
append_config "pywalfox" "pywalfox.toml" "$cfg_file"
append_config "vesktop" "vesktop.toml" "$cfg_file"
append_config "ghostty" "ghostty.toml" "$cfg_file"
append_config "kitty" "kitty.toml" "$cfg_file"
append_config "foot" "foot.toml" "$cfg_file"
append_config "alacritty" "alacritty.toml" "$cfg_file"
append_config "wezterm" "wezterm.toml" "$cfg_file"
append_config "dgop" "dgop.toml" "$cfg_file"
append_config "code" "vscode.toml" "$cfg_file"
append_config "codium" "codium.toml" "$cfg_file"
if [[ "$run_user" == "true" && -f "$CONFIG_DIR/matugen/config.toml" ]]; then
awk '/^\[templates\]/{p=1} p' "$CONFIG_DIR/matugen/config.toml" >> "$cfg_file"
echo "" >> "$cfg_file"
fi
if [[ -d "$CONFIG_DIR/matugen/dms/configs" ]]; then
for config in "$CONFIG_DIR/matugen/dms/configs"/*.toml; do
[[ -f "$config" ]] || continue
cat "$config" >> "$cfg_file"
echo "" >> "$cfg_file"
done
fi
}
generate_dank16() {
local primary="$1" surface="$2" light_flag="$3"
local args=("$primary" --json)
[[ -n "$light_flag" ]] && args+=("$light_flag")
[[ -n "$surface" ]] && args+=(--background "$surface")
dms dank16 "${args[@]}" 2>/dev/null || echo '{}'
}
set_system_color_scheme() {
[[ "$SYNC_MODE_WITH_PORTAL" != "true" ]] && return
local mode="$1"
local scheme="prefer-dark"
[[ "$mode" == "light" ]] && scheme="default"
gsettings set org.gnome.desktop.interface color-scheme "$scheme" 2>/dev/null || \
dconf write /org/gnome/desktop/interface/color-scheme "'$scheme'" 2>/dev/null || true
}
refresh_gtk() {
local mode="$1"
local gtk_css="$CONFIG_DIR/gtk-3.0/gtk.css"
[[ ! -e "$gtk_css" ]] && return
local should_run=false
if [[ -L "$gtk_css" ]]; then
[[ "$(readlink "$gtk_css")" == *"dank-colors.css"* ]] && should_run=true
elif grep -q "dank-colors.css" "$gtk_css" 2>/dev/null; then
should_run=true
fi
[[ "$should_run" != "true" ]] && return
gsettings set org.gnome.desktop.interface gtk-theme "" 2>/dev/null || true
gsettings set org.gnome.desktop.interface gtk-theme "adw-gtk3-${mode}" 2>/dev/null || true
}
setup_vscode_extension() {
local cmd="$1" ext_dir="$2" config_dir="$3"
command -v "$cmd" >/dev/null 2>&1 || return
[[ ! -d "$config_dir" ]] && return
local theme_dir="$ext_dir/themes"
mkdir -p "$theme_dir"
cp "$SHELL_DIR/matugen/templates/vscode-package.json" "$ext_dir/package.json" 2>/dev/null || true
cp "$SHELL_DIR/matugen/templates/vscode-vsixmanifest.xml" "$ext_dir/.vsixmanifest" 2>/dev/null || true
}
signal_terminals() {
pgrep -x kitty >/dev/null 2>&1 && pkill -USR1 kitty
pgrep -x ghostty >/dev/null 2>&1 && pkill -USR2 ghostty
}
build_once() {
local json="$1"
local kind=$(read_json_field "$json" "kind")
local value=$(read_json_field "$json" "value")
local mode=$(read_json_field "$json" "mode")
local mtype=$(read_json_field "$json" "matugenType")
local run_user=$(read_json_bool "$json" "runUserTemplates")
local stock_colors=$(read_json_escaped_field "$json" "stockColors")
[[ -z "$mtype" ]] && mtype="scheme-tonal-spot"
[[ -z "$run_user" ]] && run_user="true"
local TMP_CFG=$(mktemp)
trap "rm -f '$TMP_CFG'" RETURN
build_merged_config "$mode" "$run_user" "$TMP_CFG"
local light_flag=""
[[ "$mode" == "light" ]] && light_flag="--light"
local primary surface dank16_dark dank16_light import_args=()
if [[ -n "$stock_colors" ]]; then
log "Using stock/custom theme colors with matugen base"
primary=$(echo "$stock_colors" | sed -n 's/.*"primary"[^{]*{[^}]*"dark"[^{]*{[^}]*"color"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
surface=$(echo "$stock_colors" | sed -n 's/.*"surface"[^{]*{[^}]*"dark"[^{]*{[^}]*"color"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
[[ -z "$primary" ]] && { err "Failed to extract primary from stock colors"; return 1; }
dank16_dark=$(generate_dank16 "$primary" "$surface" "")
dank16_light=$(generate_dank16 "$primary" "$surface" "--light")
local dank16_current
[[ "$mode" == "light" ]] && dank16_current="$dank16_light" || dank16_current="$dank16_dark"
[[ "$TERMINALS_ALWAYS_DARK" == "true" && "$mode" == "light" ]] && dank16_current="$dank16_dark"
import_args+=(--import-json-string "{\"colors\": $stock_colors, \"dank16\": $dank16_current}")
log "Running matugen color hex with stock color overrides"
if ! matugen color hex "$primary" -m "$mode" -t "${mtype:-scheme-tonal-spot}" -c "$TMP_CFG" "${import_args[@]}"; then
err "matugen failed"
return 1
fi
else
log "Using dynamic theme from $kind: $value"
local matugen_cmd=("matugen")
[[ "$kind" == "hex" ]] && matugen_cmd+=("color" "hex") || matugen_cmd+=("$kind")
matugen_cmd+=("$value")
local mat_json
mat_json=$("${matugen_cmd[@]}" -m dark -t "$mtype" --json hex --dry-run 2>/dev/null | tr -d '\n')
[[ -z "$mat_json" ]] && { err "matugen dry-run failed"; return 1; }
primary=$(echo "$mat_json" | sed -n 's/.*"primary"[[:space:]]*:[[:space:]]*{[^}]*"dark"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')
surface=$(echo "$mat_json" | sed -n 's/.*"surface"[[:space:]]*:[[:space:]]*{[^}]*"dark"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')
[[ -z "$primary" ]] && { err "Failed to extract primary color"; return 1; }
dank16_dark=$(generate_dank16 "$primary" "$surface" "")
dank16_light=$(generate_dank16 "$primary" "$surface" "--light")
local dank16_current
[[ "$mode" == "light" ]] && dank16_current="$dank16_light" || dank16_current="$dank16_dark"
[[ "$TERMINALS_ALWAYS_DARK" == "true" && "$mode" == "light" ]] && dank16_current="$dank16_dark"
import_args+=(--import-json-string "{\"dank16\": $dank16_current}")
log "Running matugen $kind with dank16 injection"
if ! "${matugen_cmd[@]}" -m "$mode" -t "$mtype" -c "$TMP_CFG" "${import_args[@]}"; then
err "matugen failed"
return 1
fi
fi
refresh_gtk "$mode"
setup_vscode_extension "code" "$HOME/.vscode/extensions/local.dynamic-base16-dankshell-0.0.1" "$HOME/.vscode"
setup_vscode_extension "codium" "$HOME/.vscode-oss/extensions/local.dynamic-base16-dankshell-0.0.1" "$HOME/.vscode-oss"
set_system_color_scheme "$mode"
signal_terminals
return 0
}
[[ ! -f "$DESIRED_JSON" ]] && { log "No desired state file"; exit 0; }
DESIRED=$(cat "$DESIRED_JSON")
WANT_KEY=$(compute_key "$DESIRED")
HAVE_KEY=""
[[ -f "$BUILT_KEY" ]] && HAVE_KEY=$(cat "$BUILT_KEY" 2>/dev/null || true)
[[ "$WANT_KEY" == "$HAVE_KEY" ]] && { log "Already up to date"; exit 0; }
log "Building theme (key: ${WANT_KEY:0:12}...)"
if build_once "$DESIRED"; then
echo "$WANT_KEY" > "$BUILT_KEY"
log "Done"
exit 0
else
err "Build failed"
exit 2
fi