diff options
Diffstat (limited to 'plugins/git-prompt')
-rw-r--r-- | plugins/git-prompt/README.md | 66 | ||||
-rw-r--r-- | plugins/git-prompt/git-prompt.plugin.zsh | 22 | ||||
-rw-r--r-- | plugins/git-prompt/gitstatus.py | 42 |
3 files changed, 108 insertions, 22 deletions
diff --git a/plugins/git-prompt/README.md b/plugins/git-prompt/README.md new file mode 100644 index 000000000..c6610fa94 --- /dev/null +++ b/plugins/git-prompt/README.md @@ -0,0 +1,66 @@ +# git-prompt plugin + +A `zsh` prompt that displays information about the current git repository. In particular: +the branch name, difference with remote branch, number of files staged or changed, etc. + +To use it, add `git-prompt` to the plugins array in your zshrc file: + +```zsh +plugins=(... git-prompt) +``` + +See the [original repository](https://github.com/olivierverdier/zsh-git-prompt). + +## Prerequisites +This plugin uses `python`, so your host needs to have it installed + +## 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 +- `(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; the repository is otherwise clean +- `(:70c2952|✔)`: not on any branch; parent commit has hash `70c2952`; the repository is otherwise clean +- `(master|⚑2)`: on branch `master`, there are 2 stashed changes + +## Prompt Structure + +By default, the general appearance of the prompt is: + +``` +(<branch><branch tracking>|<local status>) +``` + +The symbols are as follows: + +### Local Status Symbols + +| Symbol | Meaning | +|--------|--------------------------------| +| ✔ | repository clean | +| ●n | there are `n` staged files | +| ✖n | there are `n` unmerged files | +| ✚n | there are `n` unstaged files | +| ⚑n | there are `n` stashed changes | +| … | there are some untracked files | + +### Branch Tracking Symbols + +| Symbol | Meaning | +|--------|---------------------------------------------------------------| +| ↑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 | + +## Customisation + +- Set the variable `ZSH_THEME_GIT_PROMPT_CACHE` to any value in order to enable caching. +- You may also change a number of variables (whose name start with `ZSH_THEME_GIT_PROMPT_`) + to change the appearance of the prompt. Take a look at the bottom of the [plugin file](git-prompt.plugin.zsh)` + to see what variables are available. + + +**Enjoy!** diff --git a/plugins/git-prompt/git-prompt.plugin.zsh b/plugins/git-prompt/git-prompt.plugin.zsh index 2776f297f..a4c952471 100644 --- a/plugins/git-prompt/git-prompt.plugin.zsh +++ b/plugins/git-prompt/git-prompt.plugin.zsh @@ -1,6 +1,3 @@ -# ZSH Git Prompt Plugin from: -# https://github.com/olivierverdier/zsh-git-prompt - __GIT_PROMPT_DIR="${0:A:h}" ## Hook function definitions @@ -23,9 +20,10 @@ function precmd_update_git_vars() { fi } -chpwd_functions+=(chpwd_update_git_vars) -precmd_functions+=(precmd_update_git_vars) -preexec_functions+=(preexec_update_git_vars) +autoload -U add-zsh-hook +add-zsh-hook chpwd chpwd_update_git_vars +add-zsh-hook precmd precmd_update_git_vars +add-zsh-hook preexec preexec_update_git_vars ## Function definitions @@ -42,6 +40,8 @@ function update_current_git_vars() { GIT_CONFLICTS=$__CURRENT_GIT_STATUS[5] GIT_CHANGED=$__CURRENT_GIT_STATUS[6] GIT_UNTRACKED=$__CURRENT_GIT_STATUS[7] + GIT_STASHED=$__CURRENT_GIT_STATUS[8] + GIT_CLEAN=$__CURRENT_GIT_STATUS[9] } git_super_status() { @@ -65,9 +65,12 @@ git_super_status() { 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}%}" + STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_UNTRACKED$GIT_UNTRACKED%{${reset_color}%}" + fi + if [ "$GIT_STASHED" -ne "0" ]; then + STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_STASHED$GIT_STASHED%{${reset_color}%}" fi - if [ "$GIT_CHANGED" -eq "0" ] && [ "$GIT_CONFLICTS" -eq "0" ] && [ "$GIT_STAGED" -eq "0" ] && [ "$GIT_UNTRACKED" -eq "0" ]; then + if [ "$GIT_CLEAN" -eq "1" ]; then STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CLEAN" fi STATUS="$STATUS%{${reset_color}%}$ZSH_THEME_GIT_PROMPT_SUFFIX" @@ -85,7 +88,8 @@ ZSH_THEME_GIT_PROMPT_CONFLICTS="%{$fg[red]%}%{✖%G%}" ZSH_THEME_GIT_PROMPT_CHANGED="%{$fg[blue]%}%{✚%G%}" ZSH_THEME_GIT_PROMPT_BEHIND="%{↓%G%}" ZSH_THEME_GIT_PROMPT_AHEAD="%{↑%G%}" -ZSH_THEME_GIT_PROMPT_UNTRACKED="%{…%G%}" +ZSH_THEME_GIT_PROMPT_UNTRACKED="%{$fg[cyan]%}%{…%G%}" +ZSH_THEME_GIT_PROMPT_STASHED="%{$fg_bold[blue]%}%{⚑%G%}" ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg_bold[green]%}%{✔%G%}" # Set the prompt. diff --git a/plugins/git-prompt/gitstatus.py b/plugins/git-prompt/gitstatus.py index a4d07cde6..786274a71 100644 --- a/plugins/git-prompt/gitstatus.py +++ b/plugins/git-prompt/gitstatus.py @@ -1,36 +1,44 @@ #!/usr/bin/env python from __future__ import print_function +import os import sys import re -import shlex from subprocess import Popen, PIPE, check_output def get_tagname_or_hash(): """return tagname if exists else hash""" - cmd = 'git log -1 --format="%h%d"' - output = check_output(shlex.split(cmd)).decode('utf-8').strip() - hash_, tagname = None, None # get hash - m = re.search('\(.*\)$', output) - if m: - hash_ = output[:m.start()-1] + hash_cmd = ['git', 'rev-parse', '--short', 'HEAD'] + hash_ = check_output(hash_cmd).decode('utf-8').strip() + # get tagname - m = re.search('tag: .*[,\)]', output) - if m: - tagname = 'tags/' + output[m.start()+len('tag: '): m.end()-1] + tags_cmd = ['git', 'for-each-ref', '--points-at=HEAD', '--count=2', '--sort=-version:refname', '--format=%(refname:short)', 'refs/tags'] + tags = check_output(tags_cmd).decode('utf-8').split() - if tagname: - return tagname.replace(' ', '') + if tags: + return tags[0] + ('+' if len(tags) > 1 else '') elif hash_: return hash_ return None +# Re-use method from https://github.com/magicmonty/bash-git-prompt to get stashs count +def get_stash(): + cmd = Popen(['git', 'rev-parse', '--git-dir'], stdout=PIPE, stderr=PIPE) + so, se = cmd.communicate() + stash_file = '%s%s' % (so.decode('utf-8').rstrip(), '/logs/refs/stash') + + try: + with open(stash_file) as f: + return sum(1 for _ in f) + except IOError: + return 0 + # `git status --porcelain --branch` can collect all information # branch, remote_branch, untracked, staged, changed, conflicts, ahead, behind -po = Popen(['git', 'status', '--porcelain', '--branch'], stdout=PIPE, stderr=PIPE) +po = Popen(['git', 'status', '--porcelain', '--branch'], env=dict(os.environ, LANG="C"), stdout=PIPE, stderr=PIPE) stdout, sterr = po.communicate() if po.returncode != 0: sys.exit(0) # Not a git repository @@ -72,6 +80,12 @@ for st in status: elif st[0] != ' ': staged.append(st) +stashed = get_stash() +if not changed and not staged and not conflicts and not untracked and not stashed: + clean = 1 +else: + clean = 0 + out = ' '.join([ branch, str(ahead), @@ -80,5 +94,7 @@ out = ' '.join([ str(len(conflicts)), str(len(changed)), str(len(untracked)), + str(stashed), + str(clean) ]) print(out, end='') |