mirror of
https://github.com/ohmyzsh/ohmyzsh.git
synced 2026-05-01 04:30:37 +02:00
167 lines
5.7 KiB
Bash
167 lines
5.7 KiB
Bash
# ZSH Git Prompt Plugin from:
|
|
# http://github.com/olivierverdier/zsh-git-prompt
|
|
|
|
__GIT_PROMPT_DIR="${0:A:h}"
|
|
|
|
## Hook function definitions
|
|
function chpwd_update_git_vars() {
|
|
update_current_git_vars
|
|
}
|
|
|
|
function preexec_update_git_vars() {
|
|
case "$2" in
|
|
git*|hub*|gh*|stg*)
|
|
__EXECUTED_GIT_COMMAND=1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
function precmd_update_git_vars() {
|
|
if [ -n "$__EXECUTED_GIT_COMMAND" ] || [ ! -n "$ZSH_THEME_GIT_PROMPT_CACHE" ]; then
|
|
update_current_git_vars
|
|
unset __EXECUTED_GIT_COMMAND
|
|
fi
|
|
}
|
|
|
|
chpwd_functions+=(chpwd_update_git_vars)
|
|
precmd_functions+=(precmd_update_git_vars)
|
|
preexec_functions+=(preexec_update_git_vars)
|
|
|
|
|
|
## Function definitions
|
|
|
|
function get_tagname_or_hash() {
|
|
local log_string
|
|
local refs ref
|
|
local ret_hash ret_tag
|
|
log_string="$(git log -1 --decorate=full --format="%h%d" 2> /dev/null)"
|
|
if [[ "$log_string" == *' ('*')' ]]; then
|
|
ret_hash="${log_string%% (*)}"
|
|
refs="${(M)log_string%% (*)}"
|
|
refs="${refs# \(}"
|
|
refs="${refs%\)}"
|
|
for ref in ${(s:, :)refs}; do
|
|
if [[ "$ref" == 'refs/tags/'* ]]; then # git 1.7.x
|
|
ret_tag="${ref#refs/tags/}"
|
|
elif [[ "$ref" == 'tag: refs/tags/'* ]]; then # git 2.1.x
|
|
ret_tag="${ref#tag: refs/tags/}"
|
|
fi
|
|
if [[ "$ret_tag" != "" ]]; then
|
|
TAG_OR_HASH="tags/$ret_tag"
|
|
return
|
|
fi
|
|
done
|
|
TAG_OR_HASH="$ret_hash"
|
|
fi
|
|
}
|
|
|
|
function update_current_git_vars() {
|
|
local branch branch_description branch_parts
|
|
local ahead=0 behind=0
|
|
local staged=0 conflict=0 changed=0 untracked=0
|
|
local status_string status_line
|
|
local divergence div
|
|
|
|
__CURRENT_GIT_STATUS=0
|
|
status_string="$(git status --branch --porcelain -z 2> /dev/null)"
|
|
if [[ $? -ne 0 ]]; then
|
|
# not a git repository
|
|
return
|
|
fi
|
|
__CURRENT_GIT_STATUS=1
|
|
|
|
for status_line in ${(0)status_string}; do
|
|
if [[ "${status_line:0:2}" == '##' ]]; then
|
|
branch_description="${status_line:2}"
|
|
if [[ "$branch_description" == *'Initial commit on '* ]]; then
|
|
branch="${branch_description/#*'Initial commit on '/}"
|
|
elif [[ "$branch_description" == *'no branch'* ]]; then
|
|
get_tagname_or_hash
|
|
branch="$TAG_OR_HASH"
|
|
elif [[ "$branch_description" != *'...'* ]]; then
|
|
branch="${branch_description# }"
|
|
else
|
|
# local and remote branch info
|
|
branch_parts=(${(s:...:)branch_description})
|
|
branch="${branch_parts[1]# }"
|
|
if [[ $#branch_parts -ne 1 ]]; then
|
|
# ahead or behind
|
|
divergence="${(M)branch_parts[2]%\[*\]}"
|
|
divergence="${divergence#\[}"
|
|
divergence="${divergence%\]}"
|
|
for div in ${(s:, :)divergence}; do
|
|
if [[ "$div" == 'ahead '* ]]; then
|
|
ahead="${div#ahead }"
|
|
elif [[ "$div" == 'behind '* ]]; then
|
|
behind="${div#behind }"
|
|
fi
|
|
done
|
|
fi
|
|
fi
|
|
elif [[ "${status_line:0:2}" == '??' ]]; then
|
|
untracked=$((untracked + 1))
|
|
else
|
|
if [[ "${status_line:1:1}" == 'M' ]]; then
|
|
changed=$((changed + 1))
|
|
elif [[ "${status_line:0:1}" == 'U' ]]; then
|
|
conflict=$((conflict + 1))
|
|
elif [[ "${status_line:0:1}" != ' ' ]]; then
|
|
staged=$((staged + 1))
|
|
fi
|
|
fi
|
|
done
|
|
GIT_BRANCH="$branch"
|
|
GIT_AHEAD="$ahead"
|
|
GIT_BEHIND="$behind"
|
|
GIT_STAGED="$staged"
|
|
GIT_CONFLICTS="$conflict"
|
|
GIT_CHANGED="$changed"
|
|
GIT_UNTRACKED="$untracked"
|
|
}
|
|
|
|
git_super_status() {
|
|
precmd_update_git_vars
|
|
if [ "$__CURRENT_GIT_STATUS" -eq 1 ]; then
|
|
STATUS="$ZSH_THEME_GIT_PROMPT_PREFIX$ZSH_THEME_GIT_PROMPT_BRANCH$GIT_BRANCH%{${reset_color}%}"
|
|
if [ "$GIT_BEHIND" -ne "0" ]; then
|
|
STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_BEHIND$GIT_BEHIND%{${reset_color}%}"
|
|
fi
|
|
if [ "$GIT_AHEAD" -ne "0" ]; then
|
|
STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_AHEAD$GIT_AHEAD%{${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_CHANGED" -eq "0" ] && [ "$GIT_CONFLICTS" -eq "0" ] && [ "$GIT_STAGED" -eq "0" ] && [ "$GIT_UNTRACKED" -eq "0" ]; then
|
|
STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CLEAN"
|
|
fi
|
|
STATUS="$STATUS%{${reset_color}%}$ZSH_THEME_GIT_PROMPT_SUFFIX"
|
|
echo "$STATUS"
|
|
fi
|
|
}
|
|
|
|
# Default values for the appearance of the prompt.
|
|
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]%}%{●%G%}"
|
|
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_CLEAN="%{$fg_bold[green]%}%{✔%G%}"
|
|
|
|
# Set the prompt.
|
|
RPROMPT='$(git_super_status)'
|