Skip to content

Instantly share code, notes, and snippets.

@harisund
Created March 11, 2020 09:20
Show Gist options
  • Save harisund/300e420b5dda92e84eb9079cef9acc07 to your computer and use it in GitHub Desktop.
Save harisund/300e420b5dda92e84eb9079cef9acc07 to your computer and use it in GitHub Desktop.
better bash prompt for git repos
# Colors
RED="\[\033[0;31m\]"
YELLOW="\[\033[0;33m\]"
BLUE="\[\033[0;34m\]"
LIGHT_RED="\[\033[1;31m\]"
LIGHT_GREEN="\[\033[1;32m\]"
WHITE="\[\033[1;37m\]"
LIGHT_GRAY="\[\033[0;37m\]"
COLOR_NONE="\[\e[0m\]"
# Used by GIT and SVN for clean directories
GREEN="\[\033[0;32m\]"
# Used by SVN for modified files
# Used by GIT for files tracked, modified but not staged.
YELLOW="\[\033[0;33m\]"
# Used by GIT for staged, but modified. Shouldn't normally see this, the way I work.
CYAN="\[\033[0;36m\]"
# Used by GIT and SVN for unrevisioned / untracked files
RED="\[\033[0;31m\]"
function is_git_repo {
git branch > /dev/null 2>&1
}
function set_git_branch {
# Capture the output of the "git status" command.
git_status="$(git status 2>&1)"
# Set color based on clean/staged/dirty.
if [[ ${git_status} =~ "working directory clean" ]]; then
state="${GREEN}"
elif [[ ${git_status} =~ "working tree clean" ]]; then
state="${GREEN}"
elif [[ ${git_status} =~ "Changes to be committed" ]]; then
state="${YELLOW}"
elif [[ ${git_status} =~ "fatal: this operation" ]]; then
state="${BLUE}"
else
state="${RED}"
fi
# Set arrow icon based on status against remote.
ahead_pattern="Your branch is ahead of"
behind_pattern="Your branch is behind"
diverge_pattern="Your branch and (.*) have diverged"
if [[ ${git_status} =~ ${ahead_pattern} ]]; then
compared_to_remote="↑"
elif [[ ${git_status} =~ ${behind_pattern} ]]; then
compared_to_remote="↓"
elif [[ ${git_status} =~ ${diverge_pattern} ]]; then
compared_to_remote="↕"
else
compared_to_remote=""
fi
# Get the name of the branch.
branch_pattern="On branch ([^${IFS}]*)"
if [[ ${git_status} =~ ${branch_pattern} ]]; then
branch=${BASH_REMATCH[1]}
else
detached_pattern="HEAD detached at ([^${IFS}]*)"
if [[ ${git_status} =~ ${detached_pattern} ]]; then
branch=${BASH_REMATCH[1]}
else
branch="no branch"
fi
fi
# Get Current branch. If no branch, warn about detached HEAD
#cur_branch=$(git rev-parse --abbrev-ref HEAD)
#[[ ${cur_branch} == "HEAD" ]] || branch=${cur_branch} &&\
# branch="DETACHED: $(git rev-parse --short HEAD)"
# Are we in a submodule?
dotgit="$(git rev-parse --show-toplevel)/.git"
[[ -f "${dotgit}" ]] && sub="<sub>" || sub=""
# Set the final branch string that gets used in the caller function
GITPROMPT="${state}(${branch})${sub}${compared_to_remote}${COLOR_NONE} "
}
# Return the prompt symbol to use, colorized based on the return value of the
# previous command.
function set_prompt_symbol () {
if test $1 -eq 0 ; then
PROMPT_SYMBOL="\$"
else
PROMPT_SYMBOL="${RED}\$${COLOR_NONE}"
fi
}
# Set the full bash prompt.
function set_bash_prompt () {
#{{{
# Set the PROMPT_SYMBOL variable. We do this first so we don't lose the
# return value of the last command.
set_prompt_symbol $?
# Set the GITPROMPT variable.
GITPROMPT=""
PS1="[\u@${HH}][\w] ${GITPROMPT}${PROMPT_SYMBOL}\n$ "
if is_git_repo ; then
set_git_branch
fi
# Set the bash prompt variable.
PS1="[\u@${HH}][\w] ${GITPROMPT}${PROMPT_SYMBOL}\n$ "
}
#}}}
PROMPT_COMMAND=set_bash_prompt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment