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.
202 lines
7.0 KiB
Bash
202 lines
7.0 KiB
Bash
export ZSH_CONFIG=$HOME/.config/zsh
|
|
export OHMYZSH=$ZSH_CONFIG/oh-my-zsh
|
|
export OHMYZSH_CUSTOM=$OHMYZSH/custom
|
|
|
|
export ZSHRC_GIT="https://git.jeremymcclure.com/jeremy/scripts/raw/branch/master/zsh/"
|
|
|
|
export ZSHRC_URL="$ZSHRC_GIT/zshrc"
|
|
export ZSHRC_BOOTSTRAP_URL="$ZSHRC_GIT/zshrc-bootstrap.zsh"
|
|
export ZSHRC_BOOTSTRAP_VERSION="3"
|
|
export ZSHRC_BOOTSTRAP="$ZSH_CONFIG/.bootstrapped"
|
|
|
|
[[ -d "$HOME/Scripts" ]] && path+=("$HOME/Scripts")
|
|
[[ -d "$HOME/.local/bin" ]] && path+=("$HOME/.local/bin")
|
|
[[ -d "$HOME/AppImages" ]] && path+=("$HOME/AppImages")
|
|
[[ -d "$HOME/.opencode/bin" ]] && path+=("$HOME/.opencode/bin")
|
|
|
|
update_zshrc(){
|
|
local tmp=/tmp/.zshrc.$$
|
|
curl -fsSL --connect-timeout 5 --max-time 10 "$ZSHRC_URL" -o "$tmp" 2>/dev/null || return
|
|
if zsh -n "$tmp" 2>/dev/null && ! cmp -s "$tmp" "$HOME/.zshrc" 2>/dev/null; then
|
|
echo "Updating zshrc..."
|
|
mv "$tmp" "$HOME/.zshrc" && echo "Updated. Reloading..." && exec zsh
|
|
fi
|
|
rm -f "$tmp"
|
|
}
|
|
|
|
fix_btopbg(){
|
|
sed -i 's/theme_background = true/theme_background = false/' ~/.config/btop/btop.conf
|
|
}
|
|
|
|
install_opencode(){
|
|
curl -fsSL https://opencode.ai/install | bash
|
|
}
|
|
|
|
# Bootstrap: download and run once per bootstrap version. Installs missing CLI
|
|
# tools and oh-my-zsh/plugins across distros; prints a banner so the user knows
|
|
# what the activity is. Re-runs only when ZSHRC_BOOTSTRAP_VERSION is bumped or
|
|
# BOOTSTRAP=true is set.
|
|
if [[ ! -f "$ZSHRC_BOOTSTRAP" || "$(cat "$ZSHRC_BOOTSTRAP" 2>/dev/null)" != "$ZSHRC_BOOTSTRAP_VERSION" || "$BOOTSTRAP" == "true" ]]; then
|
|
tmp=/tmp/.zshrc_bootstrap.$$
|
|
curl -fsSL --connect-timeout 5 --max-time 10 -o "$tmp" "$ZSHRC_BOOTSTRAP_URL" 2>/dev/null
|
|
if [[ -f "$tmp" ]]; then
|
|
zsh "$tmp" 2>/dev/null
|
|
echo "$ZSHRC_BOOTSTRAP_VERSION" > "$ZSHRC_BOOTSTRAP"
|
|
rm -f "$tmp"
|
|
fi
|
|
fi
|
|
|
|
TMUXCONF="$HOME/.config/tmux"
|
|
BYOBUCONF="$HOME/.config/byobu"
|
|
TMUXREMOTE="$ZSHRC_GIT/tmux.conf"
|
|
if [ ! -f "$TMUXCONF/tmux.conf" ] && [ ! -f "$BYOBUCONF/.tmux.conf" ]; then
|
|
# Create a secure temporary file
|
|
TEMP_TMUXCONF=$(mktemp)
|
|
|
|
# Download to temp file.
|
|
# The '&&' ensures the 'mv' only runs if curl succeeds (exit code 0).
|
|
if curl -fsSL --connect-timeout 5 --max-time 10 -o "$TEMP_TMUXCONF" "$TMUXREMOTE"; then
|
|
mkdir -p "$TMUXCONF" "$BYOBUCONF"
|
|
cp "$TEMP_TMUXCONF" "$TMUXCONF/tmux.conf"
|
|
mv "$TEMP_TMUXCONF" "$BYOBUCONF/.tmux.conf"
|
|
else
|
|
# Optional: Clean up temp file if download failed
|
|
rm -f "$TEMP_TMUXCONF"
|
|
echo "Error: Failed to download tmux config from $TMUXREMOTE" >&2
|
|
fi
|
|
fi
|
|
|
|
export HISTFILE="$ZSH_CONFIG/history"
|
|
export ZSH_COMPDUMP="$ZSH_CONFIG/zcompdump-${HOST}-${ZSH_VERSION}"
|
|
export HISTSIZE=10000
|
|
export SAVEHIST=10000
|
|
|
|
setopt SHARE_HISTORY
|
|
setopt HIST_IGNORE_DUPS
|
|
setopt HIST_IGNORE_ALL_DUPS
|
|
setopt HIST_REDUCE_BLANKS
|
|
setopt HIST_FCNTL_LOCK
|
|
setopt AUTO_CD
|
|
setopt AUTO_LIST
|
|
setopt INTERACTIVE_COMMENTS
|
|
setopt HIST_VERIFY
|
|
setopt EXTENDED_HISTORY
|
|
setopt AUTO_PUSHD
|
|
setopt PUSHD_IGNORE_DUPS
|
|
setopt PUSHD_SILENT
|
|
|
|
ZSH_THEME=""
|
|
ENABLE_CORRECTION="false"
|
|
HIST_STAMPS="mm/dd/yyyy"
|
|
|
|
plugins=(
|
|
git
|
|
sudo
|
|
extract
|
|
eza
|
|
history
|
|
kitty
|
|
docker
|
|
docker-compose
|
|
archlinux
|
|
encode64
|
|
universalarchive
|
|
zsh-autosuggestions
|
|
fast-syntax-highlighting
|
|
fzf
|
|
fzf-tab
|
|
systemd
|
|
vscode
|
|
rsync
|
|
starship
|
|
)
|
|
|
|
zstyle ':omz:update' 'mode' auto
|
|
zstyle ':omz:plugins:eza' 'dirs-first' yes
|
|
zstyle ':omz:plugins:eza' 'git-status' yes
|
|
zstyle ':omz:plugins:eza' 'header' yes
|
|
zstyle ':omz:plugins:eza' 'show-group' yes
|
|
zstyle ':omz:plugins:eza' 'icons' yes
|
|
zstyle ':omz:plugins:eza' 'color-scale' all
|
|
zstyle ':omz:plugins:eza' 'color-scale-mode' fixed
|
|
zstyle ':omz:plugins:eza' 'size-prefix' si
|
|
# NOTE: 'hyperlink' is intentionally NOT set here. The oh-my-zsh eza plugin adds
|
|
# a bare "--hyperlink" flag which eza (clap) treats as taking the next token as
|
|
# its optional value, so `la /` fails with "invalid value '/'". We re-enable
|
|
# hyperlinks safely below via the glued `--hyperlink=always` form.
|
|
|
|
zstyle ':completion:*' menu select
|
|
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Za-z}'
|
|
zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}"
|
|
zstyle ':completion:*' special-dirs true
|
|
|
|
source $OHMYZSH/oh-my-zsh.sh
|
|
|
|
# Re-enable eza hyperlinks safely. The oh-my-zsh eza plugin's bare
|
|
# --hyperlink flag eats the following path argument (eza clap optional-value),
|
|
# so we append the glued --hyperlink=always form to each eza alias instead.
|
|
for _ea in la ldot lD lDD ll ls lsd lsdl lS lT; do
|
|
(( $+aliases[$_ea] )) && alias "$_ea"="${aliases[$_ea]} --hyperlink=always"
|
|
done
|
|
unset _ea
|
|
|
|
# --- Tool integrations (self-configuring: enabled only when the tool exists) ---
|
|
|
|
# zoxide: frecency-based directory jumping — `z <substring>` / `zi` (fzf picker).
|
|
# Replaces nothing; `cd` still works. Auto-installed by the bootstrap.
|
|
command -v zoxide >/dev/null && eval "$(zoxide init zsh)" 2>/dev/null
|
|
|
|
# bat: colored `cat` and colored man pages. bat/batcat handled by bootstrap.
|
|
if command -v bat >/dev/null; then
|
|
alias cat='bat'
|
|
export BAT_THEME="${BAT_THEME:-Monokai Extended}"
|
|
export MANPAGER="sh -c 'col -bx | bat -l man -p'"
|
|
export MANROFFOPT='-c'
|
|
fi
|
|
|
|
# delta: prettier git diffs as git's pager (git respects GIT_PAGER). Auto-installed
|
|
# by the bootstrap. Not aliased to `diff` since delta reads diff input on stdin,
|
|
# not two file arguments — GIT_PAGER is the correct integration.
|
|
command -v delta >/dev/null && export GIT_PAGER='delta'
|
|
|
|
alias c='clear'
|
|
alias q="exit"
|
|
alias nbstat=$'netbird status --json | jq -r \'.peers.details[]? | [(.hostname // .fqdn), .netbirdIp, .status] | @tsv\' | column -t -s $\'\\t\''
|
|
alias open-ports="ss -tulpn | grep LISTEN"
|
|
alias yeet='yay -Rcs'
|
|
|
|
# Auto-update self and managed configs: checked every interactive shell start,
|
|
# silently skipped if the server is unreachable. Keeps zshrc + starship.toml in
|
|
# sync across machines (reproducible/self-configuring); only reloads the shell
|
|
# when the zshrc itself changes (starship applies its config live per render).
|
|
if [[ -o interactive ]]; then
|
|
# zshrc (reload shell if changed)
|
|
tmp=/tmp/.zshrc.$$
|
|
if curl -fsSL --connect-timeout 3 --max-time 8 "$ZSHRC_URL" -o "$tmp" 2>/dev/null \
|
|
&& [[ -f "$tmp" ]] && zsh -n "$tmp" 2>/dev/null \
|
|
&& ! cmp -s "$tmp" "$HOME/.zshrc" 2>/dev/null; then
|
|
echo "Updating zshrc..."
|
|
mv "$tmp" "$HOME/.zshrc" && exec zsh
|
|
fi
|
|
rm -f "$tmp"
|
|
|
|
# starship prompt config (overwrite if changed; applied live on next render)
|
|
if command -v starship >/dev/null; then
|
|
stmp=$(mktemp)
|
|
if curl -fsSL --connect-timeout 3 --max-time 8 "$ZSHRC_GIT/starship.toml" -o "$stmp" 2>/dev/null \
|
|
&& [[ -f "$stmp" ]] && ! cmp -s "$stmp" "$HOME/.config/starship.toml" 2>/dev/null; then
|
|
mkdir -p "$HOME/.config"
|
|
mv "$stmp" "$HOME/.config/starship.toml"
|
|
else
|
|
rm -f "$stmp"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
[[ -f $HOME/.zshrc.local ]] || touch $HOME/.zshrc.local
|
|
source $HOME/.zshrc.local
|
|
|
|
if [[ $FFENABLED != "false" && ( -o interactive || $(tty) == *"pts"* ) ]] && command -v fastfetch >/dev/null; then
|
|
fastfetch --config examples/13
|
|
fi
|