diff --git a/README.md b/README.md new file mode 100644 index 0000000..4b0134e --- /dev/null +++ b/README.md @@ -0,0 +1,160 @@ +# StianNOR-ZSHkit 🚀 + +> A clean, powerful Zsh setup for Linux — featuring Powerlevel10k, Oh My Zsh, Hack Nerd Font, colorls, fastfetch, and a full-featured update dashboard with health checks, tool suggestions and interactive install mode. + +> [!TIP] +> Having issues? Please open an issue: [https://github.com/StianNOR/StianNOR-ZSHkit/issues](https://github.com/StianNOR/StianNOR-ZSHkit/issues) +> Join the community on Discord: [https://discord.gg/eHEHCzGCAE](https://discord.gg/eHEHCzGCAE) + +--- + +## What's Included + +- **Zsh** with Oh My Zsh and Powerlevel10k prompt +- **Hack Nerd Font** installed system-wide with automatic terminal/DE configuration +- **colorls** for beautiful directory listings +- **fastfetch** for a system info splash on terminal open +- **zsh-autosuggestions**, **zsh-syntax-highlighting**, **zsh-completions** plugins +- **Update Dashboard** (`up.sh`) — a full system update + health check tool with interactive tool browser +- **ZSHrc Merge Script** (`update_zshrc.sh`) — safely merges new features into your existing `~/.zshrc` without overwriting personal config + +--- + +## Supported Package Managers ✅ + +| Package Manager | Distros | +|-----------------|-------------------------------------------| +| **APT** | Debian, Ubuntu, Linux Mint, Pop!_OS, etc | +| **DNF** | Fedora, CentOS 8+, RHEL 8+, Rocky Linux, etc | +| **Pacman** | Arch Linux, Manjaro, EndeavourOS, etc | +| **Zypper** | openSUSE, SUSE Linux Enterprise, etc | +| **APK** | Alpine Linux | + +--- + +## Installation + +```bash +cd ~ +git clone https://github.com/StianNOR/StianNOR-ZSHkit.git ZSHkit +cd ZSHkit +chmod +x *.sh +./setup_zsh.sh +``` + +After installation, **log out and back in** (or reboot) for the shell change and font to take effect. + +Then run `p10k configure` to set up your prompt style. + +--- + +## Update Dashboard 🚀 + +The update dashboard keeps your system up to date and healthy with a single command. + +```bash +up # update everything: packages, flatpak, gems, Oh My Zsh, docker +upc # first-run config: full update + interactive tool install/suppress mode +uph # health check only +ups # tool suggestions and interactive info browser +uphelp # show all commands +``` + +### What `up` does + +- Updates system packages (pacman/yay, apt, dnf, zypper, or apk) +- Updates Flatpak apps +- Updates Ruby gems (colorls etc.) +- Updates Oh My Zsh and all custom plugins +- Prunes Docker images and volumes +- Cleans journals, thumbnail cache and /tmp +- Rotates logs automatically (keeps last 10) +- Shows a health summary with GOOD/BAD verdict + +### Tool Suggestions & Info Mode 📖 + +After running `upc` (or pressing `i` after `ups`), an interactive tool browser opens: + +| Category | Tools | +|----------|-------| +| 🔒 Security | UFW, fail2ban, rkhunter, lynis, ClamAV, auditd, AppArmor | +| ⚡ Optimization | earlyoom, irqbalance, thermald, zram, preload | +| 📡 Monitoring | btop, smartmontools, ncdu, gdu, duf, nethogs, logwatch, nvtop | +| 🛠 Terminal | bat, fzf, rsync, restic, tldr | +| 🌐 Network & Extras | nmap, mtr, timeshift, yay (Arch), nala (Debian) | + +**Controls:** + +| Key | Action | +|-----|--------| +| `↑` / `↓` | Navigate tools | +| `→` / `←` | Next / previous page | +| `i` | Queue tool for install | +| `s` | Suppress tool (hide from suggestions permanently) | +| `q` | Save and exit | + +--- + +## Keeping Your Config Up To Date + +If you already have a customised `~/.zshrc` and don't want it overwritten, use the merge script instead of copying: + +```bash +cd ~/ZSHkit +git pull +zup # merges new ZSHkit sections into your existing ~/.zshrc +fresh # reload +``` + +The merge script only updates the **managed sections** (aliases, autosuggestions config) and leaves everything else untouched. + +```bash +zup --dry-run # preview changes without writing anything +zup --status # check which sections are present in your ~/.zshrc +``` + +--- + +## Helpful Aliases + +| Alias | Description | +|-------|-------------| +| `up` | Run system updates | +| `upc` | First-run config + tool browser | +| `uph` | Health check | +| `ups` | Suggestions + info mode | +| `uphelp` | Show all up commands | +| `zup` | Merge new ZSHkit config into local ~/.zshrc | +| `fresh` | Reload ~/.zshrc | +| `ali` | Show all active aliases | +| `rsy` | rsync with progress display | +| `p10` | Launch Powerlevel10k configurator | +| `ls` / `ll` / `la` / `sls` | colorls variants | + +--- + +## Uninstall + +```bash +./uninstall_zsh_setup.sh +``` + +--- + +## Screenshots + +| Before | After | +| :---: | :---: | +| ![Before]() | ![After]() | + +--- + +## Author + +**StianNOR** + +--- + +## Disclaimer ⚠️ + +Provided *as-is* for supported Linux distributions. Always back up important data before running scripts. The author accepts no responsibility for data loss or damage. Test in a VM if unsure. diff --git a/Standard Terminal.png b/Standard Terminal.png new file mode 100644 index 0000000..b2c9634 Binary files /dev/null and b/Standard Terminal.png differ diff --git a/setup_zsh.sh b/setup_zsh.sh new file mode 100644 index 0000000..88c77a5 --- /dev/null +++ b/setup_zsh.sh @@ -0,0 +1,507 @@ +#!/bin/bash +# ============================================================================= +# 🚀 StianNOR — ZSH + NERD FONT SETUP v2.0 +# Merges font_nerd_hack.sh + setup_zsh.sh +# Supports: Arch/Manjaro, Debian/Ubuntu, Fedora, openSUSE, Alpine +# ============================================================================= +set -euo pipefail + +# --- Colors --- +RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m' +BLUE='\033[0;34m'; CYAN='\033[0;36m'; BOLD='\033[1m'; RESET='\033[0m' +LINE="────────────────────────────────────────────────────────────────────────────" + +info() { echo -e "${CYAN}ℹ $*${RESET}"; } +success() { echo -e "${GREEN}✅ $*${RESET}"; } +warn() { echo -e "${YELLOW}⚠ $*${RESET}"; } +error() { echo -e "${RED}❌ $*${RESET}"; } +step() { echo -e "\n${BOLD}${BLUE}➤ $*${RESET}"; echo -e "${BLUE}${LINE}${RESET}"; } +die() { error "$*"; exit 1; } + +# --- Error trap --- +trap 'error "Failed at line $LINENO — command: $BASH_COMMAND"; exit 1' ERR + +# ============================================================================= +# 1. DETECT PACKAGE MANAGER +# ============================================================================= +step "Detecting package manager" +detect_pm() { + if command -v pacman >/dev/null 2>&1; then PM="pacman" + elif command -v apt >/dev/null 2>&1; then PM="apt" + elif command -v dnf >/dev/null 2>&1; then PM="dnf" + elif command -v zypper >/dev/null 2>&1; then PM="zypper" + elif command -v apk >/dev/null 2>&1; then PM="apk" + else die "No supported package manager found."; fi + success "Package manager: $PM" +} +detect_pm + +pkg_install() { + case "$PM" in + pacman) sudo pacman -S --noconfirm --needed "$@" ;; + apt) sudo apt install -y "$@" ;; + dnf) sudo dnf install -y "$@" ;; + zypper) sudo zypper install -y "$@" ;; + apk) sudo apk add "$@" ;; + esac +} + +pkg_update() { + case "$PM" in + pacman) sudo pacman -Syu --noconfirm ;; + apt) sudo apt update ;; + dnf) sudo dnf check-update || true ;; + zypper) sudo zypper refresh ;; + apk) sudo apk update ;; + esac +} + +# ============================================================================= +# 2. DETECT ENVIRONMENT +# ============================================================================= +step "Detecting desktop environment and terminals" + +get_distro() { + [[ -f /etc/os-release ]] && { source /etc/os-release; echo "$NAME"; return; } + uname -s +} + +get_desktop() { + local de="${XDG_CURRENT_DESKTOP,,}" + [[ -z "$de" ]] && de="${DESKTOP_SESSION,,}" + echo "$de" +} + +get_terminals() { + local terms=() + for t in gnome-terminal konsole alacritty kitty wezterm xfce4-terminal mate-terminal tilix; do + pgrep -x "$t" >/dev/null 2>&1 && terms+=("$t") + done + # Also check $TERM_PROGRAM + [[ -n "${TERM_PROGRAM:-}" ]] && terms+=("${TERM_PROGRAM,,}") + # Deduplicate + printf '%s\n' "${terms[@]}" | sort -u | tr '\n' ' ' +} + +DISTRO_NAME=$(get_distro) +DESKTOP_ENV=$(get_desktop) +TERMINALS=$(get_terminals) + +info "Distro: $DISTRO_NAME" +info "Desktop: ${DESKTOP_ENV:-unknown}" +info "Terminals: ${TERMINALS:-none detected}" + +# ============================================================================= +# 3. INSTALL DEPENDENCIES +# ============================================================================= +step "Installing core dependencies" +pkg_update + +case "$PM" in + pacman) pkg_install curl git wget unzip ruby gcc make ;; + apt) sudo apt install -y curl git wget unzip ruby ruby-dev gcc make build-essential ;; + dnf) sudo dnf install -y curl git wget unzip ruby ruby-devel gcc make ;; + zypper) sudo zypper install -y curl git wget unzip ruby ruby-devel gcc make ;; + apk) sudo apk add curl git wget unzip ruby ruby-dev gcc make ;; +esac +success "Core dependencies installed" + +# ============================================================================= +# 4. INSTALL HACK NERD FONT +# ============================================================================= +step "Installing Hack Nerd Font" + +FONT_DIR="/usr/local/share/fonts/nerd-fonts" +FONT_ALIAS="Hack Nerd Font" +FONT_TMPDIR=$(mktemp -d) +FONT_VERSION="v3.4.0" + +# Ensure fontconfig tools available +command -v fc-cache >/dev/null 2>&1 || pkg_install fontconfig + +cleanup_font_tmp() { rm -rf "$FONT_TMPDIR"; } +trap 'cleanup_font_tmp; error "Failed at line $LINENO — command: $BASH_COMMAND"; exit 1' ERR +trap 'cleanup_font_tmp' EXIT + +info "Downloading Hack Nerd Font $FONT_VERSION..." +FONT_URL="https://github.com/ryanoasis/nerd-fonts/releases/download/${FONT_VERSION}/Hack.zip" +if command -v curl >/dev/null 2>&1; then + curl -fsSL "$FONT_URL" -o "$FONT_TMPDIR/Hack.zip" || die "Font download failed" +else + wget -q "$FONT_URL" -O "$FONT_TMPDIR/Hack.zip" || die "Font download failed" +fi + +info "Extracting fonts..." +unzip -q "$FONT_TMPDIR/Hack.zip" -d "$FONT_TMPDIR/Hack" || die "Font extraction failed" + +sudo mkdir -p "$FONT_DIR" +# Only copy TTF/OTF — skip Windows-compat and licence files +find "$FONT_TMPDIR/Hack" -name "*.ttf" -o -name "*.otf" | while read -r f; do + [[ "$f" =~ (Windows|LICENSE|README) ]] && continue + sudo cp "$f" "$FONT_DIR/" +done + +sudo fc-cache -f "$FONT_DIR" +success "Hack Nerd Font installed to $FONT_DIR" + +# --- Apply to Desktop Environment --- +FONT_GENERAL="$FONT_ALIAS 12" +FONT_MONO="$FONT_ALIAS 11" +FONT_SMALL="$FONT_ALIAS 8" +FONT_OTHER="$FONT_ALIAS 10" + +apply_kde_fonts() { + local kwrite + if command -v kwriteconfig6 >/dev/null 2>&1; then kwrite="kwriteconfig6" + elif command -v kwriteconfig5 >/dev/null 2>&1; then kwrite="kwriteconfig5" + else warn "kwriteconfig not found — KDE font config skipped"; return; fi + + $kwrite --file kdeglobals --group General --key font "$FONT_ALIAS,12,-1,5,50,0,0,0,0,0" + $kwrite --file kdeglobals --group Fixed --key font "$FONT_ALIAS,11,-1,5,50,0,0,0,0,0" + $kwrite --file kdeglobals --group Small --key font "$FONT_ALIAS,8,-1,5,50,0,0,0,0,0" + $kwrite --file kdeglobals --group Toolbar --key font "$FONT_ALIAS,10,-1,5,50,0,0,0,0,0" + $kwrite --file kdeglobals --group Menu --key font "$FONT_ALIAS,10,-1,5,50,0,0,0,0,0" + $kwrite --file kdeglobals --group "Window Title" --key font "$FONT_ALIAS,10,-1,5,50,0,0,0,0,0" + $kwrite --file kdeglobals --group General --key antialiasing "true" + $kwrite --file kdeglobals --group General --key hinting "slight" + $kwrite --file kdeglobals --group General --key subpixelRendering "rgb" + $kwrite --file kdeglobals --group General --key forceFontDpi 96 + # Konsole profiles + find ~/.local/share/konsole -name "*.profile" 2>/dev/null \ + -exec sed -i "s/^Font=.*/Font=$FONT_ALIAS,12,-1,5,50,0,0,0,0,0,Regular/" {} \; + success "KDE fonts applied via $kwrite" +} + +apply_gnome_fonts() { + command -v gsettings >/dev/null 2>&1 || { warn "gsettings not found — GNOME font config skipped"; return; } + gsettings set org.gnome.desktop.interface font-name "$FONT_GENERAL" + gsettings set org.gnome.desktop.interface monospace-font-name "$FONT_MONO" + gsettings set org.gnome.desktop.interface document-font-name "$FONT_GENERAL" + # GNOME Terminal profiles via dconf + if command -v dconf >/dev/null 2>&1; then + while IFS= read -r profile; do + [[ -z "$profile" ]] && continue + dconf write "/org/gnome/terminal/legacy/profiles:/:${profile}/use-system-font" "false" + dconf write "/org/gnome/terminal/legacy/profiles:/:${profile}/font" "'$FONT_MONO'" + done < <(dconf list /org/gnome/terminal/legacy/profiles:/ 2>/dev/null | grep -oP '[^/:]+' || true) + fi + success "GNOME/Cinnamon fonts applied" +} + +apply_xfce_fonts() { + command -v xfconf-query >/dev/null 2>&1 || { warn "xfconf-query not found — XFCE font config skipped"; return; } + xfconf-query -c xsettings -p /Gtk/FontName -s "$FONT_GENERAL" 2>/dev/null || true + xfconf-query -c xfwm4 -p /general/font -s "$FONT_GENERAL" 2>/dev/null || true + local xterm_conf="$HOME/.config/xfce4/terminal/terminalrc" + if [[ -f "$xterm_conf" ]]; then + sed -i "s/^FontName=.*/FontName=$FONT_MONO/" "$xterm_conf" + fi + success "XFCE fonts applied" +} + +apply_mate_fonts() { + command -v gsettings >/dev/null 2>&1 || { warn "gsettings not found — MATE font config skipped"; return; } + gsettings set org.mate.interface font-name "$FONT_GENERAL" 2>/dev/null || true + success "MATE fonts applied" +} + +case "$DESKTOP_ENV" in + *kde*|*plasma*) apply_kde_fonts ;; + *gnome*|*cinnamon*|*unity*) apply_gnome_fonts ;; + *xfce*) apply_xfce_fonts ;; + *mate*) apply_mate_fonts ;; + *) warn "Desktop '$DESKTOP_ENV' not specifically handled — font installed system-wide via fontconfig" ;; +esac + +# --- Apply to detected terminal emulators --- +apply_terminal_font() { + local term="$1" + case "$term" in + alacritty) + # Support both .yml (old) and .toml (new Alacritty >=0.13) + local conf_toml="$HOME/.config/alacritty/alacritty.toml" + local conf_yml="$HOME/.config/alacritty/alacritty.yml" + if [[ -f "$conf_toml" ]]; then + if grep -q '^\[font\]' "$conf_toml"; then + sed -i '/^\[font\]/,/^\[/{s/^family = .*/family = "'"$FONT_ALIAS"'"/}' "$conf_toml" + else + printf '\n[font]\n[font.normal]\nfamily = "%s"\n[font.bold]\nfamily = "%s"\n[font.italic]\nfamily = "%s"\n\n[font.size]\nsize = 12.0\n' \ + "$FONT_ALIAS" "$FONT_ALIAS" "$FONT_ALIAS" >> "$conf_toml" + fi + success "Alacritty TOML font updated" + elif [[ -f "$conf_yml" ]]; then + sed -i "/^ *family:/c\\ family: \"$FONT_ALIAS\"" "$conf_yml" + sed -i "/^ *size:/c\\ size: 12" "$conf_yml" + success "Alacritty YAML font updated" + else + warn "Alacritty config not found at $conf_toml or $conf_yml — skipping" + fi + ;; + kitty) + local kconf="$HOME/.config/kitty/kitty.conf" + mkdir -p "$(dirname "$kconf")" + if [[ -f "$kconf" ]]; then + sed -i "/^font_family/c\\font_family $FONT_ALIAS" "$kconf" + sed -i "/^font_size/c\\font_size 12.0" "$kconf" + else + printf 'font_family %s\nfont_size 12.0\n' "$FONT_ALIAS" > "$kconf" + fi + success "Kitty font configured" + ;; + wezterm) + local wconf="$HOME/.config/wezterm/wezterm.lua" + if [[ -f "$wconf" ]]; then + warn "WezTerm config found at $wconf — add this manually:" + echo " config.font = wezterm.font('$FONT_ALIAS')" + fi + ;; + konsole) + find ~/.local/share/konsole -name "*.profile" 2>/dev/null \ + -exec sed -i "s/^Font=.*/Font=$FONT_ALIAS,12,-1,5,50,0,0,0,0,0,Regular/" {} \; + success "Konsole profiles updated" + ;; + xfce4-terminal) + local xterm_conf="$HOME/.config/xfce4/terminal/terminalrc" + [[ -f "$xterm_conf" ]] && sed -i "s/^FontName=.*/FontName=$FONT_MONO/" "$xterm_conf" + success "XFCE Terminal font updated" + ;; + gnome-terminal) ;; # handled by apply_gnome_fonts via dconf + *) warn "Terminal '$term' font config not supported — set manually" ;; + esac +} + +for term in $TERMINALS; do + apply_terminal_font "$term" +done + +# --- fontconfig fallback (monospace alias) --- +sudo tee /etc/fonts/local.conf > /dev/null < + + + + monospace + + ${FONT_ALIAS} + + + + Hack Nerd Font Mono + + ${FONT_ALIAS} + + + +FONTCONF +sudo fc-cache -f +success "fontconfig monospace alias set" + +# NOTE: TTY/vconsole fonts must be bitmap/psf fonts — Nerd Font TTFs +# cannot be used in vconsole.conf. Skipping to avoid breaking TTY. + +# ============================================================================= +# 5. INSTALL ZSH +# ============================================================================= +step "Installing Zsh" +if ! command -v zsh >/dev/null 2>&1; then + pkg_install zsh + success "Zsh installed" +else + success "Zsh already installed: $(zsh --version)" +fi + +# ============================================================================= +# 6. UPDATE RUBYGEMS + INSTALL COLORLS +# ============================================================================= +step "Setting up Ruby gems (colorls)" +export GEM_HOME="$HOME/.gem" +export PATH="$PATH:$GEM_HOME/bin" +USER_GEM_BIN="$(ruby -e 'puts Gem.user_dir' 2>/dev/null)/bin" + +# Update gems — skip system update on apt (breaks Debian policy) +if [[ "$PM" != "apt" ]]; then + gem update --system 2>/dev/null && success "RubyGems system updated" \ + || warn "RubyGems system update failed — continuing" +fi +gem update 2>/dev/null && success "All gems updated" || warn "gem update had warnings — continuing" + +if gem list -i colorls >/dev/null 2>&1; then + success "colorls already installed" +else + info "Installing colorls..." + gem install --user-install colorls || die "colorls install failed" + success "colorls installed" +fi + +# Add gem bin to PATH in both .zshrc and .bashrc so it works during this session too +for rc in "$HOME/.zshrc" "$HOME/.bashrc"; do + if [[ -f "$rc" ]] && ! grep -q "$USER_GEM_BIN" "$rc" 2>/dev/null; then + echo "export PATH=\"\$PATH:$USER_GEM_BIN\"" >> "$rc" + info "Added gem bin to PATH in $rc" + fi +done +export PATH="$PATH:$USER_GEM_BIN" + +# ============================================================================= +# 7. INSTALL FASTFETCH +# ============================================================================= +step "Installing fastfetch" +if command -v fastfetch >/dev/null 2>&1; then + success "fastfetch already installed: $(fastfetch --version 2>/dev/null | head -1)" +else + info "Trying package manager first..." + installed=false + case "$PM" in + pacman) sudo pacman -S --noconfirm --needed fastfetch 2>/dev/null && installed=true ;; + apt) + # fastfetch not in standard apt — try PPA or direct .deb download + if sudo add-apt-repository -y ppa:zhangsongcui3371/fastfetch 2>/dev/null; then + sudo apt update && sudo apt install -y fastfetch && installed=true + fi ;; + dnf) sudo dnf install -y fastfetch 2>/dev/null && installed=true ;; + zypper) sudo zypper install -y fastfetch 2>/dev/null && installed=true ;; + apk) sudo apk add fastfetch 2>/dev/null && installed=true ;; + esac + + if [[ "$installed" == false ]]; then + warn "Package manager install failed — downloading latest binary release..." + ARCH=$(uname -m) + [[ "$ARCH" == "x86_64" ]] && ARCH_NAME="amd64" || ARCH_NAME="$ARCH" + FF_URL=$(curl -s https://api.github.com/repos/fastfetch-cli/fastfetch/releases/latest \ + | grep "browser_download_url" \ + | grep "linux-${ARCH_NAME}.tar.gz" \ + | head -1 | cut -d'"' -f4) + if [[ -n "$FF_URL" ]]; then + FF_TMP=$(mktemp -d) + curl -fsSL "$FF_URL" -o "$FF_TMP/fastfetch.tar.gz" + tar -xzf "$FF_TMP/fastfetch.tar.gz" -C "$FF_TMP" + sudo install -m755 "$FF_TMP"/fastfetch*/usr/bin/fastfetch /usr/local/bin/fastfetch 2>/dev/null \ + || sudo cp "$(find "$FF_TMP" -name fastfetch -type f | head -1)" /usr/local/bin/fastfetch + sudo chmod +x /usr/local/bin/fastfetch + rm -rf "$FF_TMP" + installed=true + fi + fi + + if [[ "$installed" == true ]] && command -v fastfetch >/dev/null 2>&1; then + success "fastfetch installed: $(fastfetch --version 2>/dev/null | head -1)" + else + warn "fastfetch could not be installed automatically — install it manually" + fi +fi + +# ============================================================================= +# 8. INSTALL OH MY ZSH +# ============================================================================= +step "Installing Oh My Zsh" +if [[ -f "$HOME/.oh-my-zsh/oh-my-zsh.sh" ]]; then + success "Oh My Zsh already installed" +else + info "Installing Oh My Zsh..." + rm -rf "$HOME/.oh-my-zsh" + RUNZSH=no KEEP_ZSHRC=yes \ + sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" \ + || die "Oh My Zsh install failed" + success "Oh My Zsh installed" +fi + +ZSH_CUSTOM="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}" + +# ============================================================================= +# 9. INSTALL POWERLEVEL10K +# ============================================================================= +step "Installing Powerlevel10k theme" +P10K_DIR="$ZSH_CUSTOM/themes/powerlevel10k" +if [[ -d "$P10K_DIR" ]]; then + info "Updating Powerlevel10k..." + git -C "$P10K_DIR" pull --ff-only 2>/dev/null && success "Powerlevel10k updated" || warn "p10k update failed — skipping" +else + git clone --depth=1 https://github.com/romkatv/powerlevel10k.git "$P10K_DIR" \ + || die "Powerlevel10k install failed" + success "Powerlevel10k installed" +fi + +# ============================================================================= +# 10. INSTALL ZSH PLUGINS +# ============================================================================= +step "Installing Zsh plugins" +declare -A ZSH_PLUGINS=( + [zsh-autosuggestions]="https://github.com/zsh-users/zsh-autosuggestions" + [zsh-syntax-highlighting]="https://github.com/zsh-users/zsh-syntax-highlighting" + [zsh-completions]="https://github.com/zsh-users/zsh-completions" +) + +for plugin in "${!ZSH_PLUGINS[@]}"; do + local_dir="$ZSH_CUSTOM/plugins/$plugin" + if [[ -d "$local_dir" ]]; then + git -C "$local_dir" pull --ff-only 2>/dev/null && success "$plugin updated" || warn "$plugin update skipped" + else + info "Installing $plugin..." + git clone "${ZSH_PLUGINS[$plugin]}" "$local_dir" || warn "$plugin install failed — continuing" + success "$plugin installed" + fi +done + +# ============================================================================= +# 11. COPY .zshrc AND .p10k.zsh +# ============================================================================= +step "Applying .zshrc and .p10k.zsh" +# Use the directory where THIS script lives as the source +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +copy_if_exists() { + local src="$1" dst="$2" label="$3" + if [[ -f "$src" ]]; then + cp "$src" "$dst" + success "$label → $dst" + else + warn "$src not found — $label not copied" + fi +} + +copy_if_exists "$SCRIPT_DIR/.zshrc" "$HOME/.zshrc" ".zshrc" +copy_if_exists "$SCRIPT_DIR/.p10k.zsh" "$HOME/.p10k.zsh" ".p10k.zsh" + +# Ensure gem bin and zsh path are in the copied .zshrc +for line in \ + "export PATH=\"\$PATH:$USER_GEM_BIN\"" \ + "export GEM_HOME=\"\$HOME/.gem\""; do + grep -qF "$line" "$HOME/.zshrc" 2>/dev/null || echo "$line" >> "$HOME/.zshrc" +done + +# ============================================================================= +# 12. SET ZSH AS DEFAULT SHELL +# ============================================================================= +step "Setting Zsh as default shell" +ZSH_PATH=$(command -v zsh) +if [[ "$SHELL" == "$ZSH_PATH" ]]; then + success "Zsh is already the default shell" +else + # Make sure zsh is in /etc/shells + grep -qxF "$ZSH_PATH" /etc/shells || echo "$ZSH_PATH" | sudo tee -a /etc/shells + if chsh -s "$ZSH_PATH" 2>/dev/null; then + success "Default shell set to $ZSH_PATH" + info "Log out and back in for the shell change to take effect" + else + warn "Could not change default shell — run manually: chsh -s $ZSH_PATH" + fi +fi + +# ============================================================================= +# DONE +# ============================================================================= +echo "" +echo -e "${LINE}" +echo -e "${BOLD}${GREEN} ✅ StianNOR Zsh + Nerd Font Setup Complete!${RESET}" +echo -e "${LINE}" +echo -e " ${CYAN}Font:${RESET} Hack Nerd Font installed system-wide" +echo -e " ${CYAN}Shell:${RESET} Zsh + Oh My Zsh + Powerlevel10k" +echo -e " ${CYAN}Plugins:${RESET} autosuggestions, syntax-highlighting, completions" +echo -e " ${CYAN}Tools:${RESET} colorls, fastfetch" +echo -e "${LINE}" +echo -e " ${YELLOW}Next steps:${RESET}" +echo -e " 1. Log out and back in (shell change + font)" +echo -e " 2. Run ${CYAN}p10k configure${RESET} to set up your prompt" +echo -e " 3. In your terminal settings, select ${CYAN}Hack Nerd Font${RESET} manually if needed" +echo -e "${LINE}" +echo ""