Skip to content

Instantly share code, notes, and snippets.

@johnhpatton
Last active April 15, 2020 11:02
Show Gist options
  • Save johnhpatton/f6de57bbe00875c7327e46b0f5d02240 to your computer and use it in GitHub Desktop.
Save johnhpatton/f6de57bbe00875c7327e46b0f5d02240 to your computer and use it in GitHub Desktop.
Active command prompt for git, backgrounded jobs, exit codes, etc. for bash users.
# command_prompt()
#
# Follow the instructions below to add fonts and git prompt support, then
# add this scriptlet to your .bashrc.
#
# Function that is executed each time a command is run to update the PS1
# variable (ie: prompt). To configure, let's put some fonts in place.
# Download and install Gabriele Lana's Awesome Fonts:
#
# https://github.com/gabrielelana/awesome-terminal-fonts/archive/master.zip
#
# Unzip the archive and run the install.sh from the resulting
# awesome-terminal-fonts-master folder to install some fonts. Some .sh files
# will also be installed in ~/.fonts to provide constants for each font that
# can be used in scripts.
#
# If using git, install the git-prompt.sh script in your home folder and add
# to .bashrc:
#
# curl -L -o ~/.git-prompt.sh https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh
# chmod +x ~/.git-prompt.sh
# echo 'source ~/.git-prompt.sh' >> ~/.bashrc
#
# You'll need to log out and back in to pull that in, or you'll need to source
# the ~/.git-prompt.sh in your current session to test it.
#
# Color scheme is based on a dark background. If using a light background,
# you'll want to experiment with the colors.
command_prompt() {
#=========================================================
# Capture EXIT_CODE MUST BE FIRST!!!
#=========================================================
local EXIT_CODE="$?"
# Reset the PS1 (Prompt String)
PS1=""
# exit code output variables
local exit_code=""
local exit_code_color=""
# CONSTANTS
# Colors for bash prompt
# foreground colors, use with echo -e
local RESET='\[\e[m\]' # No Color, reset
# normal bright high intensity bright + high intensity
local DKGREY='\[\e[0;30m\]'
local LTGREY='\[\e[1;30m\]'
local RED='\[\e[0;31m\]' BRED='\[\e[1;31m\]' IRED='\[\e[0;91m\]' BIRED='\[\e[1;91m\]'
local GREEN='\[\e[0;32m\]' BGREEN='\[\e[1;32m\]' IGREEN='\[\e[0;92m\]' BIGREEN='\[\e[1;92m\]'
local YELLOW='\[\e[0;33m\]' BYELLOW='\[\e[1;33m\]' IYELLOW='\[\e[0;93m\]' BIYELLOW='\[\e[1;93m\]'
local BLUE='\[\e[0;34m\]' BBLUE='\[\e[1;34m\]' IBLUE='\[\e[0;94m\]' BIBLUE='\[\e[1;94m\]'
local PURPLE='\[\e[0;35m\]' BPURPLE='\[\e[1;35m\]' IPURPLE='\[\e[0;95m\]' BIPURPLE='\[\e[1;95m\]'
local CYAN='\[\e[0;36m\]' BCYAN='\[\e[1;36m\]' ICYAN='\[\e[0;96m\]' BICYAN='\[\e[1;96m\]'
local GREY='\[\e[0;37m\]' BGREY='\[\e[1;37m\]'
local WHITE='\[\e[0;97m\]' BWHITE='\[\e[1;97m\]'
local sym_radioactive=$(echo -e '\u2622')
local sym_warning=$(echo -e '\u26A0')
local sym_check_mark=$(echo -e '\u2714')
local sym_cancel=$(echo -e '\u2718')
local sym_sparkle="$(echo -e '\u2728')"
local sym_arrow="$(echo -e '\u2937')"
local sym_line="$(echo -e '\u2574')"
local sym_left_arrow_up="$(echo -e '\u2b11')"
local sym_background_process="$(echo -e '\u2749')"
local sym_colon="$(echo -e '\u003A')"
local user="${CYAN}\u${RESET}"
local host="${ICYAN}\h${RESET}"
local workdir="${YELLOW}\W${RESET}"
local git_branch=""
local git_symbols=""
# is user in an SSH session?
local bracket_color="" # default
if [[ $SSH_CLIENT ]] || [[ $SSH2_CLIENT ]]; then
bracket_color="${BPURPLE}"
fi
# check if user has ~/.git-prompt.sh loaded and run
# __git_ps1 if possible
local git_ps1=""
if declare -F __git_ps1 &>/dev/null; then
git_ps1=$(__git_ps1)
if [ -n "${git_ps1}" ]; then
# remove unnecessary characters to clean the prompt
git_ps1="${git_ps1##*( )}"
git_ps1="${git_ps1//[(]}"
git_ps1="${git_ps1//[]]}"
# colour branch name depending on state
# make the symbols easier to see.
local git_branch_color="$GREEN"
# staged files, committed but not pushed
if [[ "${git_ps1}" =~ "+" ]]; then
git_branch_color="${CYAN}"
git_ps1="${git_ps1//[+]}"
git_symbols+=" +"
fi
# if there is something stashed
if [[ "${git_ps1}" =~ "$" ]]; then
git_branch_color="${YELLOW}"
git_ps1="${git_ps1//[$]}"
git_symbols+=" $"
fi
# unstaged/uncommitted files (dirty)
if [[ "${git_ps1}" =~ "*" ]]; then
git_branch_color="${YELLOW}"
git_ps1="${git_ps1//[*]}"
git_symbols+=" *"
fi
# branch is ahead
if [[ "${git_ps1}" =~ ">" ]]; then
git_branch_color="${YELLOW}"
git_ps1="${git_ps1//[>]}"
git_symbols+=" >"
fi
# branch is behind
if [[ "${git_ps1}" =~ "<" ]]; then
git_branch_color="${YELLOW}"
git_ps1="${git_ps1//[<]}"
git_symbols+=" <"
fi
# untracked files
if [[ "${git_ps1}" =~ "%" ]]; then
git_branch_color="${RED}"
git_ps1="${git_ps1//[%]}"
git_symbols+=" %"
fi
git_branch="[[${git_branch_color}${git_ps1}${RESET}${git_symbols}${RESET}]]"
fi
fi
case ${EXIT_CODE} in
0) exit_code="${sym_check_mark}"
exit_code_color="${BGREEN}"
;;
127) exit_code="${sym_warning}" # command not found
exit_code_color="${BIRED}"
;;
130) exit_code="${sym_cancel}" # control-c
exit_code_color="${BYELLOW}"
;;
148) exit_code="${sym_sparkle}" # backgrounded command
exit_code_color="${BCYAN}"
;;
*) exit_code="${EXIT_CODE}" # other error code
exit_code_color="${RED}"
;;
esac
# backgrounded and paused jobs in the current session.
local jobs_details=""
local bg_jobs=$(jobs -r | wc -l )
(( bg_jobs > 0 )) && jobs_details="${YELLOW}${sym_background_process}${RESET}${sym_colon}${WHITE}${bg_jobs}${RESET} "
(( bg_jobs > 3 )) && jobs_details="${RED}${sym_background_process}${RESET}${sym_colon}${WHITE}${bg_jobs}${RESET} "
local st_jobs=$(jobs -s | wc -l )
(( st_jobs > 0 )) && (( st_jobs <= 3 )) && jobs_details+="${LTGREY}${sym_background_process}${RESET}${sym_colon}${WHITE}${st_jobs}${RESET}"
(( st_jobs > 3 )) && jobs_details+="${LTGREY}${sym_background_process}${RESET}${sym_colon}${WHITE}${st_jobs}${RESET}"
# assemble the prompt
[ -n "${git_branch}" ] && PS1+="${git_branch}"
[ -n "${jobs_details}" ] && PS1+="${jobs_details}"
[ -n "${PS1}" ] && PS1+="\n"
PS1+="${LTGREY}${sym_arrow} ${RESET}"
PS1+="${exit_code_color}${exit_code} ${RESET}"
PS1+="${bracket_color}[${RESET}${user}@${host}${bracket_color}][${RESET}${workdir}${bracket_color}]${RESET}$ "
}
configure_ps1() {
# configure PROMPT_COMMAND which is executed each time before PS1
# the history commands will ensure the command history file is
# updated immediately and reloaded with no duplicates.
export PROMPT_COMMAND='command_prompt; history -a; history -c; history -r;'
}
# Set the PROMPT_COMMAND and remove the configure function.
configure_ps1
unset -f configure_ps1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment