Add git status information to prompt.

This commit is contained in:
Darren 'Tadgy' Austin 2023-10-01 17:31:19 +01:00
commit 518567cabd

124
.bashrc
View file

@ -1,5 +1,110 @@
#!/bin/bash - not strictly necessary, but helps nano with syntax highlighting.
__prompt_git_status() {
# Generate a git branch/status prompt.
# Environment variables:
# GIT_PROMPT_SHOW_TYPE=1 - Show type of repository (Bare, Shallow).
# GIT_PROMPT_SHOW_IGNORED=1 - Show a ! if the directory is ignored.
# GIT_PROMPT_SHOW_UNSTAGED=1 - Show a * if there are unstaged changes (superceeded by above).
# GIT_PROMPT_SHOW_UNTRACKED=1 - Show a ? if there are untracked files in the working directory (superceeded by above).
# GIT_PROMPT_SHOW_STASH=1 - Show a & if there is a stash in this repository (superceeded by above).
# GIT_PROMPT_SHOW_UPSTREAM=1 - Show status of this repository compaired to upstream:
# ?? - No upstream set.
# == - Working tree is equal to upstream.
# <> - Divergent from upstream.
# >> or >x - Working tree is ahead of upstream (x = commits ahead when used with next option).
# << or <x - Working tree is behind upstream (x = commits behind when used with next option).
# GIT_PROMPT_SHOW_UPSTREAM_EXTENDED=1 - In addition to upstream status, show the number of commits difference (inplies above).
local COUNT GIT_PROMPT GIT_REPO_INFO RET="$?"
# Bail out if there's no format argument given.
(( $# != 1 )) && return "$RET"
# Get some repository information.
# shellcheck disable=SC2207
GIT_REPO_INFO=( $(git rev-parse --is-bare-repository --is-shallow-repository --is-inside-git-dir --is-inside-work-tree --short HEAD 2>/dev/null) )
ERR="$?"
# Do nothing if there's an error.
(( ERR >= 1 )) || { (( ERR == 128 )) && (( ${#GIT_REPO_INFO[@]} != 3 )); } && return "$RET"
# Generate the prompt.
if [[ "${GIT_REPO_INFO[2]}" == "true" ]]; then
# If in the git directory, use a special branch marker.
GIT_PROMPT+="!GIT_DIR!"
elif [[ "${GIT_REPO_INFO[3]}" == "true" ]]; then
# If in the working directory, generate the prompt.
# Add status markers.
[[ -n "$GIT_PROMPT_SHOW_TYPE" ]] && {
if [[ "${GIT_REPO_INFO[0]}" == "true" ]]; then
GIT_PROMPT+="B:"
elif [[ "${GIT_REPO_INFO[1]}" == "true" ]]; then
GIT_PROMPT+="S:"
fi
}
# Add the branch.
GIT_PROMPT+="$(git describe --contains --all HEAD)"
# Add a marker if directory is ignored, there's untracked files or a stash.
if [[ -n "$GIT_PROMPT_SHOW_IGNORED" ]] && git check-ignore -q "${PWD#"$(git rev-parse --show-toplevel)/"}"; then
GIT_PROMPT+=" !"
elif [[ -n "$GIT_PROMPT_SHOW_UNSTAGED" ]] && git ls-files --modified --exclude-standard --directory --error-unmatch -- ':/*' >/dev/null 2>&1; then
GIT_PROMPT+=" *"
elif [[ -n "$GIT_PROMPT_SHOW_UNTRACKED" ]] && git ls-files --others --exclude-standard --directory --error-unmatch -- ':/*' >/dev/null 2>&1; then
GIT_PROMPT+=" ?"
elif [[ -n "$GIT_PROMPT_SHOW_STASH" ]] && git rev-parse --verify --quiet refs/stash >/dev/null; then
GIT_PROMPT+=" &"
fi
# Get upstream status.
[[ -n "$GIT_PROMPT_SHOW_UPSTREAM" ]] || [[ -n "$GIT_PROMPT_SHOW_UPSTREAM_EXTENDED" ]] && {
COUNT="$(git rev-list --count --left-right '@{upstream}'...HEAD 2>/dev/null | tr '[:blank:]' ' ')"
case "$COUNT" in
"")
# No upstream.
GIT_PROMPT+=" ??"
;;
"0 0")
# Equal to upstream.
GIT_PROMPT+=" =="
;;
"0 "*)
# Ahead of upstream.
GIT_PROMPT+=" >"
if [[ -n "$GIT_PROMPT_SHOW_UPSTREAM_EXTENDED" ]]; then
# Show the number of the difference.
GIT_PROMPT+="${COUNT#0 }"
else
GIT_PROMPT+=">"
fi
;;
*" 0")
# Behind upstream.
GIT_PROMPT+=" <"
if [[ -n "$GIT_PROMPT_SHOW_UPSTREAM_EXTENDED" ]]; then
# Show the number of the difference.
GIT_PROMPT+="${COUNT% 0}"
else
GIT_PROMPT+="<"
fi
;;
*)
# Divergent from upstream.
GIT_PROMPT+=" <>"
;;
esac
}
fi
# Output the prompt.
# shellcheck disable=SC2059
printf -- "$1" "$GIT_PROMPT"
# Return the original error code.
return "$RET"
}
__find_ssh_agent_sock() {
# Find an *active* ssh agent socket.
# Returns: 0 = Found an active socket.
@ -248,6 +353,18 @@ else
COLOUR=5 # Purple
fi
# The commands to execute before the prompt is displayed.
PROMPT_COMMAND="__ssh_agent_prompt_command"
# Git prompt options.
GIT_PROMPT_SHOW_TYPE=1
GIT_PROMPT_SHOW_IGNORED=1
GIT_PROMPT_SHOW_UNSTAGED=1
GIT_PROMPT_SHOW_UNTRACKED=1
GIT_PROMPT_SHOW_STASH=1
GIT_PROMPT_SHOW_UPSTREAM=1
GIT_PROMPT_SHOW_UPSTREAM_EXTENDED=1
# Version specific set up.
if (( BASH_VERSINFO[0] >= 4 )); then
# Add to the shopts.
@ -256,12 +373,12 @@ if (( BASH_VERSINFO[0] >= 4 )); then
# Trim the path in the prompt.
PROMPT_DIRTRIM=2
# Coloured username + host + directory:
PS1="[\[$(tput bold)$(tput setaf "$COLOUR")\]\u\[$(tput sgr0)\]@\[$(tput bold)$(tput setaf 3)\]\h\[$(tput sgr0)\]] \[$(tput bold)$(tput setaf 4)\]\w\[$(tput sgr0)\] ->"
PS1='[\[$(tput bold)$(tput setaf "$COLOUR")\]\u\[$(tput sgr0)\]@\[$(tput bold)$(tput setaf 3)\]\h\[$(tput sgr0)\]] \[$(tput bold)$(tput setaf 4)\]\w\[$(tput sgr0)\]$(__prompt_git_status "\[\033[0;35;40m\] (%s)\[\033[0;37;40m\]") ->'
else
# Set the prompts.
# Coloured username + host + directory:
# shellcheck disable=SC2154
PS1="[\[$(tput bold)$(tput setaf "$COLOUR")\]\u\[$(tput sgr0)\]@\[$(tput bold)$(tput setaf 3)\]\h\[$(tput sgr0)\]] \[$(tput bold)$(tput setaf 4)\]\$(echo \"\${PWD/#\$HOME/~}\" | awk -F/ '{if (NF>3) {printf \".../\" \$(NF-1) \"/\" \$NF} else {printf \$0}}')\[$(tput sgr0)\] ->"
PS1="[\[$(tput bold)$(tput setaf "$COLOUR")\]\u\[$(tput sgr0)\]@\[$(tput bold)$(tput setaf 3)\]\h\[$(tput sgr0)\]] \[$(tput bold)$(tput setaf 4)\]\$(echo \"\${PWD/#\$HOME/~}\" | awk -F/ '{if (NF>3) {printf \".../\" \$(NF-1) \"/\" \$NF} else {printf \$0}}')\[$(tput sgr0)\]$(__prompt_git_status "\[\033[0;35;40m\] (%s)\[\033[0;37;40m\]") ->"
fi
unset COLOUR
@ -269,9 +386,6 @@ unset COLOUR
# shellcheck disable=SC2155
export PS4="+(\[\e[1;33;40m\]\$?\[$(tput sgr0)\]) \[$(tput bold)$(tput setaf 4)\]\${BASH_SOURCE##*/}\[$(tput sgr0)\]\${FUNCNAME[0]:+(\[$(tput bold)$(tput setaf 2)\]\${FUNCNAME[0]}\[$(tput sgr0)\])}:\[$(tput bold)$(tput setaf 1)\]\$LINENO\[$(tput sgr0)\]: "
# The commands to execute before the prompt is displayed.
PROMPT_COMMAND="__ssh_agent_prompt_command"
# Common aliases.
hash bc >/dev/null 2>&1 && alias bc='bc -lq'
hash diff >/dev/null 2>&1 && alias diff='diff --color=auto -u'