2022-01-30 11:01:58 +02:00
|
|
|
# gitstatus zsh plugin
|
|
|
|
# https://github.com/xylous/gistatus
|
|
|
|
#
|
|
|
|
# Code licensed under the MIT License
|
|
|
|
# https://raw.githubusercontent.com/xylous/gitstatus/master/LICENSE
|
|
|
|
#
|
|
|
|
# @author xylous <xylous.e@gmail.com>
|
|
|
|
# @maintainer xylous <xylous.e@gmail.com>
|
|
|
|
|
2022-01-04 22:32:30 +02:00
|
|
|
###
|
2022-01-30 11:01:58 +02:00
|
|
|
# Print a formatted gitstatus prompt to stdout
|
|
|
|
# Options: -i add a whitespace at the end, if the output isn't empty
|
2022-01-04 22:32:30 +02:00
|
|
|
###
|
2021-08-08 18:34:17 +03:00
|
|
|
function gitstatus()
|
2021-06-19 10:34:39 +03:00
|
|
|
{
|
2021-06-18 23:19:19 +03:00
|
|
|
is_in_git_repository || return 1
|
|
|
|
|
|
|
|
parse_git_status
|
|
|
|
local modified="${STATUS[1]}"
|
|
|
|
local staged="${STATUS[2]}"
|
|
|
|
local deleted="${STATUS[3]}"
|
|
|
|
local untracked="${STATUS[4]}"
|
|
|
|
unset STATUS
|
|
|
|
|
|
|
|
git_grab_current_branch
|
2022-02-04 22:42:44 +02:00
|
|
|
local branch="${REPLY}"
|
2021-06-18 23:19:19 +03:00
|
|
|
|
|
|
|
git_grab_remote_branch
|
2022-02-04 22:42:44 +02:00
|
|
|
local remote="${REPLY}"
|
2021-06-18 23:19:19 +03:00
|
|
|
|
|
|
|
[[ ! -z "$remote" ]] \
|
2021-06-19 10:34:39 +03:00
|
|
|
&& git_local_remote_diffs "$branch" "$remote" \
|
2021-06-18 23:39:12 +03:00
|
|
|
&& local commit_diffs="$REPLY"
|
2021-06-18 23:19:19 +03:00
|
|
|
|
2022-02-04 22:42:44 +02:00
|
|
|
git_determine_color ${modified} ${staged} ${deleted} ${untracked}
|
|
|
|
local color="${REPLY}"
|
2021-06-18 23:19:19 +03:00
|
|
|
|
|
|
|
(( modified > 0 )) \
|
2022-02-04 22:42:44 +02:00
|
|
|
&& modified="!${modified} "
|
2021-06-18 23:19:19 +03:00
|
|
|
(( staged > 0 )) \
|
2022-02-04 22:42:44 +02:00
|
|
|
&& staged="+${staged} "
|
2021-06-18 23:19:19 +03:00
|
|
|
(( deleted > 0 )) \
|
2022-02-04 22:42:44 +02:00
|
|
|
&& deleted="-${deleted} "
|
2021-06-18 23:19:19 +03:00
|
|
|
(( untracked > 0 )) \
|
2022-02-04 22:42:44 +02:00
|
|
|
&& untracked="?${untracked} "
|
2021-06-18 23:19:19 +03:00
|
|
|
|
2022-02-20 08:35:32 +02:00
|
|
|
local output="${color}"
|
2022-02-04 22:42:44 +02:00
|
|
|
output+=" ${branch} "
|
|
|
|
output+="${commit_diffs}"
|
|
|
|
output+="${modified}"
|
|
|
|
output+="${staged}"
|
|
|
|
output+="${deleted}"
|
|
|
|
output+="${untracked}"
|
2021-06-18 23:19:19 +03:00
|
|
|
|
2022-02-04 22:42:44 +02:00
|
|
|
local true_output="$(sed 's/[ \t]*$//' <<<"${output}")" # remove trailing whitespace
|
2022-01-04 22:32:30 +02:00
|
|
|
|
|
|
|
if [[ "$1" == "-i" ]]; then
|
|
|
|
true_output+=" "
|
|
|
|
fi
|
|
|
|
|
2021-09-15 20:25:31 +03:00
|
|
|
true_output+=$'%F{default}'
|
|
|
|
echo "${true_output}"
|
2021-06-24 14:15:15 +03:00
|
|
|
|
|
|
|
unset REPLY
|
2021-06-18 23:19:19 +03:00
|
|
|
}
|
|
|
|
|
2021-05-15 16:47:38 +03:00
|
|
|
###
|
2021-06-18 23:19:19 +03:00
|
|
|
# Check if we're in a git repository
|
2021-05-15 17:34:41 +03:00
|
|
|
# Arguments: none
|
2021-06-19 10:34:39 +03:00
|
|
|
# Returns: 0 if in a git repo, 1 otherwise
|
2021-05-15 16:47:38 +03:00
|
|
|
###
|
2021-06-18 23:19:19 +03:00
|
|
|
function is_in_git_repository()
|
|
|
|
{
|
2021-05-15 17:34:41 +03:00
|
|
|
git rev-parse --git-dir &>/dev/null || return 1
|
2021-05-15 16:47:38 +03:00
|
|
|
}
|
|
|
|
|
2021-06-19 10:34:39 +03:00
|
|
|
###
|
|
|
|
# Return current branch we're on
|
|
|
|
# Arguments: none
|
|
|
|
###
|
2021-06-18 23:19:19 +03:00
|
|
|
function git_grab_current_branch()
|
|
|
|
{
|
|
|
|
typeset -g REPLY="$(git branch --show-current)"
|
|
|
|
}
|
|
|
|
|
2021-06-19 10:34:39 +03:00
|
|
|
###
|
|
|
|
# Return remote branch that the local one is tracking
|
|
|
|
# Arguemnts: none
|
|
|
|
###
|
2021-06-18 23:19:19 +03:00
|
|
|
function git_grab_remote_branch()
|
|
|
|
{
|
|
|
|
local symbolic_ref="$(git symbolic-ref -q HEAD)"
|
2022-02-04 22:42:44 +02:00
|
|
|
typeset -g REPLY="$(git for-each-ref --format='%(upstream:short)' "${symbolic_ref}")"
|
2021-06-18 23:19:19 +03:00
|
|
|
}
|
|
|
|
|
2021-05-15 16:47:38 +03:00
|
|
|
###
|
2021-06-19 10:34:39 +03:00
|
|
|
# Find how many things have changed since last git commit
|
2021-05-15 17:34:41 +03:00
|
|
|
# Arguments: none
|
2021-05-15 16:47:38 +03:00
|
|
|
###
|
2021-06-18 23:19:19 +03:00
|
|
|
function parse_git_status()
|
|
|
|
{
|
2021-05-15 16:47:38 +03:00
|
|
|
git status --porcelain=v1 | while IFS= read -r status_line; do
|
|
|
|
case "$status_line" in
|
2021-08-08 18:34:17 +03:00
|
|
|
' M '*)
|
2021-06-18 23:19:19 +03:00
|
|
|
((modified++))
|
2021-05-15 16:47:38 +03:00
|
|
|
;;
|
|
|
|
'A '*|'M '*)
|
2021-06-18 23:19:19 +03:00
|
|
|
((staged++))
|
2021-05-15 16:47:38 +03:00
|
|
|
;;
|
2022-01-22 18:13:31 +02:00
|
|
|
'D '*|' D '*)
|
2021-06-18 23:19:19 +03:00
|
|
|
((deleted++))
|
2021-05-15 16:47:38 +03:00
|
|
|
;;
|
|
|
|
'?? '*)
|
2021-06-18 23:19:19 +03:00
|
|
|
((untracked++))
|
2021-05-15 16:47:38 +03:00
|
|
|
;;
|
2022-01-29 11:09:25 +02:00
|
|
|
'MM '*|'AM '*)
|
2021-06-18 23:19:19 +03:00
|
|
|
((staged++))
|
|
|
|
((modified++))
|
2021-05-15 16:47:38 +03:00
|
|
|
;;
|
2022-04-09 19:34:47 +03:00
|
|
|
'R '*)
|
|
|
|
((staged++))
|
|
|
|
((deleted++))
|
|
|
|
;;
|
2021-05-15 16:47:38 +03:00
|
|
|
esac
|
|
|
|
done
|
|
|
|
|
2022-02-04 22:42:44 +02:00
|
|
|
typeset -g STATUS=("${modified}" "${staged}" "${deleted}" "${untracked}")
|
2021-06-18 23:19:19 +03:00
|
|
|
return 0
|
2021-05-15 16:47:38 +03:00
|
|
|
}
|
|
|
|
|
2021-06-19 10:34:39 +03:00
|
|
|
###
|
|
|
|
# Look at how many commits a local branch is ahead/behind of remote branch
|
|
|
|
# Arguments: $1 local branch
|
|
|
|
# $2 remote branch
|
|
|
|
###
|
|
|
|
function git_local_remote_diffs()
|
2021-06-18 23:19:19 +03:00
|
|
|
{
|
|
|
|
local local_branch="$1"
|
|
|
|
local remote_branch="$2"
|
2021-05-15 16:47:38 +03:00
|
|
|
|
2022-02-04 22:42:44 +02:00
|
|
|
local differences="$(git rev-list --left-right --count ${local_branch}...${remote_branch})"
|
|
|
|
local commits_ahead=$(echo -n "${differences}" | awk '{print $1}')
|
|
|
|
local commits_behind=$(echo -n "${differences}" | awk '{print $2}')
|
2021-06-18 23:39:12 +03:00
|
|
|
local ahead="" behind=""
|
2021-06-18 23:19:19 +03:00
|
|
|
|
2021-10-06 10:55:51 +03:00
|
|
|
local result=""
|
|
|
|
|
2021-06-18 23:19:19 +03:00
|
|
|
(( $commits_ahead > 0 )) \
|
2022-02-04 22:42:44 +02:00
|
|
|
&& ahead="↑${commits_ahead}"
|
2021-06-18 23:19:19 +03:00
|
|
|
(( $commits_behind > 0 )) \
|
2022-02-04 22:42:44 +02:00
|
|
|
&& behind="↓${commits_behind}"
|
2021-06-18 23:19:19 +03:00
|
|
|
|
2021-10-06 10:55:51 +03:00
|
|
|
if [[ ! -z "${ahead}" ]]; then
|
|
|
|
result="${ahead} "
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [[ ! -z "${behind}" ]]; then
|
|
|
|
result="${behind} "
|
2021-09-15 20:25:31 +03:00
|
|
|
fi
|
2021-10-06 10:55:51 +03:00
|
|
|
|
|
|
|
typeset -g REPLY="${result}"
|
2021-06-18 23:19:19 +03:00
|
|
|
}
|
|
|
|
|
2021-06-19 10:34:39 +03:00
|
|
|
###
|
2022-01-04 22:32:30 +02:00
|
|
|
# If there is anything that changed from the past commit, return yellow.
|
2021-06-19 10:34:39 +03:00
|
|
|
# Otherwise, green.
|
|
|
|
# Arguments: list of how many things changed
|
|
|
|
###
|
2021-06-18 23:19:19 +03:00
|
|
|
function git_determine_color()
|
|
|
|
{
|
|
|
|
for i in "$@"; do
|
|
|
|
if (( $i > 0 )); then
|
2022-02-20 08:35:32 +02:00
|
|
|
typeset -g REPLY=$'%F{yellow}'
|
2021-06-18 23:19:19 +03:00
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
done
|
2022-02-20 08:35:32 +02:00
|
|
|
typeset -g REPLY=$'%F{green}'
|
2021-06-18 23:19:19 +03:00
|
|
|
return 0
|
2021-05-15 16:47:38 +03:00
|
|
|
}
|