diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e7683df --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*~ +*.bak diff --git a/README.md b/README.md index 47f1d01..f4c751f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Informative git prompt for bash +# Informative git prompt for bash and fish This prompt is a port of the "Informative git prompt for zsh" which you can find [here](https://github.com/olivierverdier/zsh-git-prompt) @@ -11,6 +11,8 @@ In particular the branch name, difference with remote branch, number of files st The prompt may look like the following: +![Example prompt](gitprompt.png) + * ``(master↑3|✚1)``: on branch ``master``, ahead of remote by 3 commits, 1 file changed but not staged * ``(status|●2)``: on branch ``status``, 2 files staged * ``(master|✚7…)``: on branch ``master``, 7 files changed, some files untracked diff --git a/gitprompt.fish b/gitprompt.fish new file mode 100644 index 0000000..7bcfe54 --- /dev/null +++ b/gitprompt.fish @@ -0,0 +1,106 @@ +if not set -q __GIT_PROMPT_DIR + set __GIT_PROMPT_DIR ~/.bash +end + +# Colors +# Reset +set ResetColor (set_color normal) # Text Reset + +# Regular Colors +set Red (set_color red) # Red +set Yellow (set_color yellow); # Yellow +set Blue (set_color blue) # Blue +set WHITE (set_color white) + +# Bold +set BGreen (set_color -o green) # Green + +# High Intensty +set IBlack (set_color -o black) # Black + +# Bold High Intensty +set Magenta (set_color -o purple) # Purple + +# Default values for the appearance of the prompt. Configure at will. +set GIT_PROMPT_PREFIX "[" +set GIT_PROMPT_SUFFIX "]" +set GIT_PROMPT_SEPARATOR "|" +set GIT_PROMPT_BRANCH "$Magenta" +set GIT_PROMPT_STAGED "$Red● " +set GIT_PROMPT_CONFLICTS "$Red✖ " +set GIT_PROMPT_CHANGED "$Blue✚ " +set GIT_PROMPT_REMOTE " " +set GIT_PROMPT_UNTRACKED "…" +set GIT_PROMPT_CLEAN "$BGreen✔" + +function fish_prompt + + # Various variables you might want for your PS1 prompt instead + set Time (date +%R) + set PathShort (pwd|sed "s=$HOME=~=") + + set PROMPT_START "$Yellow$PathShort$ResetColor" + set PROMPT_END " \n$WHITE$Time$ResetColor \$ " + + set -e __CURRENT_GIT_STATUS + set gitstatus "$__GIT_PROMPT_DIR/gitstatus.py" + + set _GIT_STATUS (python $gitstatus) + set __CURRENT_GIT_STATUS $_GIT_STATUS + + set __CURRENT_GIT_STATUS_PARAM_COUNT (count $__CURRENT_GIT_STATUS) + + if not test "0" -eq $__CURRENT_GIT_STATUS_PARAM_COUNT + set GIT_BRANCH $__CURRENT_GIT_STATUS[1] + set GIT_REMOTE "$__CURRENT_GIT_STATUS[2]" + if contains "." "$GIT_REMOTE" + set -e GIT_REMOTE + end + set GIT_STAGED $__CURRENT_GIT_STATUS[3] + set GIT_CONFLICTS $__CURRENT_GIT_STATUS[4] + set GIT_CHANGED $__CURRENT_GIT_STATUS[5] + set GIT_UNTRACKED $__CURRENT_GIT_STATUS[6] + set GIT_CLEAN $__CURRENT_GIT_STATUS[7] + end + + if test -n "$__CURRENT_GIT_STATUS" + set STATUS " $GIT_PROMPT_PREFIX$GIT_PROMPT_BRANCH$GIT_BRANCH$ResetColor" + + if set -q GIT_REMOTE + set STATUS "$STATUS$GIT_PROMPT_REMOTE$GIT_REMOTE$ResetColor" + end + + set STATUS "$STATUS$GIT_PROMPT_SEPARATOR" + + if [ $GIT_STAGED != "0" ] + set STATUS "$STATUS$GIT_PROMPT_STAGED$GIT_STAGED$ResetColor" + end + + if [ $GIT_CONFLICTS != "0" ] + set STATUS "$STATUS$GIT_PROMPT_CONFLICTS$GIT_CONFLICTS$ResetColor" + end + + if [ $GIT_CHANGED != "0" ] + set STATUS "$STATUS$GIT_PROMPT_CHANGED$GIT_CHANGED$ResetColor" + end + + if [ "$GIT_UNTRACKED" != "0" ] + set STATUS "$STATUS$GIT_PROMPT_UNTRACKED$GIT_UNTRACKED$ResetColor" + end + + if [ "$GIT_CLEAN" = "1" ] + set STATUS "$STATUS$GIT_PROMPT_CLEAN" + end + + set STATUS "$STATUS$ResetColor$GIT_PROMPT_SUFFIX" + + set PS1 "$PROMPT_START$STATUS$PROMPT_END" + else + set PS1 "$PROMPT_START$PROMPT_END" + end + + echo -e $PS1 + +end + + diff --git a/gitprompt.png b/gitprompt.png new file mode 100644 index 0000000..c3d5c05 Binary files /dev/null and b/gitprompt.png differ diff --git a/gitprompt.sh b/gitprompt.sh index 31c1bc6..cb7254d 100644 --- a/gitprompt.sh +++ b/gitprompt.sh @@ -1,120 +1,181 @@ -#!/bin/bash -# assume the gitstatus.py is in the same directory as this script -# code thanks to http://stackoverflow.com/questions/59895 -if [ -z "$__GIT_PROMPT_DIR" ] ; then - SOURCE="${BASH_SOURCE[0]}" - while [ -h "$SOURCE" ] ; do - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" - done - __GIT_PROMPT_DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" +#!/bin/sh + +function git_prompt_dir() +{ + # assume the gitstatus.py is in the same directory as this script + # code thanks to http://stackoverflow.com/questions/59895 + if [ -z "${__GIT_PROMPT_DIR}" ]; then + local SOURCE="${BASH_SOURCE[0]}" + while [ -h "${SOURCE}" ]; do + local DIR="$( cd -P "$( dirname "${SOURCE}" )" && pwd )" + SOURCE="$(readlink "${SOURCE}")" + [[ $SOURCE != /* ]] && SOURCE="${DIR}/${SOURCE}" + done + __GIT_PROMPT_DIR="$( cd -P "$( dirname "${SOURCE}" )" && pwd )" fi +} -# Colors -# Reset -ResetColor="\[\033[0m\]" # Text Reset - -# Regular Colors -Red="\[\033[0;31m\]" # Red -Yellow="\[\033[0;33m\]" # Yellow -Blue="\[\033[0;34m\]" # Blue -WHITE='\[\033[37m\]' - -# Bold -BGreen="\[\033[1;32m\]" # Green - -# High Intensty -IBlack="\[\033[0;90m\]" # Black - -# Bold High Intensty -Magenta="\[\033[1;95m\]" # Purple - -# Various variables you might want for your PS1 prompt instead -#Time12a="\@" -Time12a="(\$(date +%H:%M:%S))" -PathShort="\w" - -# Default values for the appearance of the prompt. Configure at will. -GIT_PROMPT_PREFIX="[" -GIT_PROMPT_SUFFIX="]" -GIT_PROMPT_SEPARATOR="|" -GIT_PROMPT_BRANCH="${Magenta}" -GIT_PROMPT_STAGED="${Red}● " -GIT_PROMPT_CONFLICTS="${Red}✖ " -GIT_PROMPT_CHANGED="${Blue}✚ " -GIT_PROMPT_REMOTE=" " -GIT_PROMPT_UNTRACKED="…" -GIT_PROMPT_CLEAN="${BGreen}✔" - -PROMPT_START="$Yellow$PathShort$ResetColor" -PROMPT_END=" \n$WHITE$Time12a$ResetColor $ " -if [ -z "$OLDPROMPT" ] ; then - export OLDPROMPT=$PS1 -fi +function git_prompt_config() +{ + # Colors + ResetColor="\[\033[0m\]" # Text reset + + # Bold + local BoldGreen="\[\033[1;32m\]" # Green + local BoldBlue="\[\033[1;34m\]" # Blue + + # High Intensty + local IntenseBlack="\[\033[0;90m\]" # Grey + + # Bold High Intensty + local Magenta="\[\033[1;95m\]" # Purple + + # Regular Colors + local Yellow="\[\033[0;33m\]" + local White='\[\033[37m\]' + local Red="\[\033[0;31m\]" + local Blue="\[\033[0;34m\]" + + # Default values for the appearance of the prompt. Configure at will. + GIT_PROMPT_PREFIX="[" + GIT_PROMPT_SUFFIX="]" + GIT_PROMPT_SEPARATOR="|" + GIT_PROMPT_BRANCH="${Magenta}" + GIT_PROMPT_STAGED="${Red}● " + GIT_PROMPT_CONFLICTS="${Red}✖ " + GIT_PROMPT_CHANGED="${Blue}✚ " + GIT_PROMPT_REMOTE=" " + GIT_PROMPT_UNTRACKED="…" + GIT_PROMPT_CLEAN="${BoldGreen}✔" + + # Various variables you might want for your PS1 prompt instead + local Time12a="\$(date +%H:%M)" + # local Time12a="(\$(date +%H:%M:%S))" + # local Time12a="(\@))" + local PathShort="\w" + + if [ "x${GIT_PROMPT_START}" == "x" ]; then + PROMPT_START="${Yellow}${PathShort}${ResetColor}" + else + PROMPT_START="${GIT_PROMPT_START}" + fi -function update_current_git_vars() { - unset __CURRENT_GIT_STATUS - local gitstatus="${__GIT_PROMPT_DIR}/gitstatus.py" - - _GIT_STATUS=$(python $gitstatus) - __CURRENT_GIT_STATUS=($_GIT_STATUS) - GIT_BRANCH=${__CURRENT_GIT_STATUS[0]} - GIT_REMOTE=${__CURRENT_GIT_STATUS[1]} - if [[ "." == "$GIT_REMOTE" ]]; then - unset GIT_REMOTE - fi - GIT_STAGED=${__CURRENT_GIT_STATUS[2]} - GIT_CONFLICTS=${__CURRENT_GIT_STATUS[3]} - GIT_CHANGED=${__CURRENT_GIT_STATUS[4]} - GIT_UNTRACKED=${__CURRENT_GIT_STATUS[5]} - GIT_CLEAN=${__CURRENT_GIT_STATUS[6]} + if [ "x${GIT_PROMPT_END}" == "x" ]; then + PROMPT_END=" \n${White}${Time12a}${ResetColor} $ " + else + PROMPT_END="${GIT_PROMPT_END}" + fi + + EMPTY_PROMPT="${PROMPT_START}${PROMPT_END}" + + # fetch remote revisions every other $GIT_PROMPT_FETCH_TIMEOUT (default 5) minutes + GIT_PROMPT_FETCH_TIMEOUT=${1-5} + if [ "x$__GIT_STATUS_CMD" == "x" ] + then + git_prompt_dir + __GIT_STATUS_CMD="${__GIT_PROMPT_DIR}/gitstatus.py" + fi } function setGitPrompt() { - update_current_git_vars - set_virtualenv - - if [ -n "$__CURRENT_GIT_STATUS" ]; then - STATUS=" $GIT_PROMPT_PREFIX$GIT_PROMPT_BRANCH$GIT_BRANCH$ResetColor" - - if [ -n "$GIT_REMOTE" ]; then - STATUS="$STATUS$GIT_PROMPT_REMOTE$GIT_REMOTE$ResetColor" - fi - - STATUS="$STATUS$GIT_PROMPT_SEPARATOR" - if [ "$GIT_STAGED" -ne "0" ]; then - STATUS="$STATUS$GIT_PROMPT_STAGED$GIT_STAGED$ResetColor" - fi - - if [ "$GIT_CONFLICTS" -ne "0" ]; then - STATUS="$STATUS$GIT_PROMPT_CONFLICTS$GIT_CONFLICTS$ResetColor" - fi - if [ "$GIT_CHANGED" -ne "0" ]; then - STATUS="$STATUS$GIT_PROMPT_CHANGED$GIT_CHANGED$ResetColor" - fi - if [ "$GIT_UNTRACKED" -ne "0" ]; then - STATUS="$STATUS$GIT_PROMPT_UNTRACKED$GIT_UNTRACKED$ResetColor" - fi - if [ "$GIT_CLEAN" -eq "1" ]; then - STATUS="$STATUS$GIT_PROMPT_CLEAN" - fi - STATUS="$STATUS$ResetColor$GIT_PROMPT_SUFFIX" - - PS1="$PYTHON_VIRTUALENV$PROMPT_START$STATUS$PROMPT_END" - else - #PS1="$PROMPT_START$PROMPT_END" - PS1=$OLDPROMPT - fi -} -# Determine active Python virtualenv details. -function set_virtualenv () { - if test -z "$VIRTUAL_ENV" ; then - PYTHON_VIRTUALENV="" + local GIT_PROMPT_PREFIX + local GIT_PROMPT_SUFFIX + local GIT_PROMPT_SEPARATOR + local GIT_PROMPT_BRANCH + local GIT_PROMPT_STAGED + local GIT_PROMPT_CONFLICTS + local GIT_PROMPT_CHANGED + local GIT_PROMPT_REMOTE + local GIT_PROMPT_UNTRACKED + local GIT_PROMPT_CLEAN + local PROMPT_START + local PROMPT_END + local EMPTY_PROMPT + local ResetColor + local Blue + local GIT_PROMPT_FETCH_TIMEOUT + local __GIT_STATUS_CMD + + git_prompt_config + + EMPTY_PROMPT=${OLD_GITPROMPT} + + local repo=`git rev-parse --show-toplevel 2> /dev/null` + if [[ ! -e "${repo}" ]]; then + PS1="${EMPTY_PROMPT}" + return + fi + + local FETCH_HEAD="${repo}/.git/FETCH_HEAD" + # Fech repo if local is stale for more than $GIT_FETCH_TIMEOUT minutes + if [[ ! -e "${FETCH_HEAD}" || -e `find ${FETCH_HEAD} -mmin +${GIT_PROMPT_FETCH_TIMEOUT}` ]] + then + [[ -n $(git remote show) ]] && git fetch --quiet + fi + + local -a GitStatus + GitStatus=($("${__GIT_STATUS_CMD}" 2>/dev/null)) + + local GIT_BRANCH=${GitStatus[0]} + local GIT_REMOTE=${GitStatus[1]} + if [[ "." == "$GIT_REMOTE" ]]; then + unset GIT_REMOTE + fi + local GIT_STAGED=${GitStatus[2]} + local GIT_CONFLICTS=${GitStatus[3]} + local GIT_CHANGED=${GitStatus[4]} + local GIT_UNTRACKED=${GitStatus[5]} + local GIT_CLEAN=${GitStatus[6]} + + if [[ -n "${GitStatus}" ]]; then + local STATUS=" ${GIT_PROMPT_PREFIX}${GIT_PROMPT_BRANCH}${GIT_BRANCH}${ResetColor}" + + if [[ -n "${GIT_REMOTE}" ]]; then + STATUS="${STATUS}${GIT_PROMPT_REMOTE}${GIT_REMOTE}${ResetColor}" + fi + + STATUS="${STATUS}${GIT_PROMPT_SEPARATOR}" + if [ "${GIT_STAGED}" -ne "0" ]; then + STATUS="${STATUS}${GIT_PROMPT_STAGED}${GIT_STAGED}${ResetColor}" + fi + + if [ "${GIT_CONFLICTS}" -ne "0" ]; then + STATUS="${STATUS}${GIT_PROMPT_CONFLICTS}${GIT_CONFLICTS}${ResetColor}" + fi + + if [ "${GIT_CHANGED}" -ne "0" ]; then + STATUS="${STATUS}${GIT_PROMPT_CHANGED}${GIT_CHANGED}${ResetColor}" + fi + + if [ "${GIT_UNTRACKED}" -ne "0" ]; then + STATUS="${STATUS}${GIT_PROMPT_UNTRACKED}${GIT_UNTRACKED}${ResetColor}" + fi + + if [ "${GIT_CLEAN}" -eq "1" ]; then + STATUS="${STATUS}${GIT_PROMPT_CLEAN}" + fi + + STATUS="${STATUS}${ResetColor}${GIT_PROMPT_SUFFIX}" + + + PS1="${PROMPT_START}${STATUS}${PROMPT_END}" + if [[ -n "${VIRTUAL_ENV}" ]]; then + PS1="${Blue}($(basename "${VIRTUAL_ENV}"))${ResetColor} ${PS1}" + fi + else - PYTHON_VIRTUALENV="${BLUE}(`basename \"$VIRTUAL_ENV\"`)${ResetColor} " + PS1="${EMPTY_PROMPT}" fi } -PROMPT_COMMAND=setGitPrompt +if [ -z "$OLD_GITPROMPT" ]; then + OLD_GITPROMPT=$PS1 +fi + +if [ -z "$PROMPT_COMMAND" ]; then + PROMPT_COMMAND=setGitPrompt +else + PROMPT_COMMAND="$PROMPT_COMMAND;setGitPrompt" +fi + diff --git a/gitstatus.py b/gitstatus.py index 63f4e44..a61187c 100755 --- a/gitstatus.py +++ b/gitstatus.py @@ -40,8 +40,13 @@ else: remote = '' +tag, tag_error = Popen(['git', 'describe', '--exact-match'], stdout=PIPE, stderr=PIPE).communicate() + if not branch: # not on any branch - branch = symbols['prehash']+ Popen(['git','rev-parse','--short','HEAD'], stdout=PIPE).communicate()[0][:-1] + if tag: # if we are on a tag, print the tag's name + branch = tag + else: + branch = symbols['prehash']+ Popen(['git','rev-parse','--short','HEAD'], stdout=PIPE).communicate()[0][:-1] else: remote_name = Popen(['git','config','branch.%s.remote' % branch], stdout=PIPE).communicate()[0].strip() if remote_name: