From 1e4d2b4be7ad20dd108503fb65c264673ca6457b Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Tue, 29 Sep 2026 09:55:45 +0200 Subject: feat(install): track rofi scripts, wire nvim and hypr-theme, merge qt/gtk keys The rofi menus' launch scripts lived loose in ~/bin, so the themes were tracked and the only things that open them were not. They now live in bin/ and are symlinked under the names hypr-theme's keybindings call. neovim gets a generated colorscheme: catppuccin/nvim with all 26 palette colours overridden from the active scheme, selected by rewriting only the colorscheme line of init.vim. hypr-theme is linked as the whole of ~/.config/hypr, leaving a real directory there alone. The qt-gtk templates were reference copies nothing installed. They now hold theme keys only and ini_merge writes them into the live qt5ct, qt6ct and gtk3 files key by key, keeping every other line; tests/ini-merge.sh checks it. The stale kvantum.kvconfig template is gone, install.sh writes that file. Fresh-machine fixes: settings.ini and ~/.config/gtk-4.0 are created when missing instead of aborting under set -e, and conky is found as a sibling checkout and skipped when absent, in udt-palette as well as install.sh. Co-Authored-By: Claude Opus 5.5 --- install.sh | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 98 insertions(+), 13 deletions(-) (limited to 'install.sh') diff --git a/install.sh b/install.sh index 36903ea..9626431 100755 --- a/install.sh +++ b/install.sh @@ -9,6 +9,47 @@ target="$HOME/.config/rofi/udt" mkdir -p "$target" "$HOME/bin" "$HOME/.cache/udt" +# Merge an ini template into a live file key by key: every key the template +# sets is written, every other line of the live file is kept as it was. Keys +# missing from a section are appended to it, missing sections to the end. The +# live file is written through rather than replaced, so a symlink survives. +ini_merge() { + local tmpl="$1" live="$2" + mkdir -p "$(dirname "$live")" + [ -e "$live" ] || : > "$live" + awk ' + function flush( i, p) { + for (i = 1; i <= n; i++) { + split(order[i], p, SUBSEP) + if (p[1] == sec && !(order[i] in done)) { print want[order[i]]; done[order[i]] = 1 } + } + for (; blank > 0; blank--) print "" + } + FNR == NR { + if (/^\[/) ts = $0 + else if (/^[^#;].*=/) { k = ts SUBSEP substr($0, 1, index($0, "=") - 1); want[k] = $0; order[++n] = k } + next + } + /^[[:space:]]*$/ { blank++; next } + /^\[/ { flush(); sec = $0; print; next } + { for (; blank > 0; blank--) print "" } + index($0, "=") && ((sec SUBSEP substr($0, 1, index($0, "=") - 1)) in want) { + k = sec SUBSEP substr($0, 1, index($0, "=") - 1) + print want[k]; done[k] = 1; next + } + { print } + END { + flush() + for (i = 1; i <= n; i++) if (!(order[i] in done)) { + split(order[i], p, SUBSEP) + if (!(p[1] in hdr)) { print p[1]; hdr[p[1]] = 1 } + print want[order[i]] + } + }' "$tmpl" "$live" > "$live.udt-tmp" + cat "$live.udt-tmp" > "$live" + rm -f "$live.udt-tmp" +} + # Generate every themed config from the selected scheme first: the rofi palette # symlinked below is one of its outputs, so this has to run before anything is # linked. It fails loudly if a role names a colour the scheme does not define, @@ -61,8 +102,11 @@ fi mkdir -p "$HOME/.cache/wal" ln -sfn "$HOME/.cache/udt/colors.json" "$HOME/.cache/wal/colors.json" -ln -sfn "$repo/bin/udt-accent" "$HOME/bin/udt-accent" -ln -sfn "$repo/bin/udt-palette" "$HOME/bin/udt-palette" +# The rofi menus are bound by name in hypr-theme's keybindings, so they keep +# the names they had when they lived loose in ~/bin. +for f in udt-accent udt-palette udt-powermenu.sh udt-launcher.sh qar-scrotmenu.sh; do + ln -sfn "$repo/bin/$f" "$HOME/bin/$f" +done # The generated configs for everything that is not rofi. These are copied # rather than symlinked: each app owns its config file and mixes theme keys @@ -171,15 +215,43 @@ done # GTK3 reads the theme name from gsettings on Wayland, not settings.ini: the # file is written too, but gsettings is what actually wins. It was once pinned -# to Breeze, silently overriding the file. -sed -i 's/^gtk-theme-name=.*/gtk-theme-name=udt/' "$HOME/.config/gtk-3.0/settings.ini" +# to Breeze, silently overriding the file. Every scheme is dark, so +# prefer-dark is set too; the portal passes it to libadwaita apps. +ini_merge "$repo/templates/qt-gtk/gtk3-settings.ini" "$HOME/.config/gtk-3.0/settings.ini" if command -v gsettings >/dev/null 2>&1; then gsettings set org.gnome.desktop.interface gtk-theme 'udt' 2>/dev/null || true + gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark' 2>/dev/null || true fi # GTK4 ignores gtk-theme-name entirely; its stylesheet is imported by -# ~/.config/gtk-4.0/gtk.css through this symlink. +# ~/.config/gtk-4.0/gtk.css through this symlink. gtk.css is seeded when +# missing, and otherwise only gets the import prepended if it lacks one. +mkdir -p "$HOME/.config/gtk-4.0" ln -sfn "$gtk_theme/gtk-4.0" "$HOME/.config/gtk-4.0/theme" +gtk4_css="$HOME/.config/gtk-4.0/gtk.css" +if [ ! -f "$gtk4_css" ]; then + cp "$repo/templates/qt-gtk/gtk4-gtk.css" "$gtk4_css" +elif ! grep -q '@import url("theme/gtk.css")' "$gtk4_css"; then + { echo '@import url("theme/gtk.css");'; cat "$gtk4_css"; } > "$gtk4_css.udt-tmp" + cat "$gtk4_css.udt-tmp" > "$gtk4_css" + rm -f "$gtk4_css.udt-tmp" +fi + +# qt5ct and qt6ct hand Qt apps to Kvantum. Theme keys only: both files also +# hold settings and personal lists that are none of this repo's business. +ini_merge "$repo/templates/qt-gtk/qt5ct.conf" "$HOME/.config/qt5ct/qt5ct.conf" +ini_merge "$repo/templates/qt-gtk/qt6ct.conf" "$HOME/.config/qt6ct/qt6ct.conf" + +# neovim. The colorscheme is generated, and selected with one line in +# init.vim, rewritten only if it names something else. Like Sublime's +# color_scheme key: the rest of init.vim is none of this repo's business. +mkdir -p "$HOME/.config/nvim/colors" +ln -sfn "$repo/templates/nvim/udt.lua" "$HOME/.config/nvim/colors/udt.lua" +nvim_init="$HOME/.config/nvim/init.vim" +if [ -f "$nvim_init" ] && ! grep -qx 'colorscheme udt' "$nvim_init"; then + sed -i 's/^colorscheme .*/colorscheme udt/' "$nvim_init" + grep -qx 'colorscheme udt' "$nvim_init" && echo "nvim: colorscheme switched to udt" +fi # Obsidian and Typora need more than a copy: the Obsidian snippet has to be # enabled in each vault's appearance.json without disturbing the snippets @@ -192,14 +264,27 @@ ln -sfn "$gtk_theme/gtk-4.0" "$HOME/.config/gtk-4.0/theme" # The Lua dashboard lives in its own repo; udt-palette renders its colours into # conky.conf there. Both the config and the Lua it loads are linked, since # lua_load points at ~/.config/conky/dashboard.lua. -conky_repo="$HOME/Programming/GIT/conky-theme-udt" -mkdir -p "$HOME/.config/conky" -ln -sfn "$conky_repo/conky.conf" "$HOME/.config/conky/conky.conf" -ln -sfn "$conky_repo/dashboard.lua" "$HOME/.config/conky/dashboard.lua" -ln -sfn "$conky_repo/lib" "$HOME/.config/conky/lib" -ln -sfn "$conky_repo/widgets" "$HOME/.config/conky/widgets" -# bin/ holds the weather fetch script, which conky.text runs on an execi. -ln -sfn "$conky_repo/bin" "$HOME/.config/conky/bin" +# A sibling checkout, like waybar-theme-udt, and skipped when absent. +conky_repo="$(realpath -m "$repo/../conky-theme-udt")" +if [ -d "$conky_repo" ]; then + mkdir -p "$HOME/.config/conky" + # bin/ holds the weather fetch script, which conky.text runs on an execi. + for f in conky.conf dashboard.lua lib widgets bin; do + ln -sfn "$conky_repo/$f" "$HOME/.config/conky/$f" + done +fi + +# Hyprland. hypr-theme is the whole of ~/.config/hypr, linked as one +# directory, and it reads the border this repo generates. A real directory +# there is someone's config: it is left alone rather than replaced. +hypr_repo="$(realpath -m "$repo/../hypr-theme")" +if [ -d "$hypr_repo" ]; then + if [ -L "$HOME/.config/hypr" ] || [ ! -e "$HOME/.config/hypr" ]; then + ln -sfn "$hypr_repo" "$HOME/.config/hypr" + elif [ "$(realpath "$HOME/.config/hypr")" != "$hypr_repo" ]; then + echo "hypr: ~/.config/hypr is a real directory, left alone; move it aside to link hypr-theme" >&2 + fi +fi # Reload what is running. Writing the configs is not enough: waybar, kitty and # Hyprland reread on a signal, conky only on a restart, and rofi -- cgit v1.2.3