Skip to content

Instantly share code, notes, and snippets.

@Milly
Created October 7, 2021 03:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Milly/f2e57dab3852e0750dd21f186d0f5dd9 to your computer and use it in GitHub Desktop.
Save Milly/f2e57dab3852e0750dd21f186d0f5dd9 to your computer and use it in GitHub Desktop.
zstyle ':vcs_info:git+set-message:*' hooks git_compute_vars
function __git_eread() {
[[ -r "$1" ]] && IFS=$'\r\n' read "$2" <"$1"
}
function __git_config_hash() {
local _reg="$1"
local _out="$(git config -z --get-regexp "$_reg" 2>/dev/null|tr '\0\n' '\n ')"
local _k _v
while read -r _k _v; do config[${_k}]=$_v; done <<< "$_out"
}
function +vi-git_compute_vars() {
[[ $1 == 0 ]] || return 0
local repo_info="$(git rev-parse \
--absolute-git-dir \
--is-inside-git-dir \
--is-inside-work-tree \
--is-bare-repository \
--short HEAD \
2>/dev/null)" || return
: ${(A)repo_info::="${(@f)repo_info}"}
local git_dir=${repo_info[1]}
local inside_gitdir=${repo_info[2]}
local inside_worktree=${repo_info[3]}
local bare_repo=${repo_info[4]}
local short_sha=${repo_info[5]}
local dir_state=
local unstaged=
local staged=
local stashed=
local untracked=
local upstream=
local upstream_name=
if [[ $inside_gitdir == 'true' ]]; then
if [[ $bare_repo == 'true' ]]; then
dir_state="%F{red}BARE%f:"
else
dir_state="%F{red}GIT_DIR%f!"
fi
elif [[ $inside_worktree == true ]]; then
git diff --no-ext-diff --quiet || unstaged='*'
git diff --no-ext-diff --cached --quiet || staged='+'
[[ -z $short_sha && -z $staged ]] && staged='#'
git rev-parse --verify --quiet refs/stash >/dev/null && stashed='$'
git ls-files --others --exclude-standard --directory \
--no-empty-directory --error-unmatch -- ':/*' >/dev/null 2>/dev/null \
&& untracked='%'
local count=($(git rev-list --count --left-right '@{upstream}...HEAD' 2>/dev/null))
if [[ ${#count} == 0 ]]; then # no upstream
:
elif [[ ${count[1]} == 0 ]]; then # equal or ahead
[[ ${count[2]} == 0 ]] && upstream='=' || upstream="+${count[2]}"
elif [[ ${count[2]} == 0 ]]; then # behind
upstream="-${count[1]}"
else # diverged
upstream="+${count[2]}-${count[1]}"
fi
[[ -n $upstream ]] \
&& upstream_name="$(git rev-parse --abbrev-ref '@{upstream}' 2>/dev/null)"
fi
local action=
local branch=
local step=
local total=
local detached=no
if [[ -d "$git_dir/rebase-merge" ]]; then
__git_eread "$git_dir/rebase-merge/head-name" branch
__git_eread "$git_dir/rebase-merge/msgnum" step
__git_eread "$git_dir/rebase-merge/end" total
if [[ -f "$git_dir/rebase-merge/interactive" ]]; then
action="REBASE-i"
else
action="REBASE-m"
fi
else
if [[ -d "$git_dir/rebase-apply" ]]; then
__git_eread "$git_dir/rebase-apply/next" step
__git_eread "$git_dir/rebase-apply/last" total
if [[ -f "$git_dir/rebase-apply/rebasing" ]]; then
__git_eread "$git_dir/rebase-apply/head-name" branch
action="REBASE"
elif [[ -f "$git_dir/rebase-apply/applying" ]]; then
action="AM"
else
action="AM/REBASE"
fi
elif [[ -f "$git_dir/MERGE_HEAD" ]]; then
action="MERGING"
elif [[ -f "$git_dir/CHERRY_PICK_HEAD" ]]; then
action="CHERRY-PICKING"
elif [[ -f "$git_dir/REVERT_HEAD" ]]; then
action="REVERTING"
elif [[ -f "$git_dir/BISECT_LOG" ]]; then
action="BISECTING"
fi
if [[ -n "$branch" ]]; then
:
elif [[ -h "$git_dir/HEAD" ]]; then
# symlink symbolic ref
branch="$(git symbolic-ref HEAD 2>/dev/null)"
else
local head=
__git_eread "$git_dir/HEAD" head || return
# is it a symbolic ref?
branch="${head#ref: }"
if [[ "$head" = "$branch" ]]; then
detached=yes
branch="$(git describe --tags --exact-match HEAD 2>/dev/null)" ||
branch="$short_sha..."
branch="($branch)"
fi
fi
fi
branch="%F{magenta}${branch#refs/heads/}%f"
[[ -n "$action" ]] && action="|%F{red}$action%f"
[[ -n "$step" && -n "$total" ]] && action="$action $step/$total"
local state=
if [[ -z "$unstaged$staged$untracked" ]]; then
state="%F{green}OK%f"
else
[[ -n "$unstaged" ]] && state="$state${state:+,}%B%F{red}Changed%b%f"
[[ -n "$staged" ]] && state="$state${state:+,}%B%F{green}Staged%b%f"
[[ -n "$untracked" ]] && state="$state${state:+,}%F{yellow}Untrack%f"
fi
[[ -n "$stashed" ]] && state="$state${state:+,}%F{cyan}Stash%f"
state="$state"
local sub_module=
[[ "$git_dir" == */.git/modules/* ]] \
&& sub_module="%F{white}${git_dir#*/.git/modules/}%f:"
local -A config
__git_config_hash '^user\.(name|email)$'
local user="%F{yellow}${config[user.name]}"
[[ -n ${config[user.email]} ]] && user="$user %F{cyan}<${config[user.email]}>"
user="$user%f"
hook_com[message]="%f(git)-[${dir_state}${sub_module}${branch}${upstream}](${state}${action}):$user%f"
ret=1 # show $hook[message] as is
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment