235 lines
8.9 KiB
Bash
Executable File
235 lines
8.9 KiB
Bash
Executable File
#!/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 <file> [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" <<EOF
|
|
COLOR_TEXT=$BOOT_TEXT
|
|
COLOR_BG=$BOOT_BG
|
|
COLOR_HIGHLIGHT=$BOOT_HIGHLIGHT
|
|
COLOR_DARK=$BOOT_DARK
|
|
COLOR_RED=$BOOT_RED
|
|
EOF
|
|
echo "Created $STATE_FILE with default CyberQueer colors"
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Symlink guard — refuse if any deployed path traces back to the git repo
|
|
|
|
SYMLINKED=()
|
|
for entry in "${USER_FILES[@]}"; do
|
|
deployed="${entry#*|}"
|
|
[[ -e "$deployed" ]] || continue
|
|
links_into_dotfiles "$deployed" && SYMLINKED+=("$deployed")
|
|
done
|
|
|
|
if [[ ${#SYMLINKED[@]} -gt 0 ]]; then
|
|
echo "error: the following deployed configs are symlinked back to $DOTFILES:"
|
|
printf ' %s\n' "${SYMLINKED[@]}"
|
|
cat <<'EOF'
|
|
|
|
Modifying these would write theme changes directly into the git repo.
|
|
Re-install using setup/modules/Desktop-Enviroments/hyprland-new.sh,
|
|
which copies configs instead of symlinking them.
|
|
|
|
To convert a single directory manually:
|
|
cp -rL ~/.config/hypr /tmp/hypr && rm -rf ~/.config/hypr && mv /tmp/hypr ~/.config/hypr
|
|
EOF
|
|
exit 1
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Load and diff colors
|
|
|
|
declare -A OLD NEW
|
|
|
|
while IFS='=' read -r k v; do OLD[$k]="$v"; done < <(parse_colors "$STATE_FILE")
|
|
while IFS='=' read -r k v; do NEW[$k]="$v"; done < <(parse_colors "$COLORS_CONF")
|
|
|
|
CHANGED_KEYS=()
|
|
for key in "${!NEW[@]}"; do
|
|
[[ "${OLD[$key]:-}" != "${NEW[$key]}" ]] && CHANGED_KEYS+=("$key")
|
|
done
|
|
|
|
if [[ ${#CHANGED_KEYS[@]} -eq 0 ]]; then
|
|
echo "No color changes — nothing to do."
|
|
exit 0
|
|
fi
|
|
|
|
echo "Changes to apply:"
|
|
for key in "${CHANGED_KEYS[@]}"; do
|
|
printf ' %-20s #%s → #%s\n' "$key" "${OLD[$key]:-?}" "${NEW[$key]}"
|
|
done
|
|
echo
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Apply to user files
|
|
|
|
u_ok=0; u_skip=0
|
|
for entry in "${USER_FILES[@]}"; do
|
|
deployed="${entry#*|}"
|
|
if [[ ! -f "$deployed" ]]; then
|
|
u_skip=$((u_skip + 1))
|
|
continue
|
|
fi
|
|
do_replace "$deployed"
|
|
u_ok=$((u_ok + 1))
|
|
done
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Apply to system files (sudo)
|
|
|
|
s_ok=0; s_skip=0
|
|
for entry in "${SYS_FILES[@]}"; do
|
|
deployed="${entry#*|}"
|
|
if [[ ! -f "$deployed" ]]; then
|
|
s_skip=$((s_skip + 1))
|
|
continue
|
|
fi
|
|
if do_replace "$deployed" sudo; then
|
|
s_ok=$((s_ok + 1))
|
|
else
|
|
echo " SKIP (sudo failed): $deployed"
|
|
s_skip=$((s_skip + 1))
|
|
fi
|
|
done
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Reload services that read their config once at start
|
|
|
|
POLKIT_DROP="$HOME/.config/systemd/user/hyprpolkitagent.service.d/qt-theme.conf"
|
|
if [[ -f "$POLKIT_DROP" ]] && systemctl --user is-active --quiet hyprpolkitagent 2>/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"
|