nanuqsaurus/scripts/shell-init.sh
randogoth b7bb444f3d fix(shell): let bash-preexec install last so atuin preexec fires
Eagerly calling __bp_install at source time made bash-preexec install
before starship/atuin/zoxide/ghostty modified PROMPT_COMMAND, so their
hooks landed after __bp_interactive_mode. bash-preexec then never marked
typed commands as interactive and skipped preexec_functions, so atuin's
__atuin_preexec never fired and history stopped recording
(ATUIN_PREEXEC_BACKEND stuck at "<shlvl>:none").

Remove the eager __bp_install and the manual PROMPT_COMMAND/array wiring
for starship, atuin and zoxide; each tool registers with bash-preexec
itself, and deferred install on the first prompt keeps
__bp_interactive_mode last (verified against bash-preexec 0.6.0).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 16:13:30 +03:00

121 lines
3.5 KiB
Bash

# ---- logging ---------------------------------------------------------------
log_shell_init() {
local uid="${UID:-}"
[[ -n "$uid" ]] || uid="$(id -u 2>/dev/null || echo unknown)"
# Override with:
# export NANUQSAURUS_SHELL_INIT_LOG_FILE=/path/to/log
local log_file="${NANUQSAURUS_SHELL_INIT_LOG_FILE:-/tmp/shell-init-${uid}.log}"
printf '%s\n' "shell-init: $*" >>"$log_file" 2>/dev/null || true
}
# ---- helpers ---------------------------------------------------------------
have() { command -v "$1" >/dev/null 2>&1; }
is_interactive() {
[[ -t 1 || -n ${PS1:-} ]]
}
# ---- environment sanity ----------------------------------------------------
if [[ -z ${TERM:-} || $TERM == dumb ]]; then
export TERM=xterm-256color
fi
INTERACTIVE=0
is_interactive && INTERACTIVE=1
log_shell_init "TERM=$TERM PS1=${PS1:-<empty>} SHELL=$SHELL interactive=$INTERACTIVE"
# Ensure PS1 exists so downstream init blocks run
if (( INTERACTIVE )) && [[ -z ${PS1:-} ]]; then
PS1='\\s-\\v\\$ '
fi
(( INTERACTIVE )) || return 0
# ---- bash-preexec ----------------------------------------------------------
if [[ -n ${BASH_VERSION:-} && -z ${bash_preexec_imported:-} && -r "@BASHPREEXEC@" ]]; then
# shellcheck disable=SC1090
. "@BASHPREEXEC@"
# Do NOT call __bp_install here. bash-preexec must install on the FIRST prompt,
# after starship/atuin/zoxide/ghostty have modified PROMPT_COMMAND, so that
# __bp_interactive_mode stays the LAST PROMPT_COMMAND entry. Installing eagerly
# lets later hooks land after it and silently breaks preexec (atuin recording).
log_shell_init "bash-preexec loaded"
fi
# ---- starship --------------------------------------------------------------
if have @STARSHIP@; then
log_shell_init "starship init"
case $SHELL in
*/bash) eval "$(@STARSHIP@ init bash)" ;;
*/zsh) eval "$(@STARSHIP@ init zsh)" ;;
esac
# starship's bash init registers starship_precmd/starship_preexec_all with
# bash-preexec directly; no manual PROMPT_COMMAND wiring needed.
else
log_shell_init "starship skipped"
fi
# ---- atuin -----------------------------------------------------------------
if have @ATUIN@; then
log_shell_init "atuin init"
if [[ -z ${ATUIN_SESSION:-} ]]; then
export ATUIN_SESSION="$(@ATUIN@ uuid)"
ATUIN_HISTORY_ID=""
fi
case $SHELL in
*/bash) eval "$(@ATUIN@ init bash)" ;;
*/zsh) eval "$(@ATUIN@ init zsh)" ;;
esac
# atuin's init registers __atuin_preexec/__atuin_precmd with bash-preexec
# itself; manual array wiring only caused duplicate hook entries.
else
log_shell_init "atuin skipped"
fi
# ---- zoxide ---------------------------------------------------------------
if have zoxide; then
log_shell_init "zoxide init"
case $SHELL in
*/bash) eval "$(zoxide init bash)" ;;
*/zsh) eval "$(zoxide init zsh)" ;;
esac
# zoxide's bash init hooks into bash-preexec (precmd_functions) when it is
# present; manual PROMPT_COMMAND wiring only pushed hooks past
# __bp_interactive_mode and broke preexec ordering.
else
log_shell_init "zoxide skipped"
fi
# ---- aliases --------------------------------------------------------------
if have eza; then
alias ls='eza'
alias ll='eza -l --icons=auto --group-directories-first'
alias l1='eza -1'
alias l.='eza -d .*'
fi
if have ug; then
alias grep='ug'
alias egrep='ug -E'
alias fgrep='ug -F'
alias xzgrep='ug -z'
alias xzegrep='ug -zE'
alias xzfgrep='ug -zF'
fi
if have bat; then
alias cat='bat --style=plain --pager=never' 2>/dev/null
fi