#!/usr/bin/env bash set -euo pipefail TOOLS_FILE="$(dirname "$0")/tools.yaml" LOGFILE="$(dirname "$0")/quick-install.log" log() { echo "[INFO] $(date '+%F %T') $*" | tee -a "$LOGFILE"; } log_warn() { echo "[WARN] $(date '+%F %T') $*" | tee -a "$LOGFILE"; } log_err() { echo "[ERROR] $(date '+%F %T') $*" | tee -a "$LOGFILE"; } require_tools() { for tool in yq gum; do if ! command -v "$tool" &>/dev/null; then log_err "This script requires '$tool'. Please install it first." exit 1 fi done } get_tools_for_category() { local category="$1" yq e ".${category}[]" "$TOOLS_FILE" } check_and_prepare_install_list() { local category="$1" local install_list=() local ppas_to_add=() # Read each item (YAML block) in the category local length length=$(yq e "length(.${category})" "$TOOLS_FILE") for i in $(seq 0 $((length - 1))); do local name ppa name=$(yq e ".${category}[$i].name" "$TOOLS_FILE") ppa=$(yq e ".${category}[$i].ppa // \"\"" "$TOOLS_FILE") if ! command -v "$name" &>/dev/null; then install_list+=("$name") if [[ -n "$ppa" ]]; then ppas_to_add+=("$ppa") fi fi done # Remove duplicate PPAs mapfile -t ppas_to_add < <(printf '%s\n' "${ppas_to_add[@]}" | sort -u) echo "${install_list[*]}" echo "${ppas_to_add[*]}" } install_category() { local category="$1" log "Processing category: $category" read -r -a to_install ppas < <(check_and_prepare_install_list "$category") if [[ ${#to_install[@]} -eq 0 ]]; then log "All tools in '$category' are already installed." return fi # Show the user what will be installed gum style --foreground 212 --bold "Category: $category" gum style --foreground 99 "The following tools will be installed:" printf '%s\n' "${to_install[@]}" | gum format if ! gum confirm "Proceed with installing these tools?"; then log_warn "User declined installation for category: $category" return fi # Add PPAs if any if [[ ${#ppas[@]} -gt 0 ]]; then for ppa in "${ppas[@]}"; do log "Adding PPA: $ppa" sudo add-apt-repository -y "$ppa" done sudo apt update fi log "Installing packages for category: $category" sudo apt install -y "${to_install[@]}" } main() { require_tools log "Starting tool installation from $TOOLS_FILE" # Read all top-level categories from tools.yaml mapfile -t categories < <(yq e 'keys | .[]' "$TOOLS_FILE") # Let user select categories to install selected_categories=$(gum choose --no-limit --header "Select categories to install:" "${categories[@]}") if [[ -z "$selected_categories" ]]; then log_warn "No categories selected. Exiting." exit 0 fi # Loop through selected categories and install while IFS= read -r category; do install_category "$category" done <<< "$selected_categories" log "✅ All done." } main "$@"