Skip to content

Commit

Permalink
the gitstatus Python script now delivers much more information
Browse files Browse the repository at this point in the history
it is easier to customize the appearance of the prompt by setting the various theme variables
  • Loading branch information
olivierverdier committed Aug 21, 2011
1 parent df359dd commit f3bd3e4
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 44 deletions.
29 changes: 15 additions & 14 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ Examples
The prompt may look like the following:

* ``(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
* ``(status●2)``: on branch ``status``, 2 files staged
* ``(master✚7…)``: on branch ``master``, 7 files changed, some files untracked
* ``(master✖2✚3)``: on branch ``master``, 2 conflicts, 3 files changed
* ``(experimental↓2↑3)``: on branch ``experimental``; your branch has diverged by 3 commits, remote by 2 commits
* ``(:70c2952)``: not on any branch; parent commit has sha1 ``70c2952``

Here is how it could look like when you are ahead by 2 commits, and have 3 staged files, 1 changed but unstaged file, and some untracked files, on branch ``dev``:
Here is how it could look like when you are ahead by 4 commits, behind by 5 commits, and have 1 staged files, 1 changed but unstaged file, and some untracked files, on branch ``dev``:

.. image:: http://files.droplr.com.s3.amazonaws.com/files/35740123/14GMbk.Picture%2023.png
.. image:: https://github.com/olivierverdier/zsh-git-prompt/raw/master/screenshot.png
:alt: Example


Expand All @@ -31,30 +32,30 @@ Symbols
The symbols are as follows:

* Status Symbols
:: repository clean
:n: there are ``n`` staged files
:n: there are ``n`` unmerged files
:n: there are ``n`` changed but *unstaged* files
:: repository clean
:n: there are ``n`` staged files
:n: there are ``n`` unmerged files
:n: there are ``n`` changed but *unstaged* files
:…: there are some untracked files

* Branch Symbols
:↑n: ahead of remote by ``n`` commits
:↓n: behind remote by ``n`` commits
:↓m↑n: branches diverged, other by ``m`` commits, yours by ``n`` commits
:\:: when the branch name starts with a colon ``:``, it means it's actually a sha1, not a branch (although it should be pretty clear, unless you name your branches like sha1 :-)
:\:: when the branch name starts with a colon ``:``, it means it's actually a hash, not a branch (although it should be pretty clear, unless you name your branches like hashes :-)

Install
-------

#. Create the directory ``~/.zsh/git-prompt`` if it does not exist (this location is customizable).
#. Move the file ``gitstatus.py`` into ``~/.zsh/git-prompt/``.
#. Source the file ``zshrc.sh`` from your ``~/.zshrc`` config file, and, optionally, configure your prompt. So, somewhere in ``~/.zshrc``, you should have::
#. Source the file ``zshrc.sh`` from your ``~/.zshrc`` config file, and, configure your prompt. So, somewhere in ``~/.zshrc``, you should have::

source path/to/zshrc.sh
# configure the following, or leave it commented out:
# PROMPT='%B%m%~%b$(prompt_git_info) %# '
# an example prompt
PROMPT='%B%m%~%b$(git_super_status) %# '

#. You may also redefine the function ``prompt_git_info`` (after the ``source`` statement) to adapt it to your needs (change the colour, or the order of each piece of information). Take a look in the file ``zshrc.sh`` to see what this function may look like.
#. You may also redefine the function ``git_super_status`` (after the ``source`` statement) to adapt it to your needs (to change the order in which the information is displayed). You may also change a number of variables (which name start with ``ZSH_THEME_GIT_PROMPT_``) to change the appearance of the prompt. Take a look in the file ``zshrc.sh`` to see how this function is defined, and what variables are available.
#. Go in a git repository and test it!

**Enjoy!**
**Enjoy!**
41 changes: 19 additions & 22 deletions gitstatus.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# -*- coding: UTF-8 -*-

# change those symbols to whatever you prefer
symbols = {'ahead of': '↑', 'behind': '↓', 'staged':'♦', 'changed':'‣', 'untracked':'…', 'clean':'⚡', 'unmerged':'≠', 'sha1':':'}
symbols = {'ahead of': '↑', 'behind': '↓', 'staged':'♦', 'changed':'‣', 'untracked':'…', 'clean':'⚡', 'conflict':'≠', 'prehash':':'}

from subprocess import Popen, PIPE

Expand All @@ -14,29 +14,26 @@

branch = branch[11:-1]

status = ''

changed = [namestat[0] for namestat in Popen(['git','diff','--name-status'], stdout=PIPE).communicate()[0].splitlines()]
staged = [namestat[0] for namestat in Popen(['git','diff', '--staged','--name-status'], stdout=PIPE).communicate()[0].splitlines()]
nb_changed = len(changed) - changed.count('U')
nb_U = staged.count('U')
nb_staged = len(staged) - nb_U
if nb_staged:
status += '%s%s' % (symbols['staged'], nb_staged)
if nb_U:
status += '%s%s' % (symbols['unmerged'], nb_U)
if nb_changed:
status += '%s%s' % (symbols['changed'], nb_changed)
nb = len(Popen(['git','ls-files','--others','--exclude-standard'],stdout=PIPE).communicate()[0].splitlines())
if nb:
status += symbols['untracked']
if status == '':
status = symbols['clean']

changed_files = [namestat[0] for namestat in Popen(['git','diff','--name-status'], stdout=PIPE).communicate()[0].splitlines()]
staged_files = [namestat[0] for namestat in Popen(['git','diff', '--staged','--name-status'], stdout=PIPE).communicate()[0].splitlines()]
nb_changed = len(changed_files) - changed_files.count('U')
nb_U = staged_files.count('U')
nb_staged = len(staged_files) - nb_U
staged = str(nb_staged)
conflicts = str(nb_U)
changed = str(nb_changed)
nb_untracked = len(Popen(['git','ls-files','--others','--exclude-standard'],stdout=PIPE).communicate()[0].splitlines())
untracked = str(nb_untracked)
if not nb_changed and not nb_staged and not nb_U and not nb_untracked:
clean = '1'
else:
clean = '0'

remote = ''

if not branch: # not on any branch
branch = symbols['sha1']+ Popen(['git','rev-parse','--short','HEAD'], stdout=PIPE).communicate()[0][:-1]
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:
Expand All @@ -55,6 +52,6 @@
remote += '%s%s' % (symbols['behind'], behind)
if ahead:
remote += '%s%s' % (symbols['ahead of'], ahead)
print '\n'.join([branch,remote,status])

print '\n'.join([branch,remote,staged,conflicts,changed,untracked,clean])

Binary file added screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
55 changes: 47 additions & 8 deletions zshrc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,55 @@ function update_current_git_vars() {

local gitstatus="$__GIT_PROMPT_DIR/gitstatus.py"
_GIT_STATUS=`python ${gitstatus}`
__CURRENT_GIT_STATUS=("${(f)_GIT_STATUS}")
__CURRENT_GIT_STATUS=("${(@f)_GIT_STATUS}")
GIT_BRANCH=$__CURRENT_GIT_STATUS[1]
GIT_REMOTE=$__CURRENT_GIT_STATUS[2]
GIT_STAGED=$__CURRENT_GIT_STATUS[3]
GIT_CONFLICTS=$__CURRENT_GIT_STATUS[4]
GIT_CHANGED=$__CURRENT_GIT_STATUS[5]
GIT_UNTRACKED=$__CURRENT_GIT_STATUS[6]
GIT_CLEAN=$__CURRENT_GIT_STATUS[7]
}

function prompt_git_info() {

git_super_status() {
if [ -n "$__CURRENT_GIT_STATUS" ]; then
echo "(%{${fg[red]}%}$__CURRENT_GIT_STATUS[1]%{${fg[default]}%}$__CURRENT_GIT_STATUS[2]%{${fg[magenta]}%}$__CURRENT_GIT_STATUS[3]%{${fg[default]}%})"
fi
STATUS="($GIT_BRANCH"
STATUS="$ZSH_THEME_GIT_PROMPT_PREFIX$ZSH_THEME_GIT_PROMPT_BRANCH$GIT_BRANCH%{${reset_color}%}"
if [ -n "$GIT_REMOTE" ]; then
STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_REMOTE$GIT_REMOTE%{${reset_color}%}"
fi
STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_SEPARATOR"
if [ "$GIT_STAGED" -ne "0" ]; then
STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_STAGED$GIT_STAGED%{${reset_color}%}"
fi
if [ "$GIT_CONFLICTS" -ne "0" ]; then
STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CONFLICTS$GIT_CONFLICTS%{${reset_color}%}"
fi
if [ "$GIT_CHANGED" -ne "0" ]; then
STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CHANGED$GIT_CHANGED%{${reset_color}%}"
fi
if [ "$GIT_UNTRACKED" -ne "0" ]; then
STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_UNTRACKED%{${reset_color}%}"
fi
if [ "$GIT_CLEAN" -eq "1" ]; then
STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CLEAN"
fi
STATUS="$STATUS%{${reset_color}%}$ZSH_THEME_GIT_PROMPT_SUFFIX"
echo "$STATUS"
fi
}

# Set the prompt.
PROMPT='%B%m%~%b$(prompt_git_info) %# '
# for a right prompt:
# RPROMPT='%b$(prompt_git_info)'
# Default values for the appearance of the prompt. Configure at will.
ZSH_THEME_GIT_PROMPT_PREFIX="("
ZSH_THEME_GIT_PROMPT_SUFFIX=")"
ZSH_THEME_GIT_PROMPT_SEPARATOR="|"
ZSH_THEME_GIT_PROMPT_BRANCH="%{$fg_bold[magenta]%}"
ZSH_THEME_GIT_PROMPT_STAGED="%{$fg[red]%}●"
ZSH_THEME_GIT_PROMPT_CONFLICTS="%{$fg[red]%}✖"
ZSH_THEME_GIT_PROMPT_CHANGED="%{$fg[blue]%}✚"
ZSH_THEME_GIT_PROMPT_REMOTE=""
ZSH_THEME_GIT_PROMPT_UNTRACKED=""
ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg_bold[green]%}✔"


0 comments on commit f3bd3e4

Please sign in to comment.