diff --git a/README.md b/README.md index 0275a31..794a2a4 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ In particular the branch name, difference with remote branch, number of files st (an original idea from this [blog post][]). +`gitstatus.sh` added by [AKS](http://github.com/aks). + ## Examples The prompt may look like the following: @@ -53,9 +55,13 @@ The symbols are as follows: ## Configuration 1. You can use ``GIT_PROMPT_START`` and ``GIT_PROMPT_END`` to tweak your prompt -2. If you want to tweak the colors, - currently you have to tweak it in the ``gitprompt.sh`` -3. You can define ``prompt_callback`` function to tweak your prompt dynamicly +2. If you want to tweak the colors, currently you have to tweak it in the + ``gitprompt.sh``. See the definitions of ``GIT_PROMPT_xxx1``, which include + various colors names. +3. The current git repo information is obtained by the script `gitstatus.sh` or + `gitstatus.py`. Both scripts do the same thing, but the bash script is a + tad bit more quick, and is used by default. +4. You can define ``prompt_callback`` function to tweak your prompt dynamicaly ```sh function prompt_callback { diff --git a/gitprompt.sh b/gitprompt.sh old mode 100644 new mode 100755 index 7d6cd3e..de6fa98 --- a/gitprompt.sh +++ b/gitprompt.sh @@ -42,6 +42,7 @@ function git_prompt_config() local White='\[\033[37m\]' local Red="\[\033[0;31m\]" local Blue="\[\033[0;34m\]" + local Cyan="\[\033[0;36m\]" # Default values for the appearance of the prompt. Configure at will. GIT_PROMPT_PREFIX="[" @@ -52,8 +53,8 @@ function git_prompt_config() GIT_PROMPT_CONFLICTS="${Red}✖ " GIT_PROMPT_CHANGED="${Blue}✚ " GIT_PROMPT_REMOTE=" " - GIT_PROMPT_UNTRACKED="…" - GIT_PROMPT_STASHED="⚑ " + GIT_PROMPT_UNTRACKED="${Cyan}…" + GIT_PROMPT_STASHED="${BoldBlue}⚑ " GIT_PROMPT_CLEAN="${BoldGreen}✔" # Various variables you might want for your PS1 prompt instead @@ -81,7 +82,17 @@ function git_prompt_config() if [ "x$__GIT_STATUS_CMD" == "x" ] then git_prompt_dir - __GIT_STATUS_CMD="${__GIT_PROMPT_DIR}/gitstatus.py" + local sfx file + # look first for a '.sh' version, then use the python version + for sfx in sh py ; do + file="${__GIT_PROMPT_DIR}/gitstatus.$sfx" + if [[ -x "$file" ]]; then + __GIT_STATUS_CMD="$file" + break + fi + done + # The old way + #__GIT_STATUS_CMD="${__GIT_PROMPT_DIR}/gitstatus.py" fi } diff --git a/gitstatus.sh b/gitstatus.sh new file mode 100755 index 0000000..d290e07 --- /dev/null +++ b/gitstatus.sh @@ -0,0 +1,90 @@ +#/bin/bash +# -*- coding: UTF-8 -*- +# gitstatus.sh -- produce the current git repo status on STDOUT +# Functionally equivalent to 'gitstatus.py', but written in bash (not python). +# +# Alan K. Stebbens [http://github.com/aks] + +# change those symbols to whatever you prefer +declare -a symbols +symbols['ahead']='↑·' +symbols['behind']='↓·' +symbols['prehash']=':' + +gitsym=`git symbolic-ref HEAD` + +# if "fatal: Not a git repo .., then exit +case "$gitsym" in fatal*) exit 0 ;; esac + +# the current branch is the tail end of the symbolic reference +branch="${gitsym##*/}" # get the basename after "refs/head/" + +tmp="/tmp/$$-gitstatus.out" +trap "rm -f \"$tmp\"" EXIT + +status=`git diff --name-status >$tmp` + +# if the diff is fatal, exit now +if grep -s "^fatal:" $tmp 2>/dev/null ; then + exit +fi + +# count_lines U +count_lines() { egrep -c "^$1" <$tmp ; } + +num_changed=$(( `wc -l <$tmp` - `count_lines U` )) + +staged_files=`git diff --staged --name-status >$tmp` +num_conflicts=`count_lines U` +num_staged=$(( `wc -l <$tmp` - num_conflicts )) +num_untracked=`git status -s -uall | grep -c "^??"` +num_stashed=`git stash list | wc -l` + +clean=0 +if (( num_changed == 0 && num_staged == 0 && num_U == 0 && num_untracked == 0 && num_stashed == 0 )) ; then + clean=1 +fi + +remote= + +if [[ -z "$branch" ]]; then + tag=`git describe --exact-match` + if [[ -n "$tag" ]]; then + branch="$tag" + else + branch="${symbols['prehash']}`git rev-parse --short HEAD`" + fi +else + remote_name=`git config branch.${branch}.remote` + if [[ -n "$remote_name" ]]; then + merge_name=`git config branch.${branch}.merge` + else + remote_name='origin' + merge_name="refs/heads/${branch}" + fi + if [[ "$remote_name" == '.' ]]; then + remote_ref="$merge_name" + else + remote_ref="refs/remotes/$remote_name/${merge_name##*/}" + fi + # get the revision list, and count the leading "<" and ">" + revgit=`git rev-list --left-right ${remote_ref}...HEAD >$tmp` + num_revs=`wc -l <$tmp` + num_ahead=`count_lines "^>"` + num_behind=$(( num_revs - num_ahead )) + if (( num_behind > 0 )) ; then + remote="${remote}${symbols['behind']}${num_behind}" + fi + if (( num_ahead > 0 )) ; then + remote="${remote}${symbols['ahead']}${num_ahead}" + fi +fi +if [[ -z "$remote" ]] ; then + remote='.' +fi + +for w in "$branch" "$remote" $num_staged $num_conflicts $num_changed $num_untracked $num_stashed $clean ; do + echo "$w" +done + +exit