#!/usr/bin/env bash setup_powertools() { # 1. INITIALIZATION # ----------------------------------------------------------- set -e # Define all available components declare -A COMPONENTS COMPONENTS=( [core_utils]=1 [rust]=1 [neovim]=1 [zoxide]=1 [bat]=1 [eza]=1 [tealdeer]=1 [fzf]=1 ) # Component descriptions for interactive mode declare -A DESCRIPTIONS DESCRIPTIONS=( [core_utils]="System packages (git, curl, gcc, unzip, xclip, etc)" [rust]="Rust toolchain (rustup & cargo)" [neovim]="Neovim + Kickstart.nvim config (via apt)" [zoxide]="zoxide (smarter cd command)" [bat]="bat (cat clone with syntax highlighting)" [eza]="eza (modern replacement for ls)" [tealdeer]="tealdeer (fast tldr pages)" [fzf]="fzf (command-line fuzzy finder)" ) MODE="default" # default, interactive, only, without ARGS=("$@") # 2. ARGUMENT PARSING # ----------------------------------------------------------- parse_args() { local current_flag="" while [[ $# -gt 0 ]]; do case $1 in -i|--interactive) if [[ "$MODE" == "only" || "$MODE" == "without" ]]; then echo "Error: --interactive cannot be combined with --only or --without." exit 1 fi MODE="interactive" shift ;; --only) if [[ "$MODE" == "interactive" || "$MODE" == "without" ]]; then echo "Error: --only cannot be combined with --interactive or --without." exit 1 fi if [[ "$MODE" != "only" ]]; then for key in "${!COMPONENTS[@]}"; do COMPONENTS[$key]=0; done MODE="only" fi current_flag="only" shift ;; --without) if [[ "$MODE" == "interactive" || "$MODE" == "only" ]]; then echo "Error: --without cannot be combined with --interactive or --only." exit 1 fi MODE="without" current_flag="without" shift ;; -*) echo "Unknown option: $1" exit 1 ;; *) local item=$1 if [[ -z "${COMPONENTS[$item]}" ]]; then echo "Warning: Unknown component '$item'. Valid options: ${!COMPONENTS[*]}" else if [[ "$current_flag" == "only" ]]; then COMPONENTS[$item]=1 elif [[ "$current_flag" == "without" ]]; then COMPONENTS[$item]=0 fi fi shift ;; esac done } parse_args "${ARGS[@]}" # 3. INTERACTIVE PROMPTS # ----------------------------------------------------------- if [[ "$MODE" == "interactive" ]]; then echo "--- Interactive Setup Mode ---" echo "Press Enter to accept [Y] or type 'n' to skip." echo "" for tool in "${!COMPONENTS[@]}"; do read -r -p "Install ${tool} (${DESCRIPTIONS[$tool]})? [Y/n] " response case "$response" in [nN][oO]|[nN]) COMPONENTS[$tool]=0 ;; *) COMPONENTS[$tool]=1 ;; esac done fi # 4. DEPENDENCY CHECK # ----------------------------------------------------------- NEED_RUST=0 [[ "${COMPONENTS[zoxide]}" -eq 1 ]] && NEED_RUST=1 [[ "${COMPONENTS[bat]}" -eq 1 ]] && NEED_RUST=1 [[ "${COMPONENTS[eza]}" -eq 1 ]] && NEED_RUST=1 [[ "${COMPONENTS[tealdeer]}" -eq 1 ]] && NEED_RUST=1 if [[ $NEED_RUST -eq 1 && "${COMPONENTS[rust]}" -eq 0 ]]; then if ! command -v cargo &> /dev/null; then echo "Warning: You selected Rust tools but disabled 'rust'. Installation may fail." fi fi echo "--- Starting Installation ---" SUDO="" if [ "$EUID" -ne 0 ]; then if command -v sudo >/dev/null 2>&1; then SUDO="sudo" else echo "Error: This script requires root or sudo privileges." exit 1 fi fi # 5. EXECUTION # ----------------------------------------------------------- # --- CORE UTILS --- if [[ "${COMPONENTS[core_utils]}" -eq 1 ]]; then echo "[+] Installing Core Utils (apt)..." $SUDO apt-get update -y # Added 'unzip' and 'xclip' (required by kickstart.nvim) PKGS=(build-essential git curl emacs tmux nano vim mg ripgrep unzip xclip) $SUDO apt-get install -y "${PKGS[@]}" else echo "[-] Skipping Core Utils" fi # --- NEOVIM & KICKSTART --- if [[ "${COMPONENTS[neovim]}" -eq 1 ]]; then echo "[+] Installing Neovim (apt)..." $SUDO apt-get install -y neovim python3-neovim # Warn if version is too old for kickstart (Debian stable often has v0.7, Kickstart wants v0.9+) NVIM_VER=$(nvim --version | head -n1 | grep -oE 'v[0-9]+\.[0-9]+') echo "[.] Installed Neovim version: $NVIM_VER" # Determine config directory XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" NVIM_CONFIG="$XDG_CONFIG_HOME/nvim" # Backup existing config if [ -d "$NVIM_CONFIG" ]; then if git -C "$NVIM_CONFIG" remote -v | grep -q "kickstart.nvim"; then echo "[.] Kickstart is already installed." else echo "[!] Backing up existing Neovim config to ${NVIM_CONFIG}.bak" mv "$NVIM_CONFIG" "${NVIM_CONFIG}.bak" fi fi # Clone Kickstart if directory is empty/missing if [ ! -d "$NVIM_CONFIG" ]; then echo "[+] Cloning Kickstart.nvim..." git clone https://github.com/nvim-lua/kickstart.nvim.git "$NVIM_CONFIG" echo "[.] Kickstart installed. Run 'nvim' to finish plugin setup." fi else echo "[-] Skipping Neovim" fi # --- RUST TOOLCHAIN --- if [[ "${COMPONENTS[rust]}" -eq 1 ]]; then if ! command -v cargo &> /dev/null; then echo "[+] Installing Rust/Cargo..." curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y source "$HOME/.cargo/env" else echo "[.] Rust already installed." fi else echo "[-] Skipping Rust Toolchain" fi [ -f "$HOME/.cargo/env" ] && source "$HOME/.cargo/env" export PATH="$HOME/.cargo/bin:$PATH" install_crate() { local crate=$1 if ! command -v "$crate" &> /dev/null; then echo "[+] Installing $crate..." cargo install --locked "$crate" else echo "[.] $crate already installed." fi } # --- RUST CRATES --- [[ "${COMPONENTS[zoxide]}" -eq 1 ]] && install_crate zoxide || echo "[-] Skipping zoxide" [[ "${COMPONENTS[bat]}" -eq 1 ]] && install_crate bat || echo "[-] Skipping bat" [[ "${COMPONENTS[eza]}" -eq 1 ]] && install_crate eza || echo "[-] Skipping eza" [[ "${COMPONENTS[tealdeer]}" -eq 1 ]] && install_crate tealdeer || echo "[-] Skipping tealdeer" if [[ "${COMPONENTS[tealdeer]}" -eq 1 ]] && command -v tldr &> /dev/null; then tldr --update || true fi # --- FZF --- if [[ "${COMPONENTS[fzf]}" -eq 1 ]]; then if [ ! -d "$HOME/.fzf" ]; then echo "[+] Installing FZF..." git clone --depth 1 https://github.com/junegunn/fzf.git "$HOME/.fzf" "$HOME/.fzf/install" --all else echo "[.] FZF already installed." fi else echo "[-] Skipping FZF" fi # 6. CONFIGURATION (.bashrc) # ----------------------------------------------------------- MARKER="# --- POWERTOOLS CONFIG ---" if ! grep -qF "$MARKER" "$HOME/.bashrc"; then echo "[+] Configuring .bashrc..." cat >>"${HOME}/.bashrc" < /dev/null; then eval "\$(zoxide init bash)" fi if command -v bat > /dev/null; then export MANPAGER="sh -c 'col -bx | bat -l man -p'" fi if command -v eza > /dev/null; then alias ls='eza' alias ll='eza -l' alias la='eza -la' fi EOL else echo "[.] .bashrc already configured." fi echo "--- Setup Complete! ---" } setup_powertools "$@"