2026-02-03 18:36:21 +02:00
|
|
|
# ---- logging ---------------------------------------------------------------
|
|
|
|
|
|
2026-02-02 22:07:05 +02:00
|
|
|
log_shell_init() {
|
2026-02-05 07:32:54 +02:00
|
|
|
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
|
2026-02-02 22:07:05 +02:00
|
|
|
}
|
|
|
|
|
|
2026-02-03 18:36:21 +02:00
|
|
|
# ---- helpers ---------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
have() { command -v "$1" >/dev/null 2>&1; }
|
|
|
|
|
|
|
|
|
|
is_interactive() {
|
|
|
|
|
[[ -t 1 || -n ${PS1:-} ]]
|
2026-02-02 22:07:05 +02:00
|
|
|
}
|
|
|
|
|
|
2026-02-03 18:36:21 +02:00
|
|
|
# ---- environment sanity ----------------------------------------------------
|
2026-02-02 22:07:05 +02:00
|
|
|
|
2026-02-03 18:36:21 +02:00
|
|
|
if [[ -z ${TERM:-} || $TERM == dumb ]]; then
|
2026-02-02 22:07:05 +02:00
|
|
|
export TERM=xterm-256color
|
|
|
|
|
fi
|
|
|
|
|
|
2026-02-03 18:36:21 +02:00
|
|
|
INTERACTIVE=0
|
|
|
|
|
is_interactive && INTERACTIVE=1
|
2026-02-02 22:07:05 +02:00
|
|
|
|
2026-02-03 18:36:21 +02:00
|
|
|
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
|
2026-02-02 22:07:05 +02:00
|
|
|
PS1='\\s-\\v\\$ '
|
|
|
|
|
fi
|
|
|
|
|
|
2026-02-03 18:36:21 +02:00
|
|
|
(( INTERACTIVE )) || return 0
|
|
|
|
|
|
2026-08-28 16:05:43 +03:00
|
|
|
# ---- run-once guard --------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
# Installed as both loginShellInit (/etc/profile) and interactiveShellInit
|
|
|
|
|
# (/etc/bashrc), and /etc/profile sources /etc/bashrc, so a login shell would run
|
|
|
|
|
# this twice and register starship's hooks twice. Not exported: child shells must
|
|
|
|
|
# initialise on their own.
|
|
|
|
|
if [[ -n ${NANUQSAURUS_SHELL_INIT_DONE:-} ]]; then
|
|
|
|
|
log_shell_init "already initialised, skipping"
|
|
|
|
|
return 0
|
|
|
|
|
fi
|
|
|
|
|
NANUQSAURUS_SHELL_INIT_DONE=1
|
|
|
|
|
|
2026-02-03 18:36:21 +02:00
|
|
|
# ---- bash-preexec ----------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
if [[ -n ${BASH_VERSION:-} && -z ${bash_preexec_imported:-} && -r "@BASHPREEXEC@" ]]; then
|
|
|
|
|
# shellcheck disable=SC1090
|
|
|
|
|
. "@BASHPREEXEC@"
|
|
|
|
|
log_shell_init "bash-preexec loaded"
|
2026-02-02 22:07:05 +02:00
|
|
|
fi
|
|
|
|
|
|
2026-08-28 16:05:43 +03:00
|
|
|
# bash-preexec arms its DEBUG trap from __bp_interactive_mode, which it appends to
|
|
|
|
|
# the END of PROMPT_COMMAND -- but its lazy installer runs in the MIDDLE of the
|
|
|
|
|
# first prompt, because zoxide (below) and ghostty (~/.bashrc) append their hooks
|
|
|
|
|
# after it. Those hooks then disarm the trap again, so the first command of every
|
|
|
|
|
# session never reaches preexec and atuin never records it. PS0 is expanded once
|
|
|
|
|
# per interactive command, before the DEBUG trap, so arming there is independent of
|
|
|
|
|
# PROMPT_COMMAND ordering. Needs the non-forking ${ ...; } funsub (bash >= 5.3);
|
|
|
|
|
# older bash keeps the previous behaviour.
|
|
|
|
|
if [[ -n ${bash_preexec_imported:-} ]] &&
|
|
|
|
|
((BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 3))); then
|
|
|
|
|
# shellcheck disable=SC2016
|
|
|
|
|
__nanuq_bp_arm='${ __bp_preexec_interactive_mode=on; }'
|
|
|
|
|
[[ ${PS0-} == *"$__nanuq_bp_arm"* ]] || PS0=$__nanuq_bp_arm${PS0-}
|
|
|
|
|
unset __nanuq_bp_arm
|
|
|
|
|
log_shell_init "bash-preexec PS0 arming enabled"
|
|
|
|
|
fi
|
|
|
|
|
|
2026-02-03 18:36:21 +02:00
|
|
|
# ---- starship --------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
if have @STARSHIP@; then
|
2026-02-02 22:07:05 +02:00
|
|
|
log_shell_init "starship init"
|
2026-02-03 18:36:21 +02:00
|
|
|
case $SHELL in
|
2026-02-02 22:07:05 +02:00
|
|
|
*/bash) eval "$(@STARSHIP@ init bash)" ;;
|
|
|
|
|
*/zsh) eval "$(@STARSHIP@ init zsh)" ;;
|
|
|
|
|
esac
|
2026-08-28 16:05:43 +03:00
|
|
|
# registers starship_precmd/starship_preexec_all with bash-preexec directly
|
2026-02-02 22:07:05 +02:00
|
|
|
else
|
2026-02-03 18:36:21 +02:00
|
|
|
log_shell_init "starship skipped"
|
2026-02-02 22:07:05 +02:00
|
|
|
fi
|
|
|
|
|
|
2026-02-03 18:36:21 +02:00
|
|
|
# ---- atuin -----------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
if have @ATUIN@; then
|
|
|
|
|
log_shell_init "atuin init"
|
|
|
|
|
|
|
|
|
|
if [[ -z ${ATUIN_SESSION:-} ]]; then
|
|
|
|
|
export ATUIN_SESSION="$(@ATUIN@ uuid)"
|
2026-02-02 22:07:05 +02:00
|
|
|
ATUIN_HISTORY_ID=""
|
|
|
|
|
fi
|
2026-02-03 18:36:21 +02:00
|
|
|
|
|
|
|
|
case $SHELL in
|
2026-02-02 22:07:05 +02:00
|
|
|
*/bash) eval "$(@ATUIN@ init bash)" ;;
|
|
|
|
|
*/zsh) eval "$(@ATUIN@ init zsh)" ;;
|
|
|
|
|
esac
|
2026-08-28 16:05:43 +03:00
|
|
|
# registers __atuin_preexec/__atuin_precmd with bash-preexec itself
|
2026-02-02 22:07:05 +02:00
|
|
|
else
|
|
|
|
|
log_shell_init "atuin skipped"
|
|
|
|
|
fi
|
|
|
|
|
|
2026-02-03 18:36:21 +02:00
|
|
|
# ---- zoxide ---------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
if have zoxide; then
|
2026-02-02 22:07:05 +02:00
|
|
|
log_shell_init "zoxide init"
|
2026-02-03 18:36:21 +02:00
|
|
|
case $SHELL in
|
2026-02-02 22:07:05 +02:00
|
|
|
*/bash) eval "$(zoxide init bash)" ;;
|
|
|
|
|
*/zsh) eval "$(zoxide init zsh)" ;;
|
|
|
|
|
esac
|
2026-08-28 16:05:43 +03:00
|
|
|
# appends __zoxide_hook to PROMPT_COMMAND; see the PS0 note above
|
2026-02-02 22:07:05 +02:00
|
|
|
else
|
|
|
|
|
log_shell_init "zoxide skipped"
|
|
|
|
|
fi
|
|
|
|
|
|
2026-02-03 18:36:21 +02:00
|
|
|
# ---- aliases --------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
if have eza; then
|
2026-02-02 22:07:05 +02:00
|
|
|
alias ls='eza'
|
2026-02-03 18:36:21 +02:00
|
|
|
alias ll='eza -l --icons=auto --group-directories-first'
|
2026-02-02 22:07:05 +02:00
|
|
|
alias l1='eza -1'
|
2026-02-03 18:36:21 +02:00
|
|
|
alias l.='eza -d .*'
|
2026-02-02 22:07:05 +02:00
|
|
|
fi
|
|
|
|
|
|
2026-02-03 18:36:21 +02:00
|
|
|
if have ug; then
|
2026-02-02 22:07:05 +02:00
|
|
|
alias grep='ug'
|
|
|
|
|
alias egrep='ug -E'
|
|
|
|
|
alias fgrep='ug -F'
|
|
|
|
|
alias xzgrep='ug -z'
|
|
|
|
|
alias xzegrep='ug -zE'
|
|
|
|
|
alias xzfgrep='ug -zF'
|
|
|
|
|
fi
|
|
|
|
|
|
2026-02-03 18:36:21 +02:00
|
|
|
if have bat; then
|
2026-02-02 22:07:05 +02:00
|
|
|
alias cat='bat --style=plain --pager=never' 2>/dev/null
|
2026-02-05 07:32:54 +02:00
|
|
|
fi
|