The bootstrap silently installs tools for ~30s+ on a version bump or first login, which looked like an unexplained hang. Now prints a banner explaining what is happening, that it may take a minute, and that subsequent runs are a no-op. The box is built dynamically so the right edge stays aligned regardless of the version string length. Also clarifies the trigger comment in zshrc.
158 lines
6.2 KiB
Bash
158 lines
6.2 KiB
Bash
export ZSH_CONFIG=$HOME/.config/zsh
|
|
export OHMYZSH=$ZSH_CONFIG/oh-my-zsh
|
|
export OHMYZSH_CUSTOM=$OHMYZSH/custom
|
|
|
|
# Bootstrap banner — built dynamically so the box stays aligned regardless
|
|
# of the version string length or terminal width.
|
|
_bootstrap_banner() {
|
|
local inner=61 # inner width (between the vertical bars)
|
|
local pad line
|
|
local title="Zsh bootstrap - one-time environment setup (v${ZSHRC_BOOTSTRAP_VERSION})"
|
|
local rule=$(printf '═%.0s' {1..$inner})
|
|
local mid=$(printf '─%.0s' {1..$inner})
|
|
# left-pad the title by 2 spaces so it doesn't hug the left bar
|
|
title=" $title"
|
|
pad=$(( inner - ${#title} ))
|
|
(( pad < 0 )) && pad=0
|
|
echo ""
|
|
echo "╔${rule}╗"
|
|
printf '║%s%*s║\n' "$title" "$pad" ""
|
|
echo "╠${mid}╣"
|
|
while IFS= read -r line; do
|
|
line=" $line"
|
|
pad=$(( inner - ${#line} ))
|
|
(( pad < 0 )) && pad=0
|
|
printf '║%s%*s║\n' "$line" "$pad" ""
|
|
done <<'EOF'
|
|
This runs on first login or when the bootstrap version
|
|
changes. It installs missing CLI tools and clones oh-my-zsh
|
|
+ plugins across distros. Network calls time out after
|
|
~30s so an unreachable host skips silently. The first run
|
|
may take a minute; subsequent runs are a no-op.
|
|
EOF
|
|
echo "╚${rule}╝"
|
|
echo ""
|
|
}
|
|
_bootstrap_banner
|
|
unfunction _bootstrap_banner
|
|
|
|
touch ~/.hushlogin
|
|
mkdir -p "$HOME/.local/bin"
|
|
mkdir -p "$ZSH_CONFIG"
|
|
path+=("$HOME/.local/bin")
|
|
|
|
for p in git starship fzf eza rsync lazydocker fastfetch tmux bat zoxide; do
|
|
command -v $p >/dev/null && continue
|
|
if command -v brew >/dev/null; then
|
|
echo "Installing $p using brew" && brew install $p && continue
|
|
fi
|
|
if command -v apt >/dev/null && apt-cache show $p >/dev/null 2>&1; then
|
|
echo "Installing $p using Apt" && sudo apt install $p -y && continue
|
|
fi
|
|
if command -v dnf >/dev/null && dnf list available $p >/dev/null 2>&1; then
|
|
echo "Installing $p using dnf" && sudo dnf install $p -y && continue
|
|
fi
|
|
if command -v pacman >/dev/null && pacman -Si $p >/dev/null 2>&1; then
|
|
echo "Installing $p using pacman" && sudo pacman -Sy --noconfirm $p && continue
|
|
fi
|
|
if command -v cargo >/dev/null; then
|
|
echo "Installing $p using cargo" && cargo install $p --locked && continue
|
|
fi
|
|
done
|
|
|
|
if ! command -v starship >/dev/null; then
|
|
echo "Installing starship binary..." && \
|
|
curl -fsSL --connect-timeout 5 --max-time 30 https://starship.rs/install.sh | sh -s -- -b ~/.local/bin -y >/dev/null 2>&1
|
|
fi
|
|
|
|
if ! command -v lazydocker >/dev/null; then
|
|
echo "Installing lazydocker binary..." && \
|
|
curl -fsSL --connect-timeout 5 --max-time 30 https://raw.githubusercontent.com/jesseduffield/lazydocker/master/scripts/install_update_linux.sh | \
|
|
DIR=$HOME/.local/bin bash >/dev/null 2>&1
|
|
fi
|
|
|
|
# Debian/Ubuntu ships bat as 'batcat' and fd as 'fdfind'; symlink to the
|
|
# canonical names so the zshrc integrations (which call bat/fd) work everywhere.
|
|
if ! command -v bat >/dev/null && command -v batcat >/dev/null; then
|
|
ln -sf "$(command -v batcat)" "$HOME/.local/bin/bat"
|
|
fi
|
|
if ! command -v fd >/dev/null && command -v fdfind >/dev/null; then
|
|
ln -sf "$(command -v fdfind)" "$HOME/.local/bin/fd"
|
|
fi
|
|
|
|
# git-delta: the package is named 'git-delta' on every package manager but the
|
|
# binary is 'delta' (name mismatch vs the install loop above), so install via the
|
|
# same PM cascade using the real package name. Used by zshrc as GIT_PAGER.
|
|
if ! command -v delta >/dev/null; then
|
|
if command -v brew >/dev/null; then
|
|
echo "Installing git-delta using brew" && brew install git-delta
|
|
elif command -v apt >/dev/null && apt-cache show git-delta >/dev/null 2>&1; then
|
|
echo "Installing git-delta using Apt" && sudo apt install git-delta -y
|
|
elif command -v dnf >/dev/null && dnf list available git-delta >/dev/null 2>&1; then
|
|
echo "Installing git-delta using dnf" && sudo dnf install git-delta -y
|
|
elif command -v pacman >/dev/null && pacman -Si git-delta >/dev/null 2>&1; then
|
|
echo "Installing git-delta using pacman" && sudo pacman -Sy --noconfirm git-delta
|
|
elif command -v cargo >/dev/null; then
|
|
echo "Installing git-delta using cargo" && cargo install git-delta --locked
|
|
fi
|
|
fi
|
|
|
|
arch=$(uname -m)
|
|
case "$arch" in
|
|
x86_64) target_fast="linux-amd64" && target_eza="x86_64-unknown-linux-gnu" ;;
|
|
aarch64|arm64) target_fast="linux-aarch64" && target_eza="aarch64-unknown-linux-gnu" ;;
|
|
armv7l) target_fast="linux-armv7l" && target_eza="armv7-unknown-linux-gnueabihf" ;;
|
|
esac
|
|
|
|
if [[ -n $target_fast && -n $target_eza ]]; then
|
|
if ! command -v fastfetch >/dev/null; then
|
|
if curl -fsSL --connect-timeout 5 --max-time 30 -o /tmp/fastfetch.tar.gz \
|
|
"https://github.com/fastfetch-cli/fastfetch/releases/latest/download/fastfetch-${target_fast}.tar.gz" \
|
|
&& tar -xzf /tmp/fastfetch.tar.gz -C /tmp 2>/dev/null; then
|
|
ffdir=$(find /tmp -maxdepth 1 -type d -name 'fastfetch*' | head -1)
|
|
if [[ -n "$ffdir" ]]; then
|
|
cp "$ffdir/usr/bin/fastfetch" "$HOME/.local/bin/"
|
|
chmod +x "$HOME/.local/bin/fastfetch"
|
|
mkdir -p "$HOME/.local/share/fastfetch"
|
|
cp -r "$ffdir/usr/share/fastfetch/"* "$HOME/.local/share/fastfetch/"
|
|
fi
|
|
rm -rf "$ffdir" /tmp/fastfetch.tar.gz
|
|
else
|
|
rm -f /tmp/fastfetch.tar.gz
|
|
fi
|
|
fi
|
|
|
|
if ! command -v eza >/dev/null; then
|
|
if curl -fsSL --connect-timeout 5 --max-time 30 -o /tmp/eza.tar.gz \
|
|
"https://github.com/eza-community/eza/releases/latest/download/eza_${target_eza}.tar.gz" \
|
|
&& tar -xzf /tmp/eza.tar.gz -C "$HOME/.local/bin/" 2>/dev/null; then
|
|
chmod +x "$HOME/.local/bin/eza"
|
|
else
|
|
echo "Warning: failed to download eza" >&2
|
|
fi
|
|
rm -f /tmp/eza.tar.gz
|
|
fi
|
|
fi
|
|
|
|
mkdir -p "$HOME/.config/zsh"
|
|
|
|
[ ! -d $OHMYZSH ] && \
|
|
GIT_TERMINAL_PROMPT=0 git -c http.lowSpeedLimit=1000 -c http.lowSpeedTime=10 \
|
|
clone --depth=1 https://github.com/ohmyzsh/ohmyzsh.git $OHMYZSH
|
|
|
|
for plug in \
|
|
"zsh-autosuggestions|https://github.com/zsh-users/zsh-autosuggestions" \
|
|
"fast-syntax-highlighting|https://github.com/zdharma-continuum/fast-syntax-highlighting" \
|
|
"fzf-tab|https://github.com/Aloxaf/fzf-tab"
|
|
do
|
|
name="${plug%%|*}"
|
|
url="${plug##*|}"
|
|
dir="$OHMYZSH_CUSTOM/plugins/$name"
|
|
[[ ! -d "$dir" ]] && \
|
|
GIT_TERMINAL_PROMPT=0 git -c http.lowSpeedLimit=1000 -c http.lowSpeedTime=10 \
|
|
clone "$url" "$dir" 2>/dev/null
|
|
done
|
|
|
|
# Cleanup
|
|
[[ -d $HOME/.config/oh-my-zsh ]] && rm -rf "$HOME/.config/oh-my-zsh"
|