GTK4 ignores gtk-application-prefer-dark-theme, and did not follow the portal's prefer-dark either, so Adwaita stayed light while the custom css darkened only some surfaces - that is why pavucontrol had dark-grey labels on dark backgrounds and a white content pane. GTK_THEME=Adwaita:dark fixes GTK3 and GTK4 together. Also recolour the stale ~/.themes Terminal-Dark leftovers, point gtk-4.0 at a theme and icon set that exist, and start the particle layer from bspwmrc. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Cn3dHfbgNYdbZvzb1b3GQt
242 lines
10 KiB
Bash
Executable file
242 lines
10 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
#
|
|
# Sakura Line - one-shot rice bootstrap.
|
|
#
|
|
# bash <(curl -fsSL https://git.srtk.in/sarthak/dotfiles/raw/branch/main/.config/rice/install.sh)
|
|
#
|
|
# or, from a clone: ~/.config/rice/install.sh
|
|
#
|
|
# Arch is the first-class target. Debian/Ubuntu and Fedora are best-effort:
|
|
# the desktop and build steps work, the AUR extras are skipped.
|
|
#
|
|
# Safe to re-run. Nothing in $HOME is overwritten without a backup first.
|
|
|
|
set -uo pipefail
|
|
|
|
DOTS_REMOTE="${DOTS_REMOTE:-https://git.srtk.in/sarthak/dotfiles.git}"
|
|
ST_REMOTE="${ST_REMOTE:-https://github.com/siduck/st}"
|
|
DOTS_DIR="$HOME/.dotfiles"
|
|
RICE_DIR="$HOME/.config/rice"
|
|
SRC_DIR="${SRC_DIR:-$HOME/gitclone}"
|
|
BACKUP="$HOME/.rice-backup-$(date +%Y%m%d-%H%M%S)"
|
|
STEPS_FAILED=()
|
|
DRY=0
|
|
for a in "$@"; do
|
|
case "$a" in
|
|
-n|--dry-run) DRY=1 ;;
|
|
-h|--help)
|
|
sed -n '2,14p' "$0" | sed 's/^#\s\?//'
|
|
printf '\nOptions:\n -n, --dry-run show what would happen, change nothing\n -h, --help this text\n\n'
|
|
exit 0 ;;
|
|
*) printf 'unknown option: %s (try --help)\n' "$a"; exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
c_hd=$'\e[1;38;5;111m'; c_ok=$'\e[38;5;108m'; c_wa=$'\e[38;5;179m'
|
|
c_er=$'\e[38;5;168m'; c_dim=$'\e[38;5;103m'; c_off=$'\e[0m'
|
|
say() { printf '%s==>%s %s\n' "$c_hd" "$c_off" "$*"; }
|
|
# every mutating command goes through this so --dry-run is honest
|
|
run() { if [ "$DRY" = 1 ]; then printf ' %s$ %s%s\n' "$c_dim" "$*" "$c_off"; else "$@"; fi; }
|
|
ok() { printf ' %s+%s %s\n' "$c_ok" "$c_off" "$*"; }
|
|
warn() { printf ' %s!%s %s\n' "$c_wa" "$c_off" "$*"; }
|
|
die() { printf ' %sx%s %s\n' "$c_er" "$c_off" "$*"; exit 1; }
|
|
note() { printf ' %s%s%s\n' "$c_dim" "$*" "$c_off"; }
|
|
fail_step() { STEPS_FAILED+=("$1"); printf ' %sx%s %s\n' "$c_er" "$c_off" "$1"; }
|
|
|
|
[ "$(id -u)" -eq 0 ] && die "run this as your normal user, not root (it uses sudo where needed)"
|
|
|
|
# ---------------------------------------------------------------- distro
|
|
PM=""; AUR=""
|
|
if command -v pacman >/dev/null 2>&1; then PM=pacman
|
|
elif command -v apt-get >/dev/null 2>&1; then PM=apt
|
|
elif command -v dnf >/dev/null 2>&1; then PM=dnf
|
|
else warn "no supported package manager found; skipping installs"; PM=none
|
|
fi
|
|
PM_LINE="package manager: ${PM}"
|
|
|
|
# Package names differ per distro; this maps the ones that actually differ.
|
|
map_pkg() {
|
|
local p="$1"
|
|
case "$PM" in
|
|
apt) case "$p" in
|
|
base-devel) echo "build-essential" ;;
|
|
pkgconf) echo "pkg-config" ;;
|
|
libx11) echo "libx11-dev" ;;
|
|
libxext) echo "libxext-dev" ;;
|
|
libxft) echo "libxft-dev" ;;
|
|
libxrandr) echo "libxrandr-dev" ;;
|
|
libxfixes) echo "libxfixes-dev" ;;
|
|
libxinerama) echo "libxinerama-dev" ;;
|
|
cairo) echo "libcairo2-dev" ;;
|
|
harfbuzz) echo "libharfbuzz-dev" ;;
|
|
fontconfig) echo "libfontconfig1-dev" ;;
|
|
freetype2) echo "libfreetype6-dev" ;;
|
|
gd) echo "libgd-dev" ;;
|
|
xorg-xrandr) echo "x11-xserver-utils" ;;
|
|
xorg-xprop) echo "x11-utils" ;;
|
|
ttf-jetbrains-mono-nerd) echo "fonts-jetbrains-mono" ;;
|
|
noto-fonts) echo "fonts-noto" ;;
|
|
noto-fonts-emoji) echo "fonts-noto-color-emoji" ;;
|
|
papirus-icon-theme) echo "papirus-icon-theme" ;;
|
|
qt6ct) echo "qt6ct" ;;
|
|
*) echo "$p" ;;
|
|
esac ;;
|
|
dnf) case "$p" in
|
|
base-devel) echo "@development-tools" ;;
|
|
pkgconf) echo "pkgconf-pkg-config" ;;
|
|
libx11) echo "libX11-devel" ;;
|
|
libxext) echo "libXext-devel" ;;
|
|
libxft) echo "libXft-devel" ;;
|
|
libxrandr) echo "libXrandr-devel" ;;
|
|
libxfixes) echo "libXfixes-devel" ;;
|
|
libxinerama) echo "libXinerama-devel" ;;
|
|
cairo) echo "cairo-devel" ;;
|
|
harfbuzz) echo "harfbuzz-devel" ;;
|
|
fontconfig) echo "fontconfig-devel" ;;
|
|
freetype2) echo "freetype-devel" ;;
|
|
gd) echo "gd-devel" ;;
|
|
xorg-xrandr) echo "xrandr" ;;
|
|
xorg-xprop) echo "xprop" ;;
|
|
ttf-jetbrains-mono-nerd) echo "jetbrains-mono-fonts" ;;
|
|
noto-fonts) echo "google-noto-sans-fonts" ;;
|
|
noto-fonts-emoji) echo "google-noto-emoji-fonts" ;;
|
|
*) echo "$p" ;;
|
|
esac ;;
|
|
*) echo "$p" ;;
|
|
esac
|
|
}
|
|
|
|
install_packages() {
|
|
[ "$PM" = none ] && { warn "skipping package install"; return 0; }
|
|
local list="$RICE_DIR/packages.txt" repo=() aur=() line pkg
|
|
[ -f "$list" ] || { warn "packages.txt not found, skipping"; return 0; }
|
|
|
|
while IFS= read -r line; do
|
|
line="${line%%#*}"; line="$(echo "$line" | tr -d '[:space:]')"
|
|
[ -z "$line" ] && continue
|
|
if [[ "$line" == aur:* ]]; then aur+=("${line#aur:}")
|
|
else repo+=("$(map_pkg "$line")"); fi
|
|
done < "$list"
|
|
|
|
say "installing ${#repo[@]} packages"
|
|
case "$PM" in
|
|
pacman) run sudo pacman -S --needed --noconfirm "${repo[@]}" || fail_step "some packages failed" ;;
|
|
apt) run sudo apt-get update -qq && run sudo apt-get install -y "${repo[@]}" || fail_step "some packages failed" ;;
|
|
dnf) run sudo dnf install -y "${repo[@]}" || fail_step "some packages failed" ;;
|
|
esac
|
|
|
|
if [ "$PM" = pacman ] && [ "${#aur[@]}" -gt 0 ]; then
|
|
local helper=""
|
|
for h in paru yay pikaur; do command -v "$h" >/dev/null 2>&1 && { helper="$h"; break; }; done
|
|
if [ -z "$helper" ]; then
|
|
warn "no AUR helper; skipping: ${aur[*]}"
|
|
note "install paru, then re-run to get them"
|
|
else
|
|
say "installing ${#aur[@]} AUR packages with $helper"
|
|
run "$helper" -S --needed --noconfirm "${aur[@]}" || fail_step "some AUR packages failed"
|
|
fi
|
|
elif [ "${#aur[@]}" -gt 0 ]; then
|
|
warn "not Arch; skipping AUR extras: ${aur[*]}"
|
|
fi
|
|
}
|
|
|
|
# ------------------------------------------------------------- dotfiles
|
|
dot() { git --git-dir="$DOTS_DIR" --work-tree="$HOME" "$@"; }
|
|
|
|
deploy_dotfiles() {
|
|
if [ -d "$DOTS_DIR" ]; then
|
|
ok "dotfiles repo already present"
|
|
else
|
|
say "cloning dotfiles"
|
|
run git clone --bare "$DOTS_REMOTE" "$DOTS_DIR" || { fail_step "dotfiles clone"; return 1; }
|
|
fi
|
|
run dot config status.showUntrackedFiles no
|
|
if [ "$DRY" = 1 ]; then note "would checkout main into \$HOME (backing up conflicts)"; return 0; fi
|
|
|
|
# Move anything that would be clobbered into a backup instead of losing it.
|
|
mkdir -p "$BACKUP"
|
|
local conflicts
|
|
conflicts="$(dot checkout main 2>&1 | grep -oP '^\s+\K\S+\.\S+$' || true)"
|
|
if [ -n "$conflicts" ]; then
|
|
say "backing up files that would be overwritten -> $BACKUP"
|
|
while IFS= read -r f; do
|
|
[ -z "$f" ] && continue
|
|
[ -e "$HOME/$f" ] || continue
|
|
mkdir -p "$BACKUP/$(dirname "$f")"
|
|
mv "$HOME/$f" "$BACKUP/$f" && note "$f"
|
|
done <<< "$conflicts"
|
|
dot checkout main || { fail_step "dotfiles checkout"; return 1; }
|
|
fi
|
|
rmdir "$BACKUP" 2>/dev/null
|
|
ok "dotfiles deployed"
|
|
}
|
|
|
|
# --------------------------------------------------------------- builds
|
|
build_st() {
|
|
command -v gcc >/dev/null 2>&1 || { warn "no compiler; skipping st"; return 0; }
|
|
mkdir -p "$SRC_DIR"
|
|
if [ ! -d "$SRC_DIR/st/.git" ]; then
|
|
say "cloning st"
|
|
run git clone --depth 1 "$ST_REMOTE" "$SRC_DIR/st" || { fail_step "st clone"; return 1; }
|
|
fi
|
|
# config.h is gitignored upstream, so the rice bundle carries ours
|
|
run cp "$RICE_DIR/st/config.h" "$SRC_DIR/st/config.h" || { fail_step "st config"; return 1; }
|
|
say "building st"
|
|
run bash -c 'cd "$1" && make clean >/dev/null 2>&1; make' _ "$SRC_DIR/st" || { fail_step "st build"; return 1; }
|
|
run bash -c 'cd "$1" && sudo make install' _ "$SRC_DIR/st" || { fail_step "st install"; return 1; }
|
|
ok "st installed"
|
|
}
|
|
|
|
build_particles() {
|
|
command -v gcc >/dev/null 2>&1 || { warn "no compiler; skipping particles"; return 0; }
|
|
pkg-config --exists cairo x11 xext xfixes xrandr 2>/dev/null || {
|
|
warn "cairo/X11 dev headers missing; skipping particles"; return 0; }
|
|
say "building particles"
|
|
run bash -c 'cd "$1" && make clean >/dev/null 2>&1; make' _ "$RICE_DIR/particles" || { fail_step "particles build"; return 1; }
|
|
run bash -c 'cd "$1" && sudo make install' _ "$RICE_DIR/particles" || { fail_step "particles install"; return 1; }
|
|
ok "particles installed (run 'particles' to toggle)"
|
|
}
|
|
|
|
# ---------------------------------------------------------------- setup
|
|
post_setup() {
|
|
say "post-setup"
|
|
chmod +x "$HOME"/.config/bspwm/bspwmrc 2>/dev/null
|
|
chmod +x "$HOME"/.config/polybar/launch.sh 2>/dev/null
|
|
chmod +x "$HOME"/.config/scripts/*.sh 2>/dev/null
|
|
chmod +x "$HOME"/.config/scripts/rofi-menus/*.sh 2>/dev/null
|
|
chmod +x "$HOME"/.config/rice/install.sh 2>/dev/null
|
|
[ "$DRY" = 1 ] && { note "would fix permissions, rebuild fonts, set wallpaper"; return 0; }
|
|
command -v fc-cache >/dev/null 2>&1 && fc-cache -f >/dev/null 2>&1 && ok "font cache rebuilt"
|
|
|
|
if command -v gsettings >/dev/null 2>&1; then
|
|
gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark' 2>/dev/null \
|
|
&& ok "gtk colour-scheme set to prefer-dark"
|
|
fi
|
|
if command -v papirus-folders >/dev/null 2>&1; then
|
|
papirus-folders -C blue --theme Papirus-Dark >/dev/null 2>&1 && ok "papirus folders set to blue"
|
|
fi
|
|
if [ -f "$HOME/.config/bspwm/wallpaper/wallpaper.jpg" ] && command -v feh >/dev/null 2>&1; then
|
|
feh --bg-fill "$HOME/.config/bspwm/wallpaper/wallpaper.jpg" >/dev/null 2>&1 && ok "wallpaper set"
|
|
fi
|
|
ok "post-setup done"
|
|
}
|
|
|
|
# ----------------------------------------------------------------- main
|
|
printf '\n%s Sakura Line%s - bspwm rice bootstrap\n\n' "$c_hd" "$c_off"
|
|
say "$PM_LINE"
|
|
[ "$DRY" = 1 ] && say "dry run - nothing will be changed"
|
|
install_packages
|
|
deploy_dotfiles
|
|
build_st
|
|
build_particles
|
|
post_setup
|
|
|
|
printf '\n'
|
|
if [ "${#STEPS_FAILED[@]}" -eq 0 ]; then
|
|
say "done - log out and back into bspwm to pick everything up"
|
|
else
|
|
say "finished with ${#STEPS_FAILED[@]} problem(s):"
|
|
for s in "${STEPS_FAILED[@]}"; do printf ' %s- %s%s\n' "$c_er" "$s" "$c_off"; done
|
|
fi
|
|
printf '\n %sst%s must be reopened to show new colours; %sparticles%s toggles the wallpaper layer.\n\n' \
|
|
"$c_hd" "$c_off" "$c_hd" "$c_off"
|