Bash Prompt with Git Repository and Working Tree Status Information
Here are three confessions:
- I am a total command-line geek: I spend most of my life in the (bash) shell.
- I am a total Git convert: it is to Subversion as cell phones are to landlines.
- I love a good prompt.
So, those three confessions find mutual experession in the following extract from my ".bashrc" file. By default, shows the basics: user name, hostname and working directory. I tend to have deeply-nested directory structures, so the full path to the directory gets really cumbersome, so, by default it only shows the current directory basename instead of the full path. I hope back and forth between lots of hosts, and, usually have several, if not dozens, of terminal windows open at once. This can be quite dangerous if I do not make sure I'm actually on the host that I think I am before issuing a command, especially those "sudo" ones. So I've got the prompt set that if I'm not on my own computer, the hostname is underlined. I used to have it set that the entire prompt was highlighted a different color depending on the hostname, but that just got rather complicated. The real magic is the display of the current Git branch if you are in a Git repository, as well as the SHA1 of the current HEAD. Extremely useful is the flags indicating whether there are files staged for commiting in the index ("+I"), tracked files with modifications/changes not staged for committing ("+M"), and/or untracked files in the working tree ("+U"). Until you have this, you have no idea how great it is being able to take in the status of your working tree at a glance (forgotten to commit some edits? forgotten to start tracking files?), without the need to run "git status" to get this information.
For example:
To get this prompt, add the following to your "~/.bashrc" file:
############################################################################### # IDENTIFICATION OF LOCAL HOST: CHANGE TO YOUR COMPUTER NAME ############################################################################### PRIMARYHOST="localhost" ############################################################################### # PROMPT ############################################################################### ############################################################################### # Terminal Title set_terminal_title() { if [[ -z $@ ]] then TERMINAL_TITLE=$PWD else TERMINAL_TITLE=$@ fi } alias stt='set_terminal_title' STANDARD_PROMPT_COMMAND='history -a ; echo -ne "\033]0;${TERMINAL_TITLE}\007"' PROMPT_COMMAND=$STANDARD_PROMPT_COMMAND ############################################################################### # Parses Git info for prompt function _set_git_envar_info { GIT_BRANCH="" GIT_HEAD="" GIT_STATE="" GIT_LEADER="" local STATUS STATUS=$(git status 2> /dev/null) if [[ -z $STATUS ]] then return fi GIT_LEADER=":" GIT_BRANCH="$(git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/')" GIT_HEAD=":$(git rev-parse --short HEAD)" if [[ "$STATUS" == *'working directory clean'* ]] then GIT_STATE="" else GIT_HEAD=$GIT_HEAD":" GIT_STATE="" if [[ "$STATUS" == *'Changes to be committed:'* ]] then GIT_STATE=$GIT_STATE'+I' # Index has files staged for commit fi if [[ "$STATUS" == *'Changed but not updated:'* || "$STATUS" == *'Changes not staged for commit'* ]] then GIT_STATE=$GIT_STATE"+M" # Working tree has files modified but unstaged fi if [[ "$STATUS" == *'Untracked files:'* ]] then GIT_STATE=$GIT_STATE'+U' # Working tree has untracked files fi GIT_STATE=$GIT_STATE'' fi gdir=$(cd $GIT_ROOT; pwd -P) export gdir } ############################################################################### # Composes prompt. function setps1 { # Help message. local USAGE="Usage: setps1 [none] [screen=<0|1>] [user=<0|1>] [dir=<0|1|2>] [git=<0|1>] [wrap=<0|1>] [which-python=<0|1>]" if [[ (-z $@) || ($@ == "*-h*") || ($@ == "*--h*") ]] then echo $USAGE return fi # Prompt colors. local CLEAR="\[\033[0m\]" local STY_COLOR='\[\033[1;37;41m\]' local PROMPT_COLOR='\[\033[1;94m\]' local USER_HOST_COLOR='\[\033[1;30m\]' local PROMPT_DIR_COLOR='\[\033[1;94m\]' local GIT_LEADER_COLOR='\[\033[1;30m\]' local GIT_BRANCH_COLOR=$CLEAR'\[\033[1;90m\]\[\033[4;90m\]' local GIT_HEAD_COLOR=$CLEAR'\[\033[1;32m\]' local GIT_STATE_COLOR=$CLEAR'\[\033[1;31m\]' # Hostname-based colors in prompt. if [[ $HOSTNAME != $PRIMARYHOST ]] then USER_HOST_COLOR=$REMOTE_USER_HOST_COLOR fi # Start with empty prompt. local PROMPTSTR="" # Set screen session id. if [[ $@ == *screen=1* ]] then ## Decorate prompt with indication of screen session ## if [[ -z "$STY" ]] # if screen session variable is not defined then local SCRTAG="" else local SCRTAG="$STY_COLOR(STY ${STY%%.*})$CLEAR" # get screen session number fi fi # Set user@host. if [[ $@ == *user=1* ]] then PROMPTSTR=$PROMPTSTR"$USER_HOST_COLOR\\u@\\h$CLEAR" fi # Set directory. if [[ -n $PROMPTSTR && ($@ == *dir=1* || $@ == *dir=2*) ]] then PROMPTSTR=$PROMPTSTR"$PROMPT_COLOR:" fi if [[ $@ == *dir=1* ]] then PROMPTSTR=$PROMPTSTR"$PROMPT_DIR_COLOR\W$CLEAR" elif [[ $@ == *dir=2* ]] then PROMPTSTR=$PROMPTSTR"$PROMPT_DIR_COLOR\$(pwd -P)$CLEAR" fi # set git if [[ $(which git 2> /dev/null) && $@ == *git=1* ]] then PROMPT_COMMAND=$PROMPT_COMMAND"; _set_git_envar_info" PROMPTSTR=$PROMPTSTR"$BG_COLOR$GIT_LEADER_COLOR\$GIT_LEADER$GIT_BRANCH_COLOR\$GIT_BRANCH$GIT_HEAD_COLOR\$GIT_HEAD$GIT_STATE_COLOR\$GIT_STATE$CLEAR" #PROMPTSTR=$PROMPTSTR"$GIT_LEADER_COLOR\$(_echo_git_envar_info)" else PROMPT_COMMAND=$STANDARD_PROMPT_COMMAND fi # Set wrap. if [[ $@ == *wrap=1* ]] then local WRAP="$CLEAR\n" else local WRAP="" fi # Set wrap. if [[ $@ == *which-python=1* ]] then local WHICHPYTHON="$CLEAR\n(python is '\$(which python)')$CLEAR\n" else local WHICHPYTHON="" fi # Finalize. if [[ -z $PROMPTSTR || $@ == none ]] then PROMPTSTR="\$ " else PROMPTSTR="$TITLEBAR\n$SCRTAG${PROMPT_COLOR}[$CLEAR$PROMPTSTR$PROMPT_COLOR]$WRAP$WHICHPYTHON$PROMPT_COLOR\$$CLEAR " fi # Set. PS1=$PROMPTSTR PS2='> ' PS4='+ ' } alias setps1-long='setps1 screen=1 user=1 dir=2 git=1 wrap=1' alias setps1-short='setps1 screen=1 user=1 dir=1 git=1 wrap=0' alias setps1-default='setps1-short' alias setps1-plain='setps1 screen=0 user=0 dir=0 git=0 wrap=0' alias setps1-nogit='setps1 screen=0 user=1 dir=1 git=0 wrap=0' alias setps1-local-long='setps1 screen=1 user=0 dir=2 git=1 wrap=1' alias setps1-local-short='setps1 screen=0 user=0 dir=1 git=1 wrap=0' alias setps1-local='setps1-local-short' alias setps1-dev-short='setps1 screen=0 user=0 dir=1 git=1 wrap=0 which-python=1' alias setps1-dev-long='setps1 screen=0 user=1 dir=2 git=1 wrap=0 which-python=1' alias setps1-dev-remote='setps1 screen=0 user=1 dir=1 git=1 wrap=0 which-python=1' if [[ "$HOSTNAME" = "$PRIMARYHOST" ]] then setps1 screen=0 user=0 dir=1 git=1 wrap=0 which-python=0 else setps1 screen=1 user=1 dir=1 git=1 wrap=0 which-python=0 fi
feed
Comments
2 comments postedOtherwise it would definitely be a no-go. Maybe if you provide more details I might be able to help?
nice prompt, but it doesn't refresh properly when moving to a dir that isn't under git...any idea?
Post new comment