Last active
March 9, 2018 19:49
-
-
Save ysim/845d8d2140c6d73dce8caff64331b829 to your computer and use it in GitHub Desktop.
A bash prompt for your git status and more.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# DESCRIPTION: | |
# You might find this bash prompt useful if you make regular use of Git and | |
# virtualenv. | |
# | |
# FEATURES: | |
# - Displays any activated virtualenv. | |
# - Displays the username and current working directory. | |
# - Displays the current git branch, as well as the number of commits to | |
# pull (red) or push (green). The colour of the branch name will also change | |
# depending on whether your working directory is clean (grey), has untracked | |
# files with no other modifications (light blue), has unstaged changes | |
# (yellow), has changes to be committed (dark orange), or if your local | |
# branch has diverged from the remote (red). | |
# - The prompt symbol is highlighted in red if the exit code of the last | |
# command was anything other than 0. | |
# | |
# INSTRUCTIONS: | |
# 1. Either move or symlink this file to ~/.bash_prompt | |
# 2. Add `source ~/.bash_prompt` to ~/.bash_profile or ~/.bashrc | |
# | |
# NOTES: | |
# - The number of commits will not appear if you do not have an upstream | |
# branch set for the current branch in your .gitconfig. | |
# | |
# ACKNOWLEDGEMENTS: | |
# - https://gist.github.com/insin/1425703 | |
# colour codes | |
NONE="\[\033[0m\]" | |
RED="\[\033[0;31m\]" | |
GREEN="\[\033[0;32m\]" | |
YELLOW="\[\033[0;33m\]" | |
BLUE="\[\033[0;34m\]" | |
PURPLE="\[\033[0;35m\]" | |
LIGHT_BLUE="\[\033[0;36m\]" | |
LIGHT_GREY="\[\033[0;37m\]" | |
# 256 colour support | |
function fg_colour { echo -ne "\[\033[38;5;$1m\]"; } | |
function bg_colour { echo -ne "\[\033[48;5;$1m\]"; } | |
function set_titlebar { | |
case $TERM in | |
xterm*) | |
TITLEBAR='\[\033]0;\w\007\]' | |
;; | |
*) | |
TITLEBAR="" | |
;; | |
esac | |
} | |
function set_virtualenv { | |
if [[ -z "$VIRTUAL_ENV" ]] ; then | |
VIRTUALENV="" | |
else | |
VIRTUALENV="${LIGHT_GREY}{`basename \"$VIRTUAL_ENV\"`}" | |
export PYLIB="$(python -c "import distutils; print distutils.sysconfig.get_python_lib()")" | |
fi | |
} | |
function set_username { | |
USERNAME="${GREEN}\u" | |
} | |
function set_current_working_directory { | |
CWD="${LIGHT_GREY}\w" | |
} | |
# returns 0 if the current directory is a git repository | |
function is_git_repository { | |
git branch &> /dev/null | |
} | |
# set current git branch | |
function set_git_branch { | |
branch_name="$(git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/')" | |
git_status="$(git status 2> /dev/null)" | |
if [[ ${git_status} =~ "Changes to be committed" ]] || [[ ${git_status} =~ "Unmerged paths" ]] ; then | |
branch_colour="${RED}" | |
elif [[ ${git_status} =~ "Changes not staged for commit" ]] ; then | |
branch_colour="${YELLOW}" | |
elif [[ ${git_status} =~ "Untracked files" ]] ; then | |
branch_colour="${LIGHT_BLUE}" | |
else | |
branch_colour="${LIGHT_GREY}" | |
fi | |
# The hyphen in the pattern for the branch name needs to be at the | |
# beginning of the pattern so that it isn't interpreted as a range, | |
# as in a-z. | |
# See this for more information on the restrictions on naming git branches: | |
# https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html | |
remote_pattern="Your branch is (.*) '([a-zA-Z0-9_-]+)/([-a-zA-Z0-9_.]+)' by ([0-9]+) commit" | |
if [[ ${git_status} =~ ${remote_pattern} ]] ; then | |
commits="${BASH_REMATCH[4]}" | |
if [[ "${BASH_REMATCH[1]}" == "ahead of" ]] ; then | |
branch_status=" ${GREEN}${commits}↑" | |
else | |
branch_status=" ${RED}${commits}↓" | |
fi | |
else | |
branch_status="" | |
fi | |
# if your local branch and the remote branch have diverged, make it red | |
diverge_pattern="Your branch and '([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)' have diverged" | |
if [[ ${git_status} =~ ${diverge_pattern} ]] ; then | |
diverge_detail="and have ([0-9]+) and ([0-9]+) different commit(s)? each, respectively." | |
if [[ ${git_status} =~ ${diverge_detail} ]] ; then | |
local_branch="${BASH_REMATCH[1]}" | |
remote_branch="${BASH_REMATCH[2]}" | |
fi | |
branch_colour="${RED}" | |
branch_status=" ${local_branch}↕${remote_branch}" | |
fi | |
if [[ ! "$branch_name" ]] ; then | |
branch_name='NO BRANCH' | |
if [[ ! "$(git remote -v)" ]] ; then | |
branch_name='NO REMOTE' | |
fi | |
branch_colour="${PURPLE}" | |
fi | |
GIT_BRANCH="${branch_colour}(${branch_name}${branch_status}${branch_colour})" | |
} | |
function set_prompt_symbol { | |
if [[ $1 -eq 0 ]] ; then | |
PROMPT_SYMBOL="${NONE}\$" | |
else | |
PROMPT_SYMBOL="${RED}[$1]\$" | |
fi | |
} | |
function set_bash_prompt { | |
# get return value of last command | |
set_prompt_symbol $? | |
# set the TITLEBAR variable | |
set_titlebar | |
# set the VIRTUALENV variable | |
set_virtualenv | |
# set the USERNAME variable | |
set_username | |
# set the CWD (current working directory) variable | |
set_current_working_directory | |
if is_git_repository ; then | |
set_git_branch | |
else | |
GIT_BRANCH="" | |
fi | |
export PS1="${TITLEBAR}${VIRTUALENV}${USERNAME}:${CWD}${GIT_BRANCH}${PROMPT_SYMBOL}${NONE} " | |
export PS2="${LIGHT_BLUE}>${NONE} " | |
} | |
# An environment variable provided by bash. The contents of this variable | |
# are executed as a regular bash command just before bash displays a prompt. | |
PROMPT_COMMAND=set_bash_prompt |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment