#!/bin/bash # Install waybar-theme-udt by symlink, so the repo stays canonical. # Copyright (C) 2026 Danilo M. # Licensed under the GNU General Public License v2 only. # # Installs to ~/.config/waybar-udt/, which is a separate config directory from # the stock ~/.config/waybar/: that one is left on disk untouched, so its # modules and scripts stay available to go back to. # # Nothing is started here. Hyprland launches the bar on login from # ~/.config/hypr/sections/autostart.lua; the command is printed at the end for # starting it by hand. set -euo pipefail repo="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" target="$HOME/.config/waybar-udt" udt="$(cd "$repo/../unified-desktop-theme" 2>/dev/null && pwd || true)" mkdir -p "$target/modules/hyprland" "$target/modules/custom" \ "$target/modules/extras" "$target/modules/image" \ "$target/styles" "$HOME/bin" # ---------------------------------------------------------------- colours -- # The palette is udt's, not this repo's. Generating it needs the sibling # checkout, so a missing one is a clear failure rather than a bar with no # colours: every stylesheet below names @main-bg and friends. if [ -z "$udt" ]; then echo "error: unified-desktop-theme not found next to this repo" >&2 echo " expected at $repo/../unified-desktop-theme" >&2 exit 1 fi # udt's install.sh calls this script, and it has already run udt-palette by # then. Running it again would be harmless but pointless, so it says so. if [ "${UDT_PALETTE_DONE:-}" != "1" ]; then "$udt/bin/udt-palette" fi install -Dm644 "$udt/templates/waybar/theme.css" "$target/styles/theme.css" # The dot scripts are bash, not CSS, so they cannot read @define-color. Write # the handful of colours they need as a shell fragment they source. # # The values are read back out of the stylesheet udt-palette just generated, # because that is the only place they exist in a form this script can see: # udt-palette renders files, it does not answer queries about single roles. # # Pango wants a colour it can parse, and the generated file mixes #rrggbb with # rgb()/rgba() spellings, so each is normalised to hex on the way out. scheme="$(sed -n 's/^scheme *= *//p' "$HOME/.config/udt/roles.conf")" css_color() { # Last definition wins, matching how GTK resolves a redefined colour. sed -n "s/^@define-color $1 *\(.*\);\$/\1/p" "$target/styles/theme.css" | tail -1 } to_hex() { python3 -c ' import re, sys v = sys.argv[1].strip() m = re.match(r"rgba?\(([^)]*)\)", v) if m: p = [x.strip() for x in m.group(1).split(",")] print("#%02x%02x%02x" % tuple(int(float(c)) for c in p[:3])) else: print(v) ' "$2" } { echo "# Generated by waybar-theme-udt/install.sh from the $scheme scheme." echo "# Sourced by vms_dots.sh and privacy_dots.sh. Do not edit." # The generated stylesheet carries no success/info roles, so the dots use # the palette names it does define. green/teal/mauve are role-resolved by # udt-palette, so they still follow the scheme. for pair in "SUCCESS:green" "WARNING:warning" "CRITICAL:critical" \ "INFO:teal" "ACCENT:mauve" "FAINT:overlay0"; do var="${pair%%:*}" raw="$(css_color "${pair##*:}")" [ -n "$raw" ] && printf 'DOT_%s="%s"\n' "$var" "$(to_hex "$var" "$raw")" done } > "$target/dots.colors" # ------------------------------------------------------------------ files -- # Config and modules are symlinked: this repo owns them outright, so linking # means the installed bar cannot drift from what is committed. # # Links whose source has gone are pruned first. Linking alone never removes # anything, so a module renamed or dropped in the repo would otherwise leave a # dangling link behind for every later install to step over. find "$target" -xtype l -delete 2>/dev/null || true ln -sfn "$repo/config.jsonc" "$target/config.jsonc" for f in modules/clock.jsonc \ modules/hyprland/workspaces.jsonc \ modules/custom/vmdot.jsonc modules/custom/privacy_dots.jsonc \ modules/custom/presentation.jsonc modules/custom/mail.jsonc \ modules/custom/launcher.jsonc \ modules/extras/tray.jsonc \ modules/image/volume.jsonc modules/image/language.jsonc; do ln -sfn "$repo/$f" "$target/$f" done for f in style.css fonts.css global.css pills.css; do ln -sfn "$repo/styles/$f" "$target/styles/$f" done # modules.css is generated rather than linked: it carries absolute icon paths, # which cannot be committed, and the accent-tinted launcher. # # Each @ICON:name@ is resolved by wb-icon, which reads the desktop's icon theme # from gsettings. Resolving per name rather than substituting one directory is # what makes a theme switch work at all: themes disagree about both the # subdirectory and the file extension (Suru keeps web-browser at # categories/22/*.svg, elementary-xfce at apps/22/*.png), so only a real icon # lookup knows the path. An unresolved name is left as-is and reported; the # selftest below is what turns that into a failed install. sed -e "s|@CONFIG@|$target|g" \ "$repo/styles/modules.css" > "$target/styles/modules.css" for name in $(grep -o '@ICON:[a-z0-9-]*@' "$target/styles/modules.css" \ | sed 's/@ICON:\(.*\)@/\1/' | sort -u); do if path="$("$repo/bin/wb-icon" --path "$name")"; then sed -i "s|@ICON:$name@|$path|g" "$target/styles/modules.css" else echo "warning: no icon named '$name' in the current icon theme" >&2 fi done # taskbar.jsonc names the icon theme, which is gsettings' to say, so it is # generated for the same reason modules.css is. Every other module is a symlink. # An earlier install symlinked this file into the repo. Writing through that # link would overwrite the committed source with a generated copy, so the link # is removed first; the redirect below then creates a real file. rm -f "$target/modules/extras/taskbar.jsonc" sed "s|@ICON_THEME@|$("$repo/bin/wb-icon" --theme)|g" \ "$repo/modules/extras/taskbar.jsonc" > "$target/modules/extras/taskbar.jsonc" # The launcher module carries no generated path any more: its mark is a CSS # background, so modules.css owns the paths and the module file is a plain # symlink like every other. # The flags ship as they are; the Slackware mark is monochrome, so it is # tinted here, twice. The pill inverts on hover, so the mark has to invert # with it: dark on the accent pill at rest, light on the dark pill hovered. # One mark and one pill colour would always collide in one of the two states, # which is exactly what shipped twice before this. mark_dark="$(sed -n 's/^@define-color main-bg *\(.*\);$/\1/p' "$target/styles/theme.css" | head -1)" mark_light="$(sed -n 's/^@define-color main-fg *\(.*\);$/\1/p' "$target/styles/theme.css" | head -1)" mark_dark="${mark_dark:-#24273a}" mark_light="${mark_light:-#cad3f5}" sed "s|@ACCENT@|$mark_dark|" "$repo/icons/slackware.svg" > "$target/slackware.svg" sed "s|@MARK_LIGHT@|$mark_light|" "$repo/icons/slackware-light.svg" > "$target/slackware-light.svg" install -Dm644 "$repo/icons/flag-it.svg" "$target/flag-it.svg" install -Dm644 "$repo/icons/burger.svg" "$target/burger.svg" # Files an earlier install generated that nothing references any more. The # prune above only clears dangling SYMLINKS, and these were written as real # files, so nothing else removes them: the UK flag the hamburger replaced, and # the launcher from when it was an image module. rm -f "$target/flag-gb.svg" "$target/modules/image/launcher.jsonc" # ---------------------------------------------------------------- scripts -- # The two dot scripts used to live only in ~/bin, in no repository at all. # They are this repo's now, and ~/bin gets links. Any real file found there is # kept: it is the only copy of whatever was running before. for s in vms_dots.sh privacy_dots.sh; do if [ -f "$HOME/bin/$s" ] && [ ! -L "$HOME/bin/$s" ]; then mv "$HOME/bin/$s" "$HOME/bin/$s.pre-udt" echo "kept your $s as ~/bin/$s.pre-udt" fi ln -sfn "$repo/bin/$s" "$HOME/bin/$s" done ln -sfn "$repo/bin/wb-icon" "$HOME/bin/wb-icon" ln -sfn "$repo/bin/wb-lang" "$HOME/bin/wb-lang" # ----------------------------------------------------------------- checks -- # A missing icon renders as an empty pill and nothing says why, so the names # are checked here, while someone is watching. The theme is whatever gsettings # says, so this also catches a switch to a theme that lacks one of these names. echo "icon theme: $("$repo/bin/wb-icon" --theme)" "$repo/bin/wb-icon" --selftest echo echo "installed to $target" echo "run it with: waybar -c $target/config.jsonc -s $target/styles/style.css" echo "hyprland starts it on login; see ~/.config/hypr/sections/autostart.lua"