201 lines
10 KiB
Bash
Executable File
201 lines
10 KiB
Bash
Executable File
#!/bin/bash
|
|
# tui-install.sh — TUI installer for the_miro's Arch dotfiles
|
|
|
|
set -uo pipefail
|
|
|
|
# ── Paths ─────────────────────────────────────────────────────────────────────
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
DOTFILES_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
MODULES="$DOTFILES_DIR/setup/modules"
|
|
LOG="$HOME/dotfiles-install.log"
|
|
TMP_D="$(mktemp -d)"
|
|
trap 'rm -rf "$TMP_D"' EXIT
|
|
|
|
BACKTITLE="the_miro's Arch Dotfiles"
|
|
|
|
# ── Cyberqueer dialog theme ───────────────────────────────────────────────────
|
|
export DIALOGRC="$TMP_D/dialogrc"
|
|
cat > "$DIALOGRC" <<'EOF'
|
|
use_shadow = ON
|
|
use_colors = ON
|
|
screen_color = (BLACK,BLACK,ON)
|
|
shadow_color = (BLACK,BLACK,ON)
|
|
title_color = (MAGENTA,BLACK,ON)
|
|
border_color = (MAGENTA,BLACK,ON)
|
|
button_active_color = (BLACK,MAGENTA,ON)
|
|
button_inactive_color = (WHITE,BLACK,OFF)
|
|
button_key_active_color = (BLACK,CYAN,ON)
|
|
button_key_inactive_color = (CYAN,BLACK,ON)
|
|
button_label_active_color = (BLACK,MAGENTA,ON)
|
|
button_label_inactive_color = (WHITE,BLACK,OFF)
|
|
inputbox_color = (WHITE,BLACK,OFF)
|
|
inputbox_border_color = (MAGENTA,BLACK,ON)
|
|
menubox_color = (WHITE,BLACK,OFF)
|
|
menubox_border_color = (MAGENTA,BLACK,ON)
|
|
item_color = (WHITE,BLACK,OFF)
|
|
item_selected_color = (BLACK,MAGENTA,ON)
|
|
tag_color = (CYAN,BLACK,ON)
|
|
tag_selected_color = (BLACK,CYAN,ON)
|
|
tag_key_color = (CYAN,BLACK,ON)
|
|
tag_key_selected_color = (BLACK,CYAN,ON)
|
|
check_color = (WHITE,BLACK,OFF)
|
|
check_selected_color = (BLACK,MAGENTA,ON)
|
|
uarrow_color = (MAGENTA,BLACK,ON)
|
|
darrow_color = (MAGENTA,BLACK,ON)
|
|
EOF
|
|
|
|
# ── State ─────────────────────────────────────────────────────────────────────
|
|
STEP=0
|
|
TOTAL=0
|
|
|
|
# ── Helpers ───────────────────────────────────────────────────────────────────
|
|
require_dialog() {
|
|
command -v dialog &>/dev/null && return
|
|
echo "dialog not found — installing..."
|
|
sudo pacman -S --noconfirm dialog || { echo "Failed to install dialog."; exit 1; }
|
|
}
|
|
|
|
die() {
|
|
clear
|
|
printf "\n Error: %s\n\n" "$1" >&2
|
|
exit 1
|
|
}
|
|
|
|
log_sep() {
|
|
printf "\n══════════════════════════════════\n %s\n %s\n" "$1" "$(date)" >> "$LOG"
|
|
}
|
|
|
|
# Run a module script in the terminal (dialog is cleared so stdin/stdout work
|
|
# normally — pacman prompts, yay builds, etc. all function as expected).
|
|
run_module() {
|
|
local label="$1" script="$2"
|
|
STEP=$(( STEP + 1 ))
|
|
log_sep "[$STEP/$TOTAL] $label"
|
|
|
|
clear
|
|
printf "\n\033[1;35m [$STEP/$TOTAL] %s\033[0m\n" "$label"
|
|
printf "\033[35m ─────────────────────────────────────────────\033[0m\n\n"
|
|
|
|
local rc=0
|
|
bash "$script" 2>&1 | tee -a "$LOG" || rc=${PIPESTATUS[0]}
|
|
|
|
if [[ $rc -ne 0 ]]; then
|
|
dialog --backtitle "$BACKTITLE" \
|
|
--title " Module Failed " \
|
|
--yesno "$label exited with code $rc.\n\nContinue anyway?" 8 54 \
|
|
|| { clear; exit 1; }
|
|
fi
|
|
}
|
|
|
|
count_steps() {
|
|
local c="$1" de="$2"
|
|
TOTAL=0
|
|
[[ "$c" == *"pkg"* ]] && TOTAL=$(( TOTAL + 1 ))
|
|
[[ "$c" == *"core"* ]] && TOTAL=$(( TOTAL + 1 ))
|
|
[[ "$c" == *"svc"* ]] && TOTAL=$(( TOTAL + 1 ))
|
|
[[ "$c" == *"shell"* ]] && TOTAL=$(( TOTAL + 1 ))
|
|
[[ "$c" == *"de"* && "$de" != "none" ]] && TOTAL=$(( TOTAL + 1 ))
|
|
[[ "$c" == *"py"* ]] && TOTAL=$(( TOTAL + 1 ))
|
|
[[ "$c" == *"zfs"* ]] && TOTAL=$(( TOTAL + 1 ))
|
|
[[ "$c" == *"game"* ]] && TOTAL=$(( TOTAL + 1 ))
|
|
[[ "$c" == *"netdev"* ]] && TOTAL=$(( TOTAL + 1 ))
|
|
[[ "$c" == *"wprs"* ]] && TOTAL=$(( TOTAL + 1 ))
|
|
}
|
|
|
|
# ── Preflight ─────────────────────────────────────────────────────────────────
|
|
[[ $EUID -eq 0 ]] && die "Run as your normal user (not root)."
|
|
command -v pacman &>/dev/null || die "pacman not found — Arch Linux required."
|
|
|
|
require_dialog
|
|
|
|
> "$LOG"
|
|
printf "Dotfiles install: %s\nDotfiles dir: %s\n" "$(date)" "$DOTFILES_DIR" >> "$LOG"
|
|
|
|
# ── Welcome ───────────────────────────────────────────────────────────────────
|
|
dialog --backtitle "$BACKTITLE" \
|
|
--title " Welcome " \
|
|
--msgbox "\n\
|
|
the_miro's Arch dotfiles installer\n\
|
|
Cyberqueer · Wayland · Hyprland\n\
|
|
─────────────────────────────────────────\n\
|
|
\n\
|
|
Arch Linux — network admin, development & gaming\n\
|
|
\n\
|
|
Source: $DOTFILES_DIR\n\
|
|
Log: $LOG\n" 14 62
|
|
|
|
# ── Component selection ───────────────────────────────────────────────────────
|
|
COMPONENTS=$(dialog --backtitle "$BACKTITLE" \
|
|
--title " Select Components " \
|
|
--checklist "Space toggles · Enter confirms · Esc quits" 22 68 10 \
|
|
"pkg" "Package managers yay · nvm · rust" on \
|
|
"core" "Core packages 100+ base system packages" on \
|
|
"svc" "Core services NetworkManager · cronie · fail2ban" on \
|
|
"shell" "Shell setup zsh · nvim · yazi · micro · starship" on \
|
|
"de" "Desktop environment (choose on next screen)" off \
|
|
"py" "Python tools pyright · pipx · python-pynvim" off \
|
|
"zfs" "ZFS support zfs-dkms" off \
|
|
"game" "Gaming Steam · Vesktop · Spotify · Prism" off \
|
|
"netdev" "Network dev tools nmap · wireshark · kubectl" off \
|
|
"wprs" "WPRS wprs-git (AUR)" off \
|
|
3>&1 1>&2 2>&3) || { clear; echo "Aborted."; exit 0; }
|
|
|
|
# ── DE selection ──────────────────────────────────────────────────────────────
|
|
DE="none"
|
|
if [[ "$COMPONENTS" == *"de"* ]]; then
|
|
DE=$(dialog --backtitle "$BACKTITLE" \
|
|
--title " Desktop Environment " \
|
|
--menu "Select a desktop environment:" 11 56 3 \
|
|
"hyprland" "Hyprland — Wayland WM, full setup (primary)" \
|
|
"sway" "Sway — Wayland tiling WM" \
|
|
"none" "Skip DE installation" \
|
|
3>&1 1>&2 2>&3) || DE="none"
|
|
fi
|
|
|
|
# ── Confirmation ──────────────────────────────────────────────────────────────
|
|
SUMMARY=""
|
|
[[ "$COMPONENTS" == *"pkg"* ]] && SUMMARY+=" ✦ Package managers (yay, nvm, rust)\n"
|
|
[[ "$COMPONENTS" == *"core"* ]] && SUMMARY+=" ✦ Core packages\n"
|
|
[[ "$COMPONENTS" == *"svc"* ]] && SUMMARY+=" ✦ Core services\n"
|
|
[[ "$COMPONENTS" == *"shell"* ]] && SUMMARY+=" ✦ Shell setup\n"
|
|
[[ "$COMPONENTS" == *"de"* && "$DE" != "none" ]] && SUMMARY+=" ✦ Desktop environment: $DE\n"
|
|
[[ "$COMPONENTS" == *"py"* ]] && SUMMARY+=" ✦ Python tools\n"
|
|
[[ "$COMPONENTS" == *"zfs"* ]] && SUMMARY+=" ✦ ZFS support\n"
|
|
[[ "$COMPONENTS" == *"game"* ]] && SUMMARY+=" ✦ Gaming packages\n"
|
|
[[ "$COMPONENTS" == *"netdev"* ]] && SUMMARY+=" ✦ Network dev tools\n"
|
|
[[ "$COMPONENTS" == *"wprs"* ]] && SUMMARY+=" ✦ WPRS\n"
|
|
|
|
dialog --backtitle "$BACKTITLE" \
|
|
--title " Confirm Installation " \
|
|
--yesno "\n Components to install:\n\n${SUMMARY}\n Log: $LOG\n\n Proceed?" \
|
|
20 62 || { clear; echo "Aborted."; exit 0; }
|
|
|
|
count_steps "$COMPONENTS" "$DE"
|
|
|
|
# ── Installation ──────────────────────────────────────────────────────────────
|
|
[[ "$COMPONENTS" == *"pkg"* ]] && run_module "Package Managers" "$MODULES/package-managers.sh"
|
|
[[ "$COMPONENTS" == *"core"* ]] && run_module "Core Packages" "$MODULES/core-packages.sh"
|
|
[[ "$COMPONENTS" == *"svc"* ]] && run_module "Core Services" "$MODULES/core.sh"
|
|
[[ "$COMPONENTS" == *"shell"* ]] && run_module "Shell Setup" "$MODULES/shell-setup.sh"
|
|
|
|
if [[ "$COMPONENTS" == *"de"* && "$DE" != "none" ]]; then
|
|
case "$DE" in
|
|
hyprland) run_module "Hyprland" "$MODULES/Desktop-Enviroments/hyprland-new.sh" ;;
|
|
sway) run_module "Sway" "$MODULES/Desktop-Enviroments/sway.sh" ;;
|
|
esac
|
|
fi
|
|
|
|
[[ "$COMPONENTS" == *"py"* ]] && run_module "Python Tools" "$MODULES/optional-Modules/python.sh"
|
|
[[ "$COMPONENTS" == *"zfs"* ]] && run_module "ZFS" "$MODULES/optional-Modules/zfs.sh"
|
|
[[ "$COMPONENTS" == *"game"* ]] && run_module "Gaming Packages" "$MODULES/optional-Modules/gaming-packages.sh"
|
|
[[ "$COMPONENTS" == *"netdev"* ]] && run_module "Network Dev Tools" "$MODULES/optional-Modules/network-developer-packages.sh"
|
|
[[ "$COMPONENTS" == *"wprs"* ]] && run_module "WPRS" "$MODULES/optional-Modules/wprs.sh"
|
|
|
|
# ── Done ──────────────────────────────────────────────────────────────────────
|
|
dialog --backtitle "$BACKTITLE" \
|
|
--title " Done " \
|
|
--msgbox "\n All selected components installed.\n\n Log: $LOG\n\n A reboot may be required for all changes to take effect.\n" 12 58
|
|
|
|
clear
|
|
printf "\n Done. Log: %s\n\n" "$LOG"
|