Files
CLI-dots/config/setup-zsh.sh
2026-03-28 14:36:27 +00:00

207 lines
7.6 KiB
Bash

#!/usr/bin/env bash
# =============================================================================
# setup-zsh.sh — Bootstrap zsh environment across devices
# Supports: apt (Debian/Ubuntu), dnf (Fedora)
# =============================================================================
set -euo pipefail
# ── Colours ──────────────────────────────────────────────────────────────────
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
CYAN='\033[0;36m'; BOLD='\033[1m'; RESET='\033[0m'
info() { echo -e "${CYAN}${BOLD}[INFO]${RESET} $*"; }
success() { echo -e "${GREEN}${BOLD}[OK]${RESET} $*"; }
warn() { echo -e "${YELLOW}${BOLD}[WARN]${RESET} $*"; }
error() { echo -e "${RED}${BOLD}[ERROR]${RESET} $*" >&2; exit 1; }
# ── Detect package manager ────────────────────────────────────────────────────
detect_pm() {
if command -v apt &>/dev/null; then
PM="apt"
PM_INSTALL="sudo apt install -y"
PM_UPDATE="sudo apt update -y"
elif command -v dnf &>/dev/null; then
PM="dnf"
PM_INSTALL="sudo dnf install -y"
PM_UPDATE="sudo dnf check-update -y || true"
else
error "No supported package manager found (apt or dnf required)."
fi
info "Detected package manager: ${BOLD}$PM${RESET}"
}
# ── Helpers ───────────────────────────────────────────────────────────────────
is_installed() { command -v "$1" &>/dev/null; }
install_pkg() {
local pkg="$1" cmd="${2:-$1}"
if is_installed "$cmd"; then
success "$cmd already installed — skipping."
else
info "Installing $pkg"
$PM_INSTALL "$pkg"
success "$pkg installed."
fi
}
# ── Install Starship ─────────────────────────────────────────────────────────
install_starship() {
if is_installed starship; then
success "Starship already installed — skipping."
else
info "Installing Starship …"
curl -sS https://starship.rs/install.sh | sh -s -- --yes
success "Starship installed."
fi
}
# ── Install eza ───────────────────────────────────────────────────────────────
install_eza() {
if is_installed eza; then
success "eza already installed — skipping."
return
fi
info "Installing eza …"
if [[ "$PM" == "apt" ]]; then
sudo mkdir -p /etc/apt/keyrings
wget -qO- https://raw.githubusercontent.com/eza-community/eza/main/deb.asc \
| sudo gpg --dearmor -o /etc/apt/keyrings/gierens.gpg
echo "deb [signed-by=/etc/apt/keyrings/gierens.gpg] http://deb.gierens.de stable main" \
| sudo tee /etc/apt/sources.list.d/gierens.list
sudo chmod 644 /etc/apt/keyrings/gierens.gpg /etc/apt/sources.list.d/gierens.list
sudo apt update -y
sudo apt install -y eza
elif [[ "$PM" == "dnf" ]]; then
# eza is in the EPEL/Fedora repos from F38+
sudo dnf install -y eza
fi
success "eza installed."
}
# ── Install fzf ───────────────────────────────────────────────────────────────
install_fzf() {
if is_installed fzf; then
success "fzf already installed — skipping."
return
fi
info "Installing fzf …"
if [[ "$PM" == "apt" ]]; then
sudo apt install -y fzf
elif [[ "$PM" == "dnf" ]]; then
sudo dnf install -y fzf
fi
success "fzf installed."
}
# ── Install bat ───────────────────────────────────────────────────────────────
install_bat() {
if is_installed bat; then
success "bat already installed — skipping."
return
fi
info "Installing bat …"
if [[ "$PM" == "apt" ]]; then
sudo apt install -y bat
# On Ubuntu/Debian the binary may be 'batcat'
if ! is_installed bat && is_installed batcat; then
mkdir -p ~/.local/bin
ln -sf "$(command -v batcat)" ~/.local/bin/bat
warn "Symlinked batcat → ~/.local/bin/bat (add ~/.local/bin to PATH if needed)."
fi
elif [[ "$PM" == "dnf" ]]; then
sudo dnf install -y bat
fi
success "bat installed."
}
# ── Install zinit ─────────────────────────────────────────────────────────────
install_zinit() {
local zinit_home="${HOME}/.config/zinit/zinit.git"
if [[ -d "$zinit_home" ]]; then
success "zinit already installed — skipping."
else
info "Cloning zinit …"
mkdir -p "$(dirname "$zinit_home")"
git clone https://github.com/zdharma-continuum/zinit.git "$zinit_home"
success "zinit cloned."
fi
}
# ── Deploy .zshrc ─────────────────────────────────────────────────────────────
deploy_zshrc() {
local script_dir
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
local src="${script_dir}/_zshrc"
local dest="${HOME}/.zshrc"
if [[ ! -f "$src" ]]; then
error "_zshrc not found next to setup-zsh.sh (expected: $src)"
fi
if [[ -f "$dest" ]]; then
local backup="${dest}.bak.$(date +%Y%m%d_%H%M%S)"
info "Backing up existing .zshrc → $backup"
cp "$dest" "$backup"
success "Backup created: $backup"
fi
cp "$src" "$dest"
success ".zshrc deployed to $dest"
}
# ── Make zsh default shell ────────────────────────────────────────────────────
set_default_shell() {
if [[ "$SHELL" == *"zsh"* ]]; then
success "zsh is already the default shell."
return
fi
local zsh_path
zsh_path="$(command -v zsh 2>/dev/null || true)"
if [[ -z "$zsh_path" ]]; then
warn "zsh not found in PATH — skipping default shell change."
return
fi
info "Setting zsh as the default shell …"
chsh -s "$zsh_path"
success "Default shell set to $zsh_path (takes effect on next login)."
}
# ── Main ──────────────────────────────────────────────────────────────────────
main() {
echo -e "\n${BOLD}${CYAN}╔══════════════════════════════════════╗"
echo -e "║ zsh environment setup script ║"
echo -e "╚══════════════════════════════════════╝${RESET}\n"
detect_pm
info "Updating package index …"
$PM_UPDATE
# Core dependencies
install_pkg zsh
install_pkg git
install_pkg curl
install_pkg wget
# zsh tools
install_starship
install_eza
install_fzf
install_bat
install_zinit
# anifetch removed
# Deploy config
deploy_zshrc
# Optionally switch default shell
set_default_shell
echo -e "\n${GREEN}${BOLD}✔ Setup complete!${RESET}"
echo -e " • Start a new zsh session or run: ${BOLD}exec zsh${RESET}"
echo -e " • Zinit plugins will install automatically on first zsh launch\n"
}
main "$@"