Change zsh theme

Custom theme is very minimal and has little info about your whereabouts
on the server. "bira" theme set as default.

Custom theme wasn't removed, just commented-out.
This commit is contained in:
2026-06-05 11:33:51 +02:00
parent 41a7eb370b
commit eda09583b5
3 changed files with 430 additions and 421 deletions

View File

@@ -18,12 +18,15 @@ cd ~/server_cli_tools
| # | Component | What it does | | # | Component | What it does |
|---|-----------|-------------| |---|-----------|-------------|
| 1 | **Core packages** | `vim`, `bat`, `eza`, `fzf`, `htop`, `tmux`, `zsh`, `ripgrep`, `fd-find`, `zoxide`, `git-delta` | | 1 | **Core packages** | `vim`, `bat`, `eza`, `fzf`, `htop`, `tmux`, `zsh`, `ripgrep`, `fd-find`, `zoxide`, `git-delta` |
| 2 | **Zsh + Oh-My-Zsh** | Shell, plugins (`zsh-autosuggestions`, `zsh-syntax-highlighting`, `z`), custom prompt theme | | 2 | **Zsh + Oh-My-Zsh** | Shell, plugins (`zsh-autosuggestions`, `zsh-syntax-highlighting`, `z`), `bira` prompt theme |
| 3 | **Aliases + tools** | General, git, and docker aliases with a self-documenting help system (`h`) | | 3 | **Aliases + tools** | General, git, and docker aliases with a self-documenting help system (`h`) |
| 4 | **Terminal configs** | `bat` theme (base16) | | 4 | **Terminal configs** | `bat` theme (base16) |
| 5 | **Docker** | `docker.io` via apt, service enabled, user added to `docker` group, management aliases | | 5 | **Docker** | `docker.io` via apt, service enabled, user added to `docker` group, management aliases |
| 6 | **Git config** | `git-delta` as pager with side-by-side diffs | | 6 | **Git config** | `git-delta` as pager with side-by-side diffs |
> **NOTE:** There's minimal custom theme in `<repo>/configs/zsh/zhann-elvis.zsh-theme`. To apply it toggle `ZSH_THEME` and uncomment sourcing it in `~/.zshrc` after install.
> For more themes, see [Oh-My-Zsh themes](https://github.com/ohmyzsh/ohmyzsh/wiki/themes).
## Alias highlights ## Alias highlights
Type `h` after installation to see all aliases with descriptions. Some highlights: Type `h` after installation to see all aliases with descriptions. Some highlights:
@@ -63,8 +66,7 @@ server_cli_tools/
custom_tools/ custom_tools/
backup_dotfiles.sh # backup conflicting dotfiles backup_dotfiles.sh # backup conflicting dotfiles
bat/config # bat theme bat/config # bat theme
zsh/zhann-elvis.zsh-theme # custom zsh prompt (git-aware) zshrc # .zshrc with oh-my-zsh, bira theme, plugins
zshrc # .zshrc with oh-my-zsh + plugins
``` ```
## Customization ## Customization

View File

@@ -2,7 +2,8 @@ export ZSH="$HOME/.oh-my-zsh"
export ALIASES="$HOME/.config/aliases" export ALIASES="$HOME/.config/aliases"
export CT_DIR="$HOME/.config/custom_tools" export CT_DIR="$HOME/.config/custom_tools"
export EDITOR="vim" export EDITOR="vim"
ZSH_THEME="" # ZSH_THEME=""
ZSH_THEME="bira"
DISABLE_AUTO_TITLE="true" DISABLE_AUTO_TITLE="true"
plugins=( plugins=(
git git
@@ -11,7 +12,7 @@ plugins=(
z z
) )
source $ZSH/oh-my-zsh.sh source $ZSH/oh-my-zsh.sh
source $HOME/.config/zsh/zhann-elvis.zsh-theme # source $HOME/.config/zsh/zhann-elvis.zsh-theme
source $ALIASES/.aliases source $ALIASES/.aliases
autoload -Uz zcalc autoload -Uz zcalc
[ -f /usr/share/doc/fzf/examples/key-bindings.zsh ] && source /usr/share/doc/fzf/examples/key-bindings.zsh [ -f /usr/share/doc/fzf/examples/key-bindings.zsh ] && source /usr/share/doc/fzf/examples/key-bindings.zsh

View File

@@ -13,17 +13,17 @@ BACKUP_DIR="$HOME/.server_cli_tools_bkp/$(date +%Y%m%d-%H%M%S)"
# SSH from Ghostty and other clients forwards TERM values (e.g. xterm-ghostty) # SSH from Ghostty and other clients forwards TERM values (e.g. xterm-ghostty)
# that remote servers often lack in terminfo — breaks clear/tput and colors. # that remote servers often lack in terminfo — breaks clear/tput and colors.
if ! infocmp "${TERM:-}" &>/dev/null; then if ! infocmp "${TERM:-}" &>/dev/null; then
for _term_fallback in xterm-256color xterm screen dumb; do for _term_fallback in xterm-256color xterm screen dumb; do
if infocmp "$_term_fallback" &>/dev/null; then if infocmp "$_term_fallback" &>/dev/null; then
export TERM="$_term_fallback" export TERM="$_term_fallback"
break break
fi fi
done done
unset _term_fallback unset _term_fallback
fi fi
# Colors (matching the dotfiles convention) # Colors (matching the dotfiles convention)
e_err() { echo -e "\e[1;31m$1\e[0m"; } e_err() { echo -e "\e[1;31m$1\e[0m"; }
e_info() { echo -e "\e[1;34m$1\e[0m"; } e_info() { echo -e "\e[1;34m$1\e[0m"; }
e_succ() { echo -e "\e[1;32m$1\e[0m"; } e_succ() { echo -e "\e[1;32m$1\e[0m"; }
e_warn() { echo -e "\e[1;38;5;208m$1\e[0m"; } e_warn() { echo -e "\e[1;38;5;208m$1\e[0m"; }
@@ -36,69 +36,69 @@ SKIPPED=()
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
backup_file() { backup_file() {
local src="$1" local src="$1"
if [ -e "$src" ]; then if [ -e "$src" ]; then
local rel="${src#$HOME/}" local rel="${src#$HOME/}"
local dest="$BACKUP_DIR/$rel" local dest="$BACKUP_DIR/$rel"
mkdir -p "$(dirname "$dest")" mkdir -p "$(dirname "$dest")"
cp -a "$src" "$dest" cp -a "$src" "$dest"
e_info " Backed up $src" e_info " Backed up $src"
fi fi
} }
copy_config() { copy_config() {
local src="$1" dest="$2" local src="$1" dest="$2"
backup_file "$dest" backup_file "$dest"
mkdir -p "$(dirname "$dest")" mkdir -p "$(dirname "$dest")"
cp -a "$src" "$dest" cp -a "$src" "$dest"
} }
copy_dir() { copy_dir() {
local src="$1" dest="$2" local src="$1" dest="$2"
if [ -d "$dest" ]; then if [ -d "$dest" ]; then
backup_file "$dest" backup_file "$dest"
fi fi
mkdir -p "$dest" mkdir -p "$dest"
cp -a "$src"/. "$dest"/ cp -a "$src"/. "$dest"/
} }
command_exists() { command_exists() {
command -v "$1" >/dev/null 2>&1 command -v "$1" >/dev/null 2>&1
} }
safe_clear() { safe_clear() {
clear 2>/dev/null || printf '\033[H\033[2J' clear 2>/dev/null || printf '\033[H\033[2J'
} }
check_os() { check_os() {
if [ ! -f /etc/os-release ]; then if [ ! -f /etc/os-release ]; then
e_err "Cannot detect OS. This script supports Ubuntu/Debian only." e_err "Cannot detect OS. This script supports Ubuntu/Debian only."
exit 1 exit 1
fi fi
. /etc/os-release . /etc/os-release
case "$ID" in case "$ID" in
ubuntu|debian) ;; ubuntu | debian) ;;
*) *)
e_warn "Detected $ID — this script is designed for Ubuntu/Debian." e_warn "Detected $ID — this script is designed for Ubuntu/Debian."
e_warn "Package installation may not work. Configs will still be copied." e_warn "Package installation may not work. Configs will still be copied."
;; ;;
esac esac
} }
apt_install() { apt_install() {
local packages=("$@") local packages=("$@")
local to_install=() local to_install=()
for pkg in "${packages[@]}"; do for pkg in "${packages[@]}"; do
if dpkg -s "$pkg" &>/dev/null; then if dpkg -s "$pkg" &>/dev/null; then
e_info " $pkg is already installed" e_info " $pkg is already installed"
else else
to_install+=("$pkg") to_install+=("$pkg")
fi
done
if [ ${#to_install[@]} -gt 0 ]; then
e_info " Installing: ${to_install[*]}"
sudo apt-get install -y "${to_install[@]}"
fi fi
done
if [ ${#to_install[@]} -gt 0 ]; then
e_info " Installing: ${to_install[*]}"
sudo apt-get install -y "${to_install[@]}"
fi
} }
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@@ -106,159 +106,159 @@ apt_install() {
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
install_core_packages() { install_core_packages() {
e_info "\n[1/6] Core packages" e_info "\n[1/6] Core packages"
sudo apt-get update -qq sudo apt-get update -qq
apt_install curl vim bat fzf htop tmux zsh ripgrep fd-find zoxide apt_install curl vim bat fzf htop tmux zsh ripgrep fd-find zoxide
# bat is installed as 'batcat' on Debian/Ubuntu # bat is installed as 'batcat' on Debian/Ubuntu
if command_exists batcat && ! command_exists bat; then if command_exists batcat && ! command_exists bat; then
sudo ln -sf /usr/bin/batcat /usr/local/bin/bat sudo ln -sf /usr/bin/batcat /usr/local/bin/bat
e_info " Symlinked batcat -> bat" e_info " Symlinked batcat -> bat"
fi fi
# eza — not in all distro repos, try apt first, fall back to cargo/binary # eza — not in all distro repos, try apt first, fall back to cargo/binary
if ! command_exists eza; then if ! command_exists eza; then
if apt-cache show eza &>/dev/null; then if apt-cache show eza &>/dev/null; then
apt_install eza apt_install eza
else
e_warn " eza not in apt repos. Install manually: https://github.com/eza-community/eza"
fi
else else
e_info " eza is already installed" e_warn " eza not in apt repos. Install manually: https://github.com/eza-community/eza"
fi fi
else
e_info " eza is already installed"
fi
# git-delta # git-delta
if ! command_exists delta; then if ! command_exists delta; then
if apt-cache show git-delta &>/dev/null; then if apt-cache show git-delta &>/dev/null; then
apt_install git-delta apt_install git-delta
else
e_warn " git-delta not in apt repos. Install from: https://github.com/dandavison/delta/releases"
fi
else else
e_info " delta is already installed" e_warn " git-delta not in apt repos. Install from: https://github.com/dandavison/delta/releases"
fi fi
else
e_info " delta is already installed"
fi
INSTALLED+=("core-packages") INSTALLED+=("core-packages")
} }
install_zsh() { install_zsh() {
e_info "\n[2/6] Zsh + Oh-My-Zsh" e_info "\n[2/6] Zsh + Oh-My-Zsh"
if ! command_exists zsh; then if ! command_exists zsh; then
apt_install zsh apt_install zsh
fi
# Oh-My-Zsh
if [ ! -d "$HOME/.oh-my-zsh" ]; then
e_info " Installing Oh-My-Zsh..."
RUNZSH=no CHSH=no sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
else
e_info " Oh-My-Zsh already installed"
fi
# Plugins
local zsh_custom="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}"
if [ ! -d "$zsh_custom/plugins/zsh-autosuggestions" ]; then
e_info " Cloning zsh-autosuggestions..."
git clone --quiet https://github.com/zsh-users/zsh-autosuggestions "$zsh_custom/plugins/zsh-autosuggestions"
else
e_info " zsh-autosuggestions already installed"
fi
if [ ! -d "$zsh_custom/plugins/zsh-syntax-highlighting" ]; then
e_info " Cloning zsh-syntax-highlighting..."
git clone --quiet https://github.com/zsh-users/zsh-syntax-highlighting.git "$zsh_custom/plugins/zsh-syntax-highlighting"
else
e_info " zsh-syntax-highlighting already installed"
fi
# Theme
# mkdir -p "$HOME/.config/zsh"
# copy_config "$CONFIGS/zsh/zhann-elvis.zsh-theme" "$HOME/.config/zsh/zhann-elvis.zsh-theme"
# e_info " Installed zhann-elvis.zsh-theme"
# .zshrc
copy_config "$CONFIGS/zshrc" "$HOME/.zshrc"
e_info " Installed .zshrc"
# Change default shell to zsh (if not already)
if [ "$(basename "$SHELL")" != "zsh" ]; then
e_info " Changing default shell to zsh..."
if command_exists chsh; then
chsh -s "$(which zsh)" || e_warn " chsh failed — change shell manually: chsh -s \$(which zsh)"
fi fi
fi
# Oh-My-Zsh INSTALLED+=("zsh")
if [ ! -d "$HOME/.oh-my-zsh" ]; then
e_info " Installing Oh-My-Zsh..."
RUNZSH=no CHSH=no sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
else
e_info " Oh-My-Zsh already installed"
fi
# Plugins
local zsh_custom="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}"
if [ ! -d "$zsh_custom/plugins/zsh-autosuggestions" ]; then
e_info " Cloning zsh-autosuggestions..."
git clone --quiet https://github.com/zsh-users/zsh-autosuggestions "$zsh_custom/plugins/zsh-autosuggestions"
else
e_info " zsh-autosuggestions already installed"
fi
if [ ! -d "$zsh_custom/plugins/zsh-syntax-highlighting" ]; then
e_info " Cloning zsh-syntax-highlighting..."
git clone --quiet https://github.com/zsh-users/zsh-syntax-highlighting.git "$zsh_custom/plugins/zsh-syntax-highlighting"
else
e_info " zsh-syntax-highlighting already installed"
fi
# Theme
mkdir -p "$HOME/.config/zsh"
copy_config "$CONFIGS/zsh/zhann-elvis.zsh-theme" "$HOME/.config/zsh/zhann-elvis.zsh-theme"
e_info " Installed zhann-elvis.zsh-theme"
# .zshrc
copy_config "$CONFIGS/zshrc" "$HOME/.zshrc"
e_info " Installed .zshrc"
# Change default shell to zsh (if not already)
if [ "$(basename "$SHELL")" != "zsh" ]; then
e_info " Changing default shell to zsh..."
if command_exists chsh; then
chsh -s "$(which zsh)" || e_warn " chsh failed — change shell manually: chsh -s \$(which zsh)"
fi
fi
INSTALLED+=("zsh")
} }
install_aliases() { install_aliases() {
e_info "\n[3/6] Aliases + custom tools" e_info "\n[3/6] Aliases + custom tools"
copy_dir "$CONFIGS/aliases" "$HOME/.config/aliases" copy_dir "$CONFIGS/aliases" "$HOME/.config/aliases"
chmod +x "$HOME/.config/aliases"/.aliases "$HOME/.config/aliases"/.functions.sh 2>/dev/null || true chmod +x "$HOME/.config/aliases"/.aliases "$HOME/.config/aliases"/.functions.sh 2>/dev/null || true
e_info " Installed aliases to ~/.config/aliases/" e_info " Installed aliases to ~/.config/aliases/"
copy_dir "$CONFIGS/custom_tools" "$HOME/.config/custom_tools" copy_dir "$CONFIGS/custom_tools" "$HOME/.config/custom_tools"
chmod +x "$HOME/.config/custom_tools"/*.sh 2>/dev/null || true chmod +x "$HOME/.config/custom_tools"/*.sh 2>/dev/null || true
e_info " Installed custom tools to ~/.config/custom_tools/" e_info " Installed custom tools to ~/.config/custom_tools/"
INSTALLED+=("aliases" "custom-tools") INSTALLED+=("aliases" "custom-tools")
} }
install_terminal_configs() { install_terminal_configs() {
e_info "\n[4/6] Terminal configs (bat)" e_info "\n[4/6] Terminal configs (bat)"
mkdir -p "$HOME/.config/bat" mkdir -p "$HOME/.config/bat"
copy_config "$CONFIGS/bat/config" "$HOME/.config/bat/config" copy_config "$CONFIGS/bat/config" "$HOME/.config/bat/config"
e_info " Installed bat config (theme: base16)" e_info " Installed bat config (theme: base16)"
INSTALLED+=("terminal-configs") INSTALLED+=("terminal-configs")
} }
install_docker() { install_docker() {
e_info "\n[5/6] Docker" e_info "\n[5/6] Docker"
sudo apt-get update -qq sudo apt-get update -qq
apt_install docker.io apt_install docker.io
if command_exists systemctl; then if command_exists systemctl; then
sudo systemctl enable --now docker 2>/dev/null \ sudo systemctl enable --now docker 2>/dev/null ||
|| e_warn " Could not enable docker service — start manually: sudo systemctl start docker" e_warn " Could not enable docker service — start manually: sudo systemctl start docker"
fi fi
if id -nG "$USER" 2>/dev/null | grep -qw docker; then if id -nG "$USER" 2>/dev/null | grep -qw docker; then
e_info " $USER is already in the docker group" e_info " $USER is already in the docker group"
else else
e_info " Adding $USER to the docker group..." e_info " Adding $USER to the docker group..."
sudo usermod -aG docker "$USER" sudo usermod -aG docker "$USER"
e_warn " Log out and back in (or run: newgrp docker) for group membership to apply" e_warn " Log out and back in (or run: newgrp docker) for group membership to apply"
fi fi
mkdir -p "$HOME/.config/aliases" mkdir -p "$HOME/.config/aliases"
copy_config "$CONFIGS/aliases/.docker_aliases" "$HOME/.config/aliases/.docker_aliases" copy_config "$CONFIGS/aliases/.docker_aliases" "$HOME/.config/aliases/.docker_aliases"
e_info " Installed Docker aliases" e_info " Installed Docker aliases"
INSTALLED+=("docker") INSTALLED+=("docker")
} }
install_git_config() { install_git_config() {
e_info "\n[6/6] Git config (delta pager)" e_info "\n[6/6] Git config (delta pager)"
if ! command_exists delta; then if ! command_exists delta; then
e_warn " git-delta not installed — config will be ready when delta is available" e_warn " git-delta not installed — config will be ready when delta is available"
fi fi
local gitconfig="$HOME/.gitconfig" local gitconfig="$HOME/.gitconfig"
# Only inject delta config if not already present # Only inject delta config if not already present
if [ -f "$gitconfig" ] && grep -q '\[delta\]' "$gitconfig" 2>/dev/null; then if [ -f "$gitconfig" ] && grep -q '\[delta\]' "$gitconfig" 2>/dev/null; then
e_info " Delta config already present in ~/.gitconfig" e_info " Delta config already present in ~/.gitconfig"
else else
e_info " Adding delta pager config to ~/.gitconfig" e_info " Adding delta pager config to ~/.gitconfig"
cat >> "$gitconfig" << 'DELTA' cat >>"$gitconfig" <<'DELTA'
[core] [core]
pager = delta pager = delta
@@ -271,9 +271,9 @@ install_git_config() {
[merge] [merge]
conflictStyle = zdiff3 conflictStyle = zdiff3
DELTA DELTA
fi fi
INSTALLED+=("git-config") INSTALLED+=("git-config")
} }
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@@ -281,60 +281,63 @@ DELTA
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
uninstall() { uninstall() {
e_warn "This will remove configs installed by Server CLI Tools." e_warn "This will remove configs installed by Server CLI Tools."
e_warn "Installed packages (apt) will NOT be removed." e_warn "Installed packages (apt) will NOT be removed."
echo "" echo ""
printf "Continue? [y/N] " printf "Continue? [y/N] "
read -r confirm read -r confirm
case "$confirm" in case "$confirm" in
y|Y) ;; y | Y) ;;
*) echo "Aborted."; exit 0 ;; *)
esac echo "Aborted."
exit 0
;;
esac
local removed=() local removed=()
# Aliases + custom tools # Aliases + custom tools
if [ -d "$HOME/.config/aliases" ]; then if [ -d "$HOME/.config/aliases" ]; then
rm -rf "$HOME/.config/aliases" rm -rf "$HOME/.config/aliases"
removed+=("aliases") removed+=("aliases")
fi fi
if [ -d "$HOME/.config/custom_tools" ]; then if [ -d "$HOME/.config/custom_tools" ]; then
rm -rf "$HOME/.config/custom_tools" rm -rf "$HOME/.config/custom_tools"
removed+=("custom-tools") removed+=("custom-tools")
fi fi
# Terminal configs # Terminal configs
if [ -f "$HOME/.config/bat/config" ]; then if [ -f "$HOME/.config/bat/config" ]; then
rm -f "$HOME/.config/bat/config" rm -f "$HOME/.config/bat/config"
removed+=("bat-config") removed+=("bat-config")
fi fi
# Zsh theme + zshrc # Zsh theme + zshrc
if [ -f "$HOME/.config/zsh/zhann-elvis.zsh-theme" ]; then if [ -f "$HOME/.config/zsh/zhann-elvis.zsh-theme" ]; then
rm -f "$HOME/.config/zsh/zhann-elvis.zsh-theme" rm -f "$HOME/.config/zsh/zhann-elvis.zsh-theme"
removed+=("zsh-theme") removed+=("zsh-theme")
fi fi
if [ -f "$HOME/.zshrc" ]; then if [ -f "$HOME/.zshrc" ]; then
rm -f "$HOME/.zshrc" rm -f "$HOME/.zshrc"
removed+=("zshrc") removed+=("zshrc")
fi fi
# Oh-My-Zsh plugins (only the ones we installed) # Oh-My-Zsh plugins (only the ones we installed)
local zsh_custom="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}" local zsh_custom="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}"
if [ -d "$zsh_custom/plugins/zsh-autosuggestions" ]; then if [ -d "$zsh_custom/plugins/zsh-autosuggestions" ]; then
rm -rf "$zsh_custom/plugins/zsh-autosuggestions" rm -rf "$zsh_custom/plugins/zsh-autosuggestions"
removed+=("zsh-autosuggestions") removed+=("zsh-autosuggestions")
fi fi
if [ -d "$zsh_custom/plugins/zsh-syntax-highlighting" ]; then if [ -d "$zsh_custom/plugins/zsh-syntax-highlighting" ]; then
rm -rf "$zsh_custom/plugins/zsh-syntax-highlighting" rm -rf "$zsh_custom/plugins/zsh-syntax-highlighting"
removed+=("zsh-syntax-highlighting") removed+=("zsh-syntax-highlighting")
fi fi
# Git config — strip delta block # Git config — strip delta block
local gitconfig="$HOME/.gitconfig" local gitconfig="$HOME/.gitconfig"
if [ -f "$gitconfig" ] && grep -q '\[delta\]' "$gitconfig" 2>/dev/null; then if [ -f "$gitconfig" ] && grep -q '\[delta\]' "$gitconfig" 2>/dev/null; then
local tmp local tmp
tmp=$(mktemp) tmp=$(mktemp)
awk ' awk '
/^\[core\]/ { if (skip==0) { peek=1; hold=$0; next } } /^\[core\]/ { if (skip==0) { peek=1; hold=$0; next } }
peek==1 { peek==1 {
if ($0 ~ /pager *= *delta/) { skip=1; next } if ($0 ~ /pager *= *delta/) { skip=1; next }
@@ -347,42 +350,42 @@ uninstall() {
/^\[/ { skip=0 } /^\[/ { skip=0 }
skip { next } skip { next }
{ print } { print }
' "$gitconfig" > "$tmp" ' "$gitconfig" >"$tmp"
mv "$tmp" "$gitconfig" mv "$tmp" "$gitconfig"
removed+=("git-delta-config") removed+=("git-delta-config")
fi fi
echo ""
if [ ${#removed[@]} -gt 0 ]; then
e_succ "Removed:"
for item in "${removed[@]}"; do
echo " - $item"
done
else
e_info "Nothing to remove."
fi
# Offer to restore backups
local bkp_base="$HOME/.server_cli_tools_bkp"
if [ -d "$bkp_base" ]; then
echo "" echo ""
if [ ${#removed[@]} -gt 0 ]; then local latest
e_succ "Removed:" latest=$(ls -1t "$bkp_base" 2>/dev/null | head -n1)
for item in "${removed[@]}"; do if [ -n "$latest" ]; then
echo " - $item" e_info "Backup found: $bkp_base/$latest"
done printf "Restore from this backup? [y/N] "
else read -r restore
e_info "Nothing to remove." case "$restore" in
y | Y)
cp -a "$bkp_base/$latest"/. "$HOME"/
e_succ "Restored from $bkp_base/$latest"
;;
*) e_info "Skipping restore." ;;
esac
fi fi
fi
# Offer to restore backups echo ""
local bkp_base="$HOME/.server_cli_tools_bkp"
if [ -d "$bkp_base" ]; then
echo ""
local latest
latest=$(ls -1t "$bkp_base" 2>/dev/null | head -n1)
if [ -n "$latest" ]; then
e_info "Backup found: $bkp_base/$latest"
printf "Restore from this backup? [y/N] "
read -r restore
case "$restore" in
y|Y)
cp -a "$bkp_base/$latest"/. "$HOME"/
e_succ "Restored from $bkp_base/$latest"
;;
*) e_info "Skipping restore." ;;
esac
fi
fi
echo ""
} }
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@@ -390,104 +393,104 @@ uninstall() {
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
COMPONENTS=( COMPONENTS=(
"Core packages (vim, bat, eza, fzf, htop, tmux, rg, fd, zoxide, delta)" "Core packages (vim, bat, eza, fzf, htop, tmux, rg, fd, zoxide, delta)"
"Zsh + Oh-My-Zsh (shell, plugins, theme)" "Zsh + Oh-My-Zsh (shell, plugins)"
"Aliases + custom tools" "Aliases + custom tools"
"Terminal configs (bat)" "Terminal configs (bat)"
"Docker (engine + aliases)" "Docker (engine + aliases)"
"Git config (delta pager)" "Git config (delta pager)"
) )
INSTALLERS=( INSTALLERS=(
install_core_packages install_core_packages
install_zsh install_zsh
install_aliases install_aliases
install_terminal_configs install_terminal_configs
install_docker install_docker
install_git_config install_git_config
) )
show_menu() { show_menu() {
local count=${#COMPONENTS[@]} local count=${#COMPONENTS[@]}
local selected=() local selected=()
for ((i = 0; i < count; i++)); do
selected+=(1)
done
while true; do
safe_clear
echo ""
e_info "Server CLI Tools — Installer"
echo "============================="
echo ""
echo "Select components (enter number to toggle, a=all, n=none):"
echo ""
for ((i = 0; i < count; i++)); do for ((i = 0; i < count; i++)); do
selected+=(1) local mark=" "
if [ "${selected[$i]}" -eq 1 ]; then
mark=" x "
fi
printf " [%s] %d) %s\n" "$mark" "$((i + 1))" "${COMPONENTS[$i]}"
done done
while true; do echo ""
safe_clear echo " [a] Select all [n] Select none [Enter] Install [q] Quit"
echo "" echo ""
e_info "Server CLI Tools — Installer" printf " > "
echo "=============================" read -r choice
echo ""
echo "Select components (enter number to toggle, a=all, n=none):"
echo ""
for ((i = 0; i < count; i++)); do case "$choice" in
local mark=" " q | Q)
if [ "${selected[$i]}" -eq 1 ]; then echo "Aborted."
mark=" x " exit 0
fi ;;
printf " [%s] %d) %s\n" "$mark" "$((i + 1))" "${COMPONENTS[$i]}" a | A)
done for ((i = 0; i < count; i++)); do
selected[$i]=1
done
;;
n | N)
for ((i = 0; i < count; i++)); do
selected[$i]=0
done
;;
"")
# Run selected installers
local any=0
for ((i = 0; i < count; i++)); do
if [ "${selected[$i]}" -eq 1 ]; then
any=1
fi
done
if [ "$any" -eq 0 ]; then
e_warn "Nothing selected!"
sleep 1
continue
fi
echo "" echo ""
echo " [a] Select all [n] Select none [Enter] Install [q] Quit" for ((i = 0; i < count; i++)); do
echo "" if [ "${selected[$i]}" -eq 1 ]; then
printf " > " ${INSTALLERS[$i]}
read -r choice else
SKIPPED+=("${COMPONENTS[$i]}")
case "$choice" in fi
q|Q) done
echo "Aborted." return
exit 0 ;;
;; *)
a|A) if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le "$count" ]; then
for ((i = 0; i < count; i++)); do local idx=$((choice - 1))
selected[$i]=1 if [ "${selected[$idx]}" -eq 1 ]; then
done selected[$idx]=0
;; else
n|N) selected[$idx]=1
for ((i = 0; i < count; i++)); do fi
selected[$i]=0 fi
done ;;
;; esac
"") done
# Run selected installers
local any=0
for ((i = 0; i < count; i++)); do
if [ "${selected[$i]}" -eq 1 ]; then
any=1
fi
done
if [ "$any" -eq 0 ]; then
e_warn "Nothing selected!"
sleep 1
continue
fi
echo ""
for ((i = 0; i < count; i++)); do
if [ "${selected[$i]}" -eq 1 ]; then
${INSTALLERS[$i]}
else
SKIPPED+=("${COMPONENTS[$i]}")
fi
done
return
;;
*)
if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le "$count" ]; then
local idx=$((choice - 1))
if [ "${selected[$idx]}" -eq 1 ]; then
selected[$idx]=0
else
selected[$idx]=1
fi
fi
;;
esac
done
} }
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@@ -495,38 +498,38 @@ show_menu() {
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
print_summary() { print_summary() {
echo "" echo ""
echo "===========================================" echo "==========================================="
e_succ " Installation complete!" e_succ " Installation complete!"
echo "===========================================" echo "==========================================="
if [ ${#INSTALLED[@]} -gt 0 ]; then
echo ""
e_succ "Installed:"
for item in "${INSTALLED[@]}"; do
echo " + $item"
done
fi
if [ ${#SKIPPED[@]} -gt 0 ]; then
echo ""
e_warn "Skipped:"
for item in "${SKIPPED[@]}"; do
echo " - $item"
done
fi
if [ -d "$BACKUP_DIR" ]; then
echo ""
e_info "Backups saved to: $BACKUP_DIR"
fi
if [ ${#INSTALLED[@]} -gt 0 ]; then
echo "" echo ""
e_info "To apply changes, start a new shell or run:" e_succ "Installed:"
echo " exec zsh" for item in "${INSTALLED[@]}"; do
echo " + $item"
done
fi
if [ ${#SKIPPED[@]} -gt 0 ]; then
echo "" echo ""
e_info "Type 'h' to see all available aliases." e_warn "Skipped:"
for item in "${SKIPPED[@]}"; do
echo " - $item"
done
fi
if [ -d "$BACKUP_DIR" ]; then
echo "" echo ""
e_info "Backups saved to: $BACKUP_DIR"
fi
echo ""
e_info "To apply changes, start a new shell or run:"
echo " exec zsh"
echo ""
e_info "Type 'h' to see all available aliases."
echo ""
} }
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@@ -534,62 +537,65 @@ print_summary() {
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
usage() { usage() {
echo "Usage: $0 [OPTIONS]" echo "Usage: $0 [OPTIONS]"
echo "" echo ""
echo "Options:" echo "Options:"
echo " --all Install all components (non-interactive)" echo " --all Install all components (non-interactive)"
echo " --update Pull latest changes and re-run installer" echo " --update Pull latest changes and re-run installer"
echo " --update --all Pull latest and install all (non-interactive)" echo " --update --all Pull latest and install all (non-interactive)"
echo " --uninstall Remove installed configs (keeps packages)" echo " --uninstall Remove installed configs (keeps packages)"
echo " --help Show this help message" echo " --help Show this help message"
echo "" echo ""
echo "Without options, an interactive menu is shown." echo "Without options, an interactive menu is shown."
} }
main() { main() {
case "${1:-}" in case "${1:-}" in
--help|-h) --help | -h)
usage usage
exit 0 exit 0
;; ;;
--uninstall) --uninstall)
uninstall uninstall
exit 0 exit 0
;; ;;
--update) --update)
e_info "Pulling latest changes..." e_info "Pulling latest changes..."
git -C "$SCRIPT_DIR" pull || { e_err "git pull failed"; exit 1; } git -C "$SCRIPT_DIR" pull || {
echo "" e_err "git pull failed"
check_os exit 1
if [ "${2:-}" = "--all" ] || [ "${2:-}" = "-a" ]; then }
e_info "Server CLI Tools — installing all components" echo ""
for installer in "${INSTALLERS[@]}"; do check_os
$installer if [ "${2:-}" = "--all" ] || [ "${2:-}" = "-a" ]; then
done e_info "Server CLI Tools — installing all components"
else for installer in "${INSTALLERS[@]}"; do
show_menu $installer
fi done
print_summary else
;; show_menu
--all|-a) fi
check_os print_summary
e_info "Server CLI Tools — installing all components" ;;
for installer in "${INSTALLERS[@]}"; do --all | -a)
$installer check_os
done e_info "Server CLI Tools — installing all components"
print_summary for installer in "${INSTALLERS[@]}"; do
;; $installer
"") done
check_os print_summary
show_menu ;;
print_summary "")
;; check_os
*) show_menu
e_err "Unknown option: $1" print_summary
usage ;;
exit 1 *)
;; e_err "Unknown option: $1"
esac usage
exit 1
;;
esac
} }
main "$@" main "$@"