shell-integration: automatic bash integration

This change adds automatic bash shell detection and integration.

Unlike our other shell integrations, bash doesn't provide a built-in
mechanism for injecting our ghostty.bash script into the new shell
environment.

Instead, we start bash in POSIX mode and use the ENV environment
variable to load our integration script, and the rest of the bash
startup sequence becomes the responsibility of our script to emulate
(along with disabling POSIX mode).
This commit is contained in:
Jon Parise
2024-05-05 13:24:09 -07:00
parent 2e2d924353
commit 73b3560e62
4 changed files with 421 additions and 54 deletions

View File

@@ -13,6 +13,66 @@
if [[ "$-" != *i* ]] ; then builtin return; fi
if [ -z "$GHOSTTY_RESOURCES_DIR" ]; then builtin return; fi
# When automatic shell integration is active, we need to manually
# load the normal bash startup files based on the injected state.
if [ -n "$GHOSTTY_BASH_INJECT" ]; then
builtin declare ghostty_bash_inject="$GHOSTTY_BASH_INJECT"
builtin unset GHOSTTY_BASH_INJECT ENV
# At this point, we're in POSIX mode and rely on the injected
# flags to guide is through the rest of the startup sequence.
# POSIX mode was requested by the user so there's nothing
# more to do that optionally source their original $ENV.
# No other startup files are read, per the standard.
if [[ "$ghostty_bash_inject" == *"--posix"* ]]; then
if [ -n "$GHOSTTY_BASH_ENV" ]; then
builtin source "$GHOSTTY_BASH_ENV"
builtin export ENV="$GHOSTTY_BASH_ENV"
fi
else
# Restore bash's default 'posix' behavior. Also reset 'inherit_errexit',
# which doesn't happen as part of the 'posix' reset.
builtin set +o posix
builtin shopt -u inherit_errexit 2>/dev/null
# Unexport HISTFILE if it was set by the shell integration code.
if [[ -n "$GHOSTTY_BASH_UNEXPORT_HISTFILE" ]]; then
builtin export -n HISTFILE
builtin unset GHOSTTY_BASH_UNEXPORT_HISTFILE
fi
# Manually source the startup files, respecting the injected flags like
# --norc and --noprofile that we parsed with the shell integration code.
#
# See also: run_startup_files() in shell.c in the Bash source code
if builtin shopt -q login_shell; then
if [[ $ghostty_bash_inject != *"--noprofile"* ]]; then
[ -r /etc/profile ] && builtin source "/etc/profile"
for rcfile in "$HOME/.bash_profile" "$HOME/.bash_login" "$HOME/.profile"; do
[ -r "$rcfile" ] && { builtin source "$rcfile"; break; }
done
fi
else
if [[ $ghostty_bash_inject != *"--norc"* ]]; then
# The location of the system bashrc is determined at bash build
# time via -DSYS_BASHRC and can therefore vary across distros:
# Arch, Debian, Ubuntu use /etc/bash.bashrc
# Fedora uses /etc/bashrc sourced from ~/.bashrc instead of SYS_BASHRC
# Void Linux uses /etc/bash/bashrc
for rcfile in /etc/bash.bashrc /etc/bash/bashrc ; do
[ -r "$rcfile" ] && { builtin source "$rcfile"; break; }
done
if [[ -z "$GHOSTTY_BASH_RCFILE" ]]; then GHOSTTY_BASH_RCFILE="$HOME/.bashrc"; fi
[ -r "$GHOSTTY_BASH_RCFILE" ] && builtin source "$GHOSTTY_BASH_RCFILE"
fi
fi
fi
builtin unset GHOSTTY_BASH_ENV GHOSTTY_BASH_RCFILE
builtin unset ghostty_bash_inject rcfile
fi
# Import bash-preexec, safe to do multiple times
builtin source "$GHOSTTY_RESOURCES_DIR/shell-integration/bash/bash-preexec.sh"