main/modules/30-shell-zsh.sh

119 lines
4.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# 30-shell-zsh — zsh + oh-my-zsh + plugins, set as default shell, drop our config.
step_name="shell-zsh"
step_desc="zsh + oh-my-zsh + plugins, set default shell, ship config"
step_run="run_zsh"
# All paths resolve against the config TARGET (set by 05-create-user).
# NOTE: we deliberately do NOT honor an inherited $ZSH env var — oh-my-zsh exports
# ZSH when it loads, so a setup.sh run from an omz-equipped shell would otherwise
# pin these to the *old* home (e.g. /root) while the chown step retargets to the
# *new* user, mis-owning the wrong tree (the 'insecure completion dirs' bug).
ZSH="$TARGET_HOME/.oh-my-zsh"
ZSH_CUSTOM="$ZSH/custom"
ZDOTDIR_TARGET="$TARGET_HOME/.config/zsh"
run_zsh() {
log "installing zsh + oh-my-zsh"
_install_zsh
_install_omz
_install_plugins
_chown_target_tree
_ship_config
_set_default_shell
if [[ "$TARGET_USER" != "$USER" ]]; then
log "zsh ready. Start it as $TARGET_USER: sudo -iu $TARGET_USER"
else
ok "zsh ready — start it with: exec zsh"
fi
}
_chown_target_tree() {
# when running as root for a created user, make omz + plugins + config owned by them
if [[ "$TARGET_USER" == "$USER" ]]; then return; fi
local grp; grp="$(id -gn "$TARGET_USER" 2>/dev/null || echo "$TARGET_USER")"
chown -R "$TARGET_USER:$grp" "$ZSH" "$ZDOTDIR_TARGET" "$TARGET_HOME/.zshrc" 2>/dev/null || true
}
_install_zsh() {
if command -v zsh >/dev/null 2>&1; then ok "zsh already installed"; return; fi
case "$DISTRO" in
arch) sudo_ pacman -Sy --noconfirm --needed zsh ;;
debian) sudo_ apt-get install -y zsh ;;
esac
}
_install_omz() {
if [[ -d "$ZSH/.git" ]]; then ok "oh-my-zsh already present"; return; fi
# clone directly (skip the upstream installer so we keep .zshrc under our control)
rm -rf "$ZSH"
git clone --depth=1 https://github.com/ohmyzsh/ohmyzsh.git "$ZSH"
ok "oh-my-zsh cloned to $ZSH"
}
_install_plugins() {
mkdir -p "$ZSH_CUSTOM/plugins"
_clone_plugin zsh-users/zsh-autosuggestions "$ZSH_CUSTOM/plugins/zsh-autosuggestions"
_clone_plugin zsh-users/zsh-syntax-highlighting "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting"
_clone_plugin zsh-users/zsh-completions "$ZSH_CUSTOM/plugins/zsh-completions"
_clone_plugin zsh-users/zsh-history-substring-search "$ZSH_CUSTOM/plugins/history-substring-search"
_clone_plugin Aloxaf/fzf-tab "$ZSH_CUSTOM/plugins/fzf-tab"
}
_clone_plugin() { # repo dest
local repo="$1" dest="$2"
if [[ -d "$dest/.git" ]]; then return; fi
git clone --depth=1 "https://github.com/$repo.git" "$dest" \
|| warn "failed to clone $repo"
}
_ship_config() {
log "shipping zsh config to $ZDOTDIR_TARGET"
mkdir -p "$ZDOTDIR_TARGET"
local f
for f in zshrc aliases.zsh functions.zsh path.zsh plugins.zsh; do
local src="$BOOT_DIR/config/zsh/$f"
[[ -f "$src" ]] || continue
local dst="$ZDOTDIR_TARGET/$f"
[[ -f "$dst" ]] && cp "$dst" "${dst}.bak.$(date +%Y%m%d-%H%M%S)"
cp "$src" "$dst"
done
# aliases-extras.zsh is user-owned: only seed it if absent
if [[ ! -f "$ZDOTDIR_TARGET/aliases-extras.zsh" ]]; then
cp "$BOOT_DIR/config/zsh/aliases-extras.zsh" "$ZDOTDIR_TARGET/aliases-extras.zsh"
fi
# ~/.zshrc shim that loads our real config via ZDOTDIR
local shim="$TARGET_HOME/.zshrc"
if ! grep -q 'BOOTSTRAP ZDOTDIR' "$shim" 2>/dev/null; then
cat >> "$shim" <<'EOF'
# BOOTSTRAP ZDOTDIR — real config lives in ~/.config/zsh
export ZDOTDIR="${ZDOTDIR:-$HOME/.config/zsh}"
[[ -f "$ZDOTDIR/zshrc" ]] && source "$ZDOTDIR/zshrc"
EOF
fi
# ensure the whole shipped tree is owned by the target user
if [[ "$TARGET_USER" != "$USER" ]]; then
chown -R "$TARGET_USER:$(id -gn "$TARGET_USER" 2>/dev/null || echo "$TARGET_USER")" "$ZDOTDIR_TARGET" "$shim"
fi
ok "zsh config installed ($ZDOTDIR_TARGET) + $shim shim"
}
_set_default_shell() {
local zsh_bin; zsh_bin="$(command -v zsh || true)"
[[ -z "$zsh_bin" ]] && { warn "zsh not on PATH — skipping chsh"; return; }
# ensure listed in /etc/shells
if ! grep -qx "$zsh_bin" /etc/shells 2>/dev/null; then
echo "$zsh_bin" | sudo_ tee -a /etc/shells >/dev/null
fi
if [[ "$(getent passwd "$TARGET_USER" | cut -d: -f7)" != "$zsh_bin" ]]; then
if yn "Set zsh as default login shell for $TARGET_USER?" y; then
sudo_ chsh -s "$zsh_bin" "$TARGET_USER" && ok "default shell set to zsh for $TARGET_USER"
else
warn "zsh not set as default — run 'chsh -s $zsh_bin' for $TARGET_USER' later"
fi
else
ok "zsh already the default shell for $TARGET_USER"
fi
}