177 lines
6.6 KiB
Bash
177 lines
6.6 KiB
Bash
# This is originally based on the recommended bash integration from
|
|
# the semantic prompts proposal as well as some logic from Kitty's
|
|
# bash integration.
|
|
#
|
|
# I'm not a bash expert so this probably has some major issues but for
|
|
# my simple bash usage this is working. If a bash expert wants to
|
|
# improve this please do!
|
|
|
|
# We need to be in interactive mode and we need to have the Ghostty
|
|
# resources dir set which also tells us we're running in Ghostty.
|
|
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
|
|
# Nixos uses /etc/bashrc
|
|
for rcfile in /etc/bash.bashrc /etc/bash/bashrc /etc/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"
|
|
|
|
# This is set to 1 when we're executing a command so that we don't
|
|
# send prompt marks multiple times.
|
|
_ghostty_executing=""
|
|
_ghostty_last_reported_cwd=""
|
|
|
|
function __ghostty_get_current_command() {
|
|
builtin local last_cmd
|
|
# shellcheck disable=SC1007
|
|
last_cmd=$(HISTTIMEFORMAT= builtin history 1)
|
|
last_cmd="${last_cmd#*[[:digit:]]*[[:space:]]}" # remove leading history number
|
|
last_cmd="${last_cmd#"${last_cmd%%[![:space:]]*}"}" # remove remaining leading whitespace
|
|
builtin printf "\e]2;%s\a" "${last_cmd//[[:cntrl:]]}" # remove any control characters
|
|
}
|
|
|
|
function __ghostty_precmd() {
|
|
local ret="$?"
|
|
if test "$_ghostty_executing" != "0"; then
|
|
_GHOSTTY_SAVE_PS0="$PS0"
|
|
_GHOSTTY_SAVE_PS1="$PS1"
|
|
_GHOSTTY_SAVE_PS2="$PS2"
|
|
|
|
# Marks
|
|
PS1=$PS1'\[\e]133;B\a\]'
|
|
PS2=$PS2'\[\e]133;B\a\]'
|
|
|
|
# bash doesn't redraw the leading lines in a multiline prompt so
|
|
# mark the last line as a secondary prompt (k=s) to prevent the
|
|
# preceding lines from being erased by ghostty after a resize.
|
|
if [[ "${PS1}" == *"\n"* || "${PS1}" == *$'\n'* ]]; then
|
|
PS1=$PS1'\[\e]133;A;k=s\a\]'
|
|
fi
|
|
|
|
# Cursor
|
|
if test "$GHOSTTY_SHELL_INTEGRATION_NO_CURSOR" != "1"; then
|
|
PS1=$PS1'\[\e[5 q\]'
|
|
PS0=$PS0'\[\e[0 q\]'
|
|
fi
|
|
|
|
# Sudo
|
|
if [[ "$GHOSTTY_SHELL_INTEGRATION_NO_SUDO" != "1" ]] && [[ -n "$TERMINFO" ]]; then
|
|
# Wrap `sudo` command to ensure Ghostty terminfo is preserved
|
|
# shellcheck disable=SC2317
|
|
sudo() {
|
|
builtin local sudo_has_sudoedit_flags="no"
|
|
for arg in "$@"; do
|
|
# Check if argument is '-e' or '--edit' (sudoedit flags)
|
|
if [[ "$arg" == "-e" || $arg == "--edit" ]]; then
|
|
sudo_has_sudoedit_flags="yes"
|
|
builtin break
|
|
fi
|
|
# Check if argument is neither an option nor a key-value pair
|
|
if [[ "$arg" != -* && "$arg" != *=* ]]; then
|
|
builtin break
|
|
fi
|
|
done
|
|
if [[ "$sudo_has_sudoedit_flags" == "yes" ]]; then
|
|
builtin command sudo "$@";
|
|
else
|
|
builtin command sudo TERMINFO="$TERMINFO" "$@";
|
|
fi
|
|
}
|
|
fi
|
|
|
|
if [[ "$GHOSTTY_SHELL_INTEGRATION_NO_TITLE" != 1 ]]; then
|
|
# Command and working directory
|
|
# shellcheck disable=SC2016
|
|
PS0=$PS0'$(__ghostty_get_current_command)'
|
|
PS1=$PS1'\[\e]2;$PWD\a\]'
|
|
fi
|
|
fi
|
|
|
|
if test "$_ghostty_executing" != ""; then
|
|
# End of current command. Report its status.
|
|
builtin printf "\e]133;D;%s;aid=%s\a" "$ret" "$BASHPID"
|
|
fi
|
|
|
|
# unfortunately bash provides no hooks to detect cwd changes
|
|
# in particular this means cwd reporting will not happen for a
|
|
# command like cd /test && cat. PS0 is evaluated before cd is run.
|
|
if [[ "$_ghostty_last_reported_cwd" != "$PWD" ]]; then
|
|
_ghostty_last_reported_cwd="$PWD"
|
|
builtin printf "\e]7;kitty-shell-cwd://%s%s\a" "$HOSTNAME" "$PWD"
|
|
fi
|
|
|
|
# Fresh line and start of prompt.
|
|
builtin printf "\e]133;A;aid=%s\a" "$BASHPID"
|
|
_ghostty_executing=0
|
|
}
|
|
|
|
function __ghostty_preexec() {
|
|
PS0="$_GHOSTTY_SAVE_PS0"
|
|
PS1="$_GHOSTTY_SAVE_PS1"
|
|
PS2="$_GHOSTTY_SAVE_PS2"
|
|
builtin printf "\e]133;C;\a"
|
|
_ghostty_executing=1
|
|
}
|
|
|
|
preexec_functions+=(__ghostty_preexec)
|
|
precmd_functions+=(__ghostty_precmd)
|