Skip to content

Instantly share code, notes, and snippets.

@michaelbaudino
Last active August 30, 2021 08:57
Show Gist options
  • Save michaelbaudino/4168015 to your computer and use it in GitHub Desktop.
Save michaelbaudino/4168015 to your computer and use it in GitHub Desktop.
Bash prompt with GIT branch and status display
### Michael Baudino <michael.baudino@alpine-lab.com>
### License: WTFPL
###
### To use this fancy prompt:
### 1. copy this file as ~/.git-in-prompt.sh
### 2. add the following line to your ~/.bashrc file:
### [[ -s "$HOME/.git-in-prompt.sh" ]] && source "$HOME/.git-in-prompt.sh"
### 3. enjoy :-)
###
# Configure colors
# (from https://gist.github.com/3109854)
# (see full ANSI colors posibilities at https://misc.flogisoft.com/bash/tip_colors_and_formatting)
c_reset='\e[0m'
c_black='\e[0;30m'
c_red='\e[0;31m'
c_green='\e[0;32m'
c_yellow='\e[0;33m'
c_blue='\e[0;34m'
c_purple='\e[0;35m'
c_cyan='\e[0;36m'
c_lightgray='\e[0;37m'
c_darkgray='\e[0;90m'
c_lightred='\e[0;91m'
c_lightgreen='\e[0;92m'
c_lightyellow='\e[0;93m'
c_lightblue='\e[0;94m'
c_lightmagenta='\e[0;95m'
c_lightcyan='\e[0;96m'
c_white='\e[0;97m'
is_git_repository() {
git rev-parse &> /dev/null
}
print_git_part() {
local branch_name=$(git rev-parse --abbrev-ref HEAD)
dashline() {
printf '%*s' $1 | tr ' ' '-'
}
ahead_arrow() {
local commits_ahead=$(git rev-list --count refs/remotes/origin/${branch_name}..refs/heads/${branch_name})
[ 0 -eq ${commits_ahead} ] \
&& local color=${c_lightgray} \
|| local color=${c_green}
echo -e "${color}$(dashline $commits_ahead)> $commits_ahead$c_reset"
}
behind_arrow() {
local commits_behind=$(git rev-list --count refs/heads/${branch_name}..refs/remotes/origin/${branch_name})
[ 0 -eq ${commits_behind} ] \
&& local color=${c_lightgray} \
|| local color=${c_red}
echo -e "${color}${commits_behind} <$(dashline ${commits_behind})${c_reset}"
}
branch_part() {
if [ -z "$(git status --porcelain)" ]; then
local color=${c_green}
else
if [ -z "$(git status --porcelain --untracked-files=no)" ]; then
local color=${c_yellow}
else
local color=${c_red}
fi
fi
echo "${color}${branch_name}${c_reset}"
}
distance_to_origin_part() {
if branch_exists_on_origin; then
echo -e "$(behind_arrow)${c_darkgray}|${c_reset}$(ahead_arrow)"
else
echo -e "${c_yellow}<not on origin>${c_reset}"
fi
}
detached_head() {
! git symbolic-ref --quiet HEAD &> /dev/null
}
branch_exists_on_origin() {
git show-ref --quiet refs/remotes/origin/${branch_name}
}
current_commit() {
git rev-parse --short HEAD
}
current_commit_with_tags() {
local color=$1
echo -ne "${color}$(current_commit)"
git tag --points-at HEAD | while read -r tag; do
echo -ne "${c_reset}|${color}${tag}"
done
}
if detached_head; then
echo -e "${c_darkgray}[${c_reset}${c_yellow}<detached>${c_reset}@$(current_commit_with_tags ${c_purple})${c_reset}${c_darkgray}]"
else
echo -e "${c_darkgray}[${c_reset}$(branch_part)${c_darkgray}] [${c_reset}$(distance_to_origin_part)${c_darkgray}]${c_reset}"
fi
}
# Function that prints the pre prompt (a line actually displaying all the important information)
print_pre_prompt ()
{
# Create left and right parts
local left_part="${c_darkgray}$(hostname) ${c_cyan}$(pwd | sed "s#$HOME#~#")${c_reset}"
local right_part=$(is_git_repository && print_git_part)
# Compute their lengths without color codes characters
local left_part_length=$(echo -ne ${left_part} | sed -r 's:\x1B\[[0-9;]*[mK]::g' | wc -c)
local right_part_length=$(echo -ne ${right_part} | sed -r 's:\x1B\[[0-9;]*[mK]::g' | wc -c)
# Compute length between left and right parts
local middle_space_length=$((${COLUMNS:-$(tput cols)}-${left_part_length}-${right_part_length}))
# This will be executed prior to prompt rendering
# (we basically print the left prompt, some spaces, then the right prompt)
printf "%b%${middle_space_length}b%b\n" "${left_part}" " " "${right_part}"
}
set_prompt_symbol ()
{
# Decide prompt color and value according to previous command status
if [ "$?" = "0" ]; then
PS1="\[${c_lightyellow}\]→\[${c_reset}\] "
else
PS1="\[${c_red}\]!!!→\[${c_reset}\] "
fi
}
PROMPT_COMMAND="set_prompt_symbol;print_pre_prompt;${PROMPT_COMMAND}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment