#!/bin/bash # Apply theme colors from ~/.config/colors.conf to all deployed dotfile configs. # # Guards: # - Refuses if any deployed config is symlinked back to ~/Dotfiles (old-style # install), to prevent theme changes from propagating into the git repo. # - When configs are copied into ~/.config (new-style install), overwrites # those copies in-place. # # Tracks last-applied state in ~/.config/colors.state so only changed colors # trigger replacements. Run again after re-install to re-apply your theme. # # Usage: ~/apply-theme.sh [/path/to/colors.conf] set -euo pipefail DOTFILES="${DOTFILES:-$HOME/Dotfiles}" COLORS_CONF="${1:-$HOME/.config/colors.conf}" STATE_FILE="$HOME/.config/colors.state" # Hardcoded defaults — the values baked into every source file in the repo. # Used to bootstrap colors.state on first run after a fresh install. BOOT_TEXT="D6ABAB" BOOT_BG="1A1A1A" BOOT_HIGHLIGHT="E40046" BOOT_DARK="5018DD" BOOT_RED="F50505" # "dotfiles_relative_path|absolute_deployed_path" USER_FILES=( "starship.toml|$HOME/.config/starship.toml" "yazi/theme.toml|$HOME/.config/yazi/theme.toml" "desktopenvs/hyprland/hypr/hyprland.conf|$HOME/.config/hypr/hyprland.conf" "desktopenvs/hyprland/hypr/hyprtoolkit.conf|$HOME/.config/hypr/hyprtoolkit.conf" "desktopenvs/hyprland/hypr/hyprlock.conf|$HOME/.config/hypr/hyprlock.conf" "desktopenvs/hyprland/kitty/current-theme.conf|$HOME/.config/kitty/current-theme.conf" "desktopenvs/hyprland/kitty/kitty.conf|$HOME/.config/kitty/kitty.conf" "desktopenvs/hyprland/kitty/themes/cyberqueer.conf|$HOME/.config/kitty/themes/cyberqueer.conf" "desktopenvs/hyprland/waybar/style.css|$HOME/.config/waybar/style.css" "desktopenvs/hyprland/wofi/style.css|$HOME/.config/wofi/style.css" "desktopenvs/hyprland/walker/themes/cyberqueer.css|$HOME/.config/walker/themes/cyberqueer.css" "desktopenvs/hyprland/nwg-dock-hyprland/style.css|$HOME/.config/nwg-dock-hyprland/style.css" "desktopenvs/hyprland/nwg-drawer/drawer.css|$HOME/.config/nwg-drawer/drawer.css" "desktopenvs/hyprland/nwg-panel/menu-start.css|$HOME/.config/nwg-panel/menu-start.css" "desktopenvs/hyprland/vicinae/cyberqueer.toml|$HOME/.config/vicinae/cyberqueer.toml" "desktopenvs/hyprland/scripts/onscreenkb.sh|$HOME/.config/scripts/onscreenkb.sh" "desktopenvs/hyprland/spicetify/Themes/cli-cyberqueer/color.ini|$HOME/.config/spicetify/Themes/cli-cyberqueer/color.ini" "desktopenvs/hyprland/spicetify/Themes/matte-cyberqueer/color.ini|$HOME/.config/spicetify/Themes/matte-cyberqueer/color.ini" "desktopenvs/hyprland/ulauncher/user-themes/cyberqueer/manifest.json|$HOME/.config/ulauncher/user-themes/cyberqueer/manifest.json" "desktopenvs/hyprland/ulauncher/user-themes/cyberqueer/theme.css|$HOME/.config/ulauncher/user-themes/cyberqueer/theme.css" "desktopenvs/hyprland/ulauncher/user-themes/cyberqueer/generated.css|$HOME/.config/ulauncher/user-themes/cyberqueer/generated.css" "desktopenvs/hyprland/Vencord/themes/cyberqueer.theme.css|$HOME/.config/Vencord/themes/cyberqueer.theme.css" "desktopenvs/hyprland/Vencord/themes/system24/theme/flavors/cyberqueer.theme.css|$HOME/.config/Vencord/themes/system24/theme/flavors/cyberqueer.theme.css" "qt-themes/cyberqueer/style.qss|$HOME/.config/qt6ct/qss/style.qss" "qt-themes/cyberqueer/cyberqueer.conf|$HOME/.config/qt6ct/colors/cyberqueer.conf" "qt-themes/cyberqueer/style-plugin/CyberQueerStyle.cpp|$DOTFILES/qt-themes/cyberqueer/style-plugin/CyberQueerStyle.cpp" "qt-themes/cyberqueer/hyprpolkitagent-qt.conf|$HOME/.config/systemd/user/hyprpolkitagent.service.d/qt-theme.conf" ) # System-owned paths — sed is run via sudo SYS_FILES=( "etc-ly-config.ini|/etc/ly/config.ini" "gtk-themes/cyberqueer/gtk-3.0/gtk.css|/usr/share/themes/cyberqueer/gtk-3.0/gtk.css" "gtk-themes/cyberqueer/gtk-4.0/gtk.css|/usr/share/themes/cyberqueer/gtk-4.0/gtk.css" ) # --------------------------------------------------------------------------- die() { echo "error: $*" >&2; exit 1; } parse_colors() { local file="$1" [[ -f "$file" ]] || die "not found: $file" while IFS='=' read -r key val; do key="${key%%[[:space:]]*}" [[ "$key" =~ ^[[:space:]]*# || -z "$key" ]] && continue val="${val%%#*}" val="${val//[[:space:]]/}" val="${val^^}" printf '%s=%s\n' "$key" "$val" done < "$file" } # Returns 0 if any path component of $1 is a symlink pointing into DOTFILES links_into_dotfiles() { local path="$1" while [[ "${#path}" -gt 1 ]]; do if [[ -L "$path" ]]; then local target target=$(readlink -f "$path" 2>/dev/null) || break [[ "$target" == "$DOTFILES"/* || "$target" == "$DOTFILES" ]] && return 0 fi [[ "$path" == "$HOME" ]] && break path=$(dirname "$path") done return 1 } # Run sed -i with optional command prefix (e.g. "sudo"). # Called as: do_replace [sudo] do_replace() { local file="$1" shift # remaining "$@" is either empty or "sudo" for key in "${CHANGED_KEYS[@]}"; do local old="${OLD[$key]:-}" local new="${NEW[$key]}" [[ -z "$old" || "$old" == "$new" ]] && continue "$@" sed -i "s/${old}/${new}/gI" "$file" done } # --------------------------------------------------------------------------- # Bootstrap state on fresh install (deployed files still have default colors) if [[ ! -f "$STATE_FILE" ]]; then cat > "$STATE_FILE" </dev/null; then systemctl --user daemon-reload systemctl --user restart hyprpolkitagent echo "Restarted hyprpolkitagent with updated colors." fi # Rebuild Qt style plugin if its source was updated PLUGIN_BUILD="$DOTFILES/qt-themes/cyberqueer/style-plugin/build.sh" if [[ -f "$PLUGIN_BUILD" ]]; then if bash "$PLUGIN_BUILD"; then echo "Rebuilt cyberqueer Qt style plugin." else echo "Warning: Qt style plugin rebuild failed — relaunch apps will still use old colors." fi fi # --------------------------------------------------------------------------- # Persist state cp "$COLORS_CONF" "$STATE_FILE" echo "User files: $u_ok updated, $u_skip not installed." [[ $((s_ok + s_skip)) -gt 0 ]] && echo "System files: $s_ok updated, $s_skip not installed." echo "State saved → $STATE_FILE"