Package sections: always-on + advanced menu #3

Merged
yuri merged 2 commits from feat/package-sections into main 2026-10-27 13:57:40 +01:00
Showing only changes of commit 5b7ed5ede9 - Show all commits
+158 -1
View File
@@ -395,7 +395,164 @@ fi
#------------------------------------------
# 6 Done
#------------------------------------------
step "7 Summary"
#------------------------------------------
# 6 Always-installed packages
#------------------------------------------
# Add a category here and it is installed on every run, no questions asked.
# Keep each category one line so diffs stay readable.
ALWAYS_PACKAGES=(
# Terminals
"ghostty ghostty-bash-completion"
)
step "6 Always-installed packages"
rule
for category in "${ALWAYS_PACKAGES[@]}"; do
# shellcheck disable=SC2086
install_packages $category
done
ok "Always-packages installed."
pause_if_debug
#------------------------------------------
# 7 Advanced: optional tool selection (menu-driven)
#------------------------------------------
# Add categories/apps by editing these parallel arrays:
# ADV_CATEGORIES : display order
# ADV_<NAME> : "pkg1 pkg2 ..." for each category (dots/minus -> underscore)
ADV_CATEGORIES=(
"Virtualisation"
"Browsers"
)
# shellcheck disable=SC2034 # arrays are read via nameref from ADV_CATEGORIES
ADV_Virtualisation=(
"qemu-kvm:QEMU/KVM (full virt stack):qemu-kvm libvirt virt-install virt-manager virt-viewer edk2-ovmf swtpm guestfs-tools libguestfs-tools"
"virtualbox:VirtualBox (Oracle):VirtualBox kernel-devel kernel-headers dkms akmod-VirtualBox"
)
# shellcheck disable=SC2034 # arrays are read via nameref from ADV_CATEGORIES
ADV_Browsers=(
"firefox:Firefox:firefox"
"chromium:Chromium:chromium"
"google-chrome:Google Chrome (adds repo):google-chrome-stable"
"brave:Brave (adds repo):brave-browser"
)
run_advanced_menu() {
local done_any=false
while true; do
printf "\n"
color_gray "Optional tools - select a category to pick from:"
printf "\n"
local i=1 cat
for cat in "${ADV_CATEGORIES[@]}"; do
echo " $i) $cat"
i=$((i+1))
done
echo " x) Done with optional tools"
local choice
if ! read -t 90 -rp "Category [1-${#ADV_CATEGORIES[@]}/x] (default: x): " choice; then
printf "\n"; choice="x"
fi
[[ "${choice,,}" == "x" || -z "$choice" ]] && break
if [[ ! "$choice" =~ ^[0-9]+$ ]] || (( choice < 1 || choice > ${#ADV_CATEGORIES[@]} )); then
err "Invalid choice: $choice"
continue
fi
cat="${ADV_CATEGORIES[$((choice-1))]}"
# apps for this category — nameref, because ${!var} on an array name
# would only give element 0 (that bug showed in testing: Browsers
# listed exactly one entry)
local var="ADV_${cat//[ .-]/_}"
local -n entries_ref="$var"
local -a entries
# shellcheck disable=SC2206
entries=("${entries_ref[@]}")
printf "\n"
color_cyan "$cat:"
local j=1 entry
local -a ids=() labels=()
for entry in "${entries[@]}"; do
ids+=("${entry%%:*}") # entry id
local rest="${entry#*:}"
labels+=("${rest%%:*}") # display label
echo " $j) ${labels[-1]}"
j=$((j+1))
done
echo " x) Back"
local sel
if ! read -t 90 -rp "Install which? (comma-separate for multiple, default: back): " sel; then
printf "\n"; continue
fi
[[ "${sel,,}" == "x" || -z "$sel" ]] && continue
# Resolve picks to package lists. Entry format: id:Label:packages...
local -a to_install=()
local pick n rest
IFS=',' read -ra picks <<< "$sel"
for pick in "${picks[@]}"; do
pick="${pick// /}"
[[ "$pick" =~ ^[0-9]+$ ]] || { err "Ignoring invalid pick: $pick"; continue; }
n=${#entries[@]}
if (( pick < 1 || pick > n )); then err "Ignoring out-of-range pick: $pick"; continue; fi
entry="${entries[$((pick-1))]}"
rest="${entry#*:}"; rest="${rest#*:}" # drop id and label -> packages
to_install+=("$rest")
done
if (( ${#to_install[@]} > 0 )); then
step "Installing from $cat: ${to_install[*]}"
# Repos for items that need one are handled in install_optional_pkgs below.
install_category_pkgs "$cat" "${to_install[@]}"
done_any=true
fi
done
$done_any && ok "Optional tools installed."
}
# Per-category pre-repo wiring. Add third-party repos here when you add an
# app that needs one; packages alone stay generic.
install_category_pkgs() {
local cat="$1"; shift
case "$cat" in
Browsers)
local needs_chrome=false needs_brave=false item
for item in "$@"; do
[[ "$item" == *google-chrome* ]] && needs_chrome=true
[[ "$item" == *brave* ]] && needs_brave=true
done
if $needs_chrome && ! pkg_installed google-chrome-stable; then
info "Adding Google Chrome repo..."
sudo dnf install -y fedora-workstation-repositories 2>/dev/null || true
sudo dnf config-manager setopt google-chrome.enabled=1 2>/dev/null || \
sudo dnf install -y "https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm"
fi
if $needs_brave && ! pkg_installed brave-browser; then
info "Adding Brave repo..."
sudo dnf install -y dnf-plugins-core
sudo dnf config-manager add --from-repofile=https://brave-browser-rpm-release.s3.brave.com/brave-browser.repo || \
true
sudo rpm --import https://brave-browser-rpm-release.s3.brave.com/brave-core.asc 2>/dev/null || true
fi
;;
esac
install_packages "$@"
}
# Interactive only: an unattended --yes run must not hang on this menu.
# Skip silently there; use --de/--twm/--dotfiles for everything unattended.
if [[ "$ASSUME_YES" != "true" ]]; then
run_advanced_menu
fi
pause_if_debug
step "8 Summary"
rule
ok "DE: $DE"
ok "TWM: $TWM"