The goal is to have a
PS1
that dynamically reacts to various aspects of my environment.
$
with the exit status of the last commandHere's my full PS1
export UNDERLINE=$(tput sgr 0 1)
export BOLD=$(tput bold)
export BLACK=$(tput setaf 0)
export RED=$(tput setaf 1)
export GREEN=$(tput setaf 2)
export YELLOW=$(tput setaf 3)
export BLUE=$(tput setaf 4)
export PURPLE=$(tput setaf 5)
export CYAN=$(tput setaf 6)
export WHITE=$(tput setaf 7)
export RESET=$(tput sgr0)
##################################################################################################
# Set the base $PS1 to include username, hostname, and full working directory
##################################################################################################
PS1="\u@\h \[${GREEN}\]\w"
##################################################################################################
# If this is an xterm set the title to user@host:dir
##################################################################################################
if [[ -z "${debian_chroot:-}" && -r /etc/debian_chroot ]]; then
debian_chroot=$(cat /etc/debian_chroot)
fi
case "$TERM" in
xterm* | rxvt*)
# Prepends title thingy to $PS1
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
;;
*) ;;
esac
##################################################################################################
# Add a colored (VPN) to the beginning if VPN is running and connected
#
# VPN_GATEWAY should be set in a non-vcs tracked ./bashrc.d/ file to determine if the VPN is
# connected.
##################################################################################################
__vpn_connection_status() {
OLD_EXIT_STATUS=$?
if [[ -z "$VPN_GATEWAY" ]]; then
return $OLD_EXIT_STATUS
fi
# Check if there's a route to the gateway that goes through a 'tun' device
if ip route get "$VPN_GATEWAY" | grep tun >/dev/null; then
echo -en "${GREEN}"
else
echo -en "${RED}"
fi
return $OLD_EXIT_STATUS
}
__vpn_running() {
OLD_EXIT_STATUS=$?
if pgrep openconnect >/dev/null; then
echo -n "(VPN) "
fi
return $OLD_EXIT_STATUS
}
PS1="\[\$(__vpn_connection_status)\]\$(__vpn_running)\[${RESET}\]${PS1}"
##################################################################################################
# Indicate that your shell is polluted by a Yocto SDK toolchain environment
##################################################################################################
__yocto_sysroot_ps1() {
OLD_EXIT_STATUS=$?
if [[ -n "$OECORE_TARGET_SYSROOT" ]]; then
echo -n "[$(basename "$OECORE_TARGET_SYSROOT")] "
fi
return $OLD_EXIT_STATUS
}
PS1="\[${YELLOW}\]\$(__yocto_sysroot_ps1)\[${RESET}\]${PS1}"
##################################################################################################
# If connected over SSH, prepend a red (ssh)
##################################################################################################
__is_ssh() {
if [[ -n "$SSH_CLIENT" || -n "$SSH_TTY" ]]; then
return 0
else
case $(ps -o comm= -p $PPID) in
sshd | */sshd) return 0 ;;
esac
fi
return 1
}
if __is_ssh; then
PS1="\[${BOLD}${RED}\](\[${RESET}${RED}\]ssh\[${BOLD}\]) \[${RESET}\]${PS1}"
fi
##################################################################################################
# If connected over a serial port, prepend a red (serial)
##################################################################################################
__is_serial() {
case "$(tty)" in
/dev/tty[0-9])
# local console
return 1
;;
/dev/tty[a-zA-Z]*[0-9])
# serial console
return 0
;;
*)
# Likely a /dev/pty/ pseudo terminal
return 1
;;
esac
}
if __is_serial; then
PS1="\[${BOLD}${RED}\](\[${RESET}${RED}\]serial\[${BOLD}\]) \[${RESET}\]${PS1}"
fi
##################################################################################################
# Add the __git_ps1 from /usr/share/git-core/contrib/completion/git-prompt.sh
##################################################################################################
function_exists() {
declare -f -F "$1" >/dev/null
return $?
}
# See https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh for more details.
export GIT_PS1_SHOWDIRTYSTATE=1 # Adds '*' and '+' for unstaged and staged changes
export GIT_PS1_DESCRIBE_STYLE='branch' # When in a detached head state, attempt to find the branch HEAD is on.
export GIT_PS1_SHOWCOLORHINTS=1 # Use colored output to indicate the current status ('git status -sb'). Only works if __git_ps1 is used from PROMPT_COMMAND, not PS1.
export GIT_PS1_SHOWSTASHSTATE=1 # Show a '$' next to the branch name if something is stashed.
export GIT_PS1_SHOWUNTRACKEDFILES=1 # Show a '%' next to the branch name if there are untracked files.
export GIT_PS1_SHOWUPSTREAM='auto' # '=' means up to date with upstream, '<' means you're behind, and '>' means you're ahead. '<>' means you've diverged.
if function_exists __git_ps1; then
PS1="${PS1}\[${BLUE}\]\$(__git_ps1)\[${RESET}\]"
fi
##################################################################################################
# List the number of background jobs
##################################################################################################
__list_background_jobs() {
OLD_EXIT_STATUS=$?
NUM_BACKGROUND_JOBS=$(jobs | wc -l)
if [[ "$NUM_BACKGROUND_JOBS" -gt 0 ]]; then
echo -n " [$NUM_BACKGROUND_JOBS]"
fi
return $OLD_EXIT_STATUS
}
PS1="${PS1}\$(__list_background_jobs)"
##################################################################################################
# Color the $ sign based on the exit status of the last command
#
# Requires each of the \$(foo) functions that the PS1 invokes do not clobber the exit status:
#
# OLD_EXIT_STATUS=$?
# ...
# return $OLD_EXIT_STATUS
##################################################################################################
__decorate_exit_status() {
if [[ $? -eq 0 ]]; then
echo -en "${WHITE}"
else
echo -en "${BOLD}${RED}"
fi
}
PS1="${PS1} \[\$(__decorate_exit_status)\]\$\[${RESET}\] "
##################################################################################################
# Add the +side-by-side feature to delta when the terminal is wide enough
##################################################################################################
__delta_side_by_side_width() {
local columns
columns=$(tput cols)
# Enough room for two side-by-side 80-char diffs with some room for line numbers to spare
if [[ "$columns" -ge 170 ]]; then
export DELTA_FEATURES="+side-by-side"
else
export DELTA_FEATURES=""
fi
}
PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}__delta_side_by_side_width"