374 lines
17 KiB
Bash
374 lines
17 KiB
Bash
#!/bin/bash
|
||
|
||
# Set up symbols
|
||
function _symbols() {
|
||
|
||
# Import colors
|
||
_colors_bash "$@"
|
||
|
||
__ps="$(printf '%b\u7C%b' "${BOLD}${LEMON}" "${RESET}")" # |
|
||
__ss="$(printf '%b\u2714' "${BOLD}${CYAN}")" # ✔
|
||
__dss="$(printf '%b\u002A' "${BOLD}${RED}")" # ∗
|
||
__ahs="$(printf '%b\u2191' "${BOLD}${CYAN}")" # ↑
|
||
__bhs="$(printf '%b\u2193' "${BOLD}${RED}")" # ↓
|
||
__duphs="$(printf '%b\u25B2' "${BOLD}${YELLOW}")" # ▲
|
||
__duplls="$(printf '%b\u25BC' "${BOLD}${RED}")" # ▼
|
||
__duus="$(printf '%bdu' "${BOLD}${CYAN}")" # du
|
||
__upulls="$(printf '%b\u25BD' "${BOLD}${GREEN}")" # ▽
|
||
__sts="$(printf '%b\u2192\u004D' "${BOLD}${CYAN}")" # →M
|
||
__usts="$(printf '%b\u2190\u004D' "${BOLD}${RED}")" # ←M
|
||
__stusts="$(printf '%b<M>' "${BOLD}${RED}")" # <M>
|
||
__uts="$(printf '%b\u003F' "${BOLD}${RED}")" # ?
|
||
__nfs="$(printf '%b\u002B' "${BOLD}${CYAN}")" # +
|
||
__dfs="$(printf '%bD' "${BOLD}${RED}")" # D
|
||
__rns="$(printf '%b\u2387 ' "${BOLD}${RED}")" # ⎇
|
||
}
|
||
|
||
function _get_git_branch() {
|
||
# On branches, this will return the branch name
|
||
# On non-branches, (no branch)
|
||
ref="$(git symbolic-ref HEAD 2> /dev/null | sed -e 's/refs\/heads\///')"
|
||
if [[ -n $ref ]]; then
|
||
printf '%s' "$ref"
|
||
else
|
||
printf "(no branch)"
|
||
fi
|
||
}
|
||
|
||
function _get_git_progress() {
|
||
# Detect in-progress actions (e.g. merge, rebase)
|
||
# https://github.com/git/git/blob/v1.9-rc2/wt-status.c#L1199-L1241
|
||
git_dir="$(git rev-parse --git-dir)"
|
||
|
||
# git merge
|
||
if [[ -f "$git_dir/MERGE_HEAD" ]]; then
|
||
printf " [merge]"
|
||
elif [[ -d "$git_dir/rebase-apply" ]]; then
|
||
# git am
|
||
if [[ -f "$git_dir/rebase-apply/applying" ]]; then
|
||
printf " [am]"
|
||
# git rebase
|
||
else
|
||
printf " [rebase]"
|
||
fi
|
||
elif [[ -d "$git_dir/rebase-merge" ]]; then
|
||
# git rebase --interactive/--merge
|
||
printf " [rebase]"
|
||
elif [[ -f "$git_dir/CHERRY_PICK_HEAD" ]]; then
|
||
# git cherry-pick
|
||
printf " [cherry-pick]"
|
||
fi
|
||
if [[ -f "$git_dir/BISECT_LOG" ]]; then
|
||
# git bisect
|
||
printf " [bisect]"
|
||
fi
|
||
if [[ -f "$git_dir/REVERT_HEAD" ]]; then
|
||
# git revert --no-commit
|
||
printf " [revert]"
|
||
fi
|
||
}
|
||
|
||
_prompt_is_branch1_behind_branch2 () {
|
||
# $ git log origin/master..master -1
|
||
# commit 4a633f715caf26f6e9495198f89bba20f3402a32
|
||
# Author: Todd Wolfson <todd@twolfson.com>
|
||
# Date: Sun Jul 7 22:12:17 2013 -0700
|
||
#
|
||
# Unsynced commit
|
||
|
||
# Find the first log (if any) that is in branch1 but not branch2
|
||
first_log="$(git log "$1..$2" -1 2> /dev/null)"
|
||
|
||
# Exit with 0 if there is a first log, 1 if there is not
|
||
[[ -n "$first_log" ]]
|
||
}
|
||
|
||
_prompt_branch_exists () {
|
||
# List remote branches | # Find our branch and exit with 0 or 1 if found/not found
|
||
git branch --remote 2> /dev/null | grep --quiet "$1"
|
||
}
|
||
|
||
_prompt_parse_git_ahead () {
|
||
# Grab the local and remote branch
|
||
branch="$(_get_git_branch)"
|
||
remote="$(git config --get "branch.${branch}.remote" || echo -n "origin")"
|
||
remote_branch="$remote/$branch"
|
||
|
||
# $ git log origin/master..master
|
||
# commit 4a633f715caf26f6e9495198f89bba20f3402a32
|
||
# Author: Todd Wolfson <todd@twolfson.com>
|
||
# Date: Sun Jul 7 22:12:17 2013 -0700
|
||
#
|
||
# Unsynced commit
|
||
|
||
# If the remote branch is behind the local branch
|
||
# or it has not been merged into origin (remote branch doesn't exist)
|
||
if (_prompt_is_branch1_behind_branch2 "$remote_branch" "$branch" || ! _prompt_branch_exists "$remote_branch"); then echo -n "0"; else echo -n "1"; fi
|
||
}
|
||
|
||
_prompt_parse_git_behind() {
|
||
# Grab the branch
|
||
branch="$(_get_git_branch)"
|
||
remote="$(git config --get "branch.${branch}.remote" || echo -n "origin")"
|
||
remote_branch="$remote/$branch"
|
||
|
||
# $ git log master..origin/master
|
||
# commit 4a633f715caf26f6e9495198f89bba20f3402a32
|
||
# Author: Todd Wolfson <todd@twolfson.com>
|
||
# Date: Sun Jul 7 22:12:17 2013 -0700
|
||
#
|
||
# Unsynced commit
|
||
|
||
# If the local branch is behind the remote branch
|
||
if _prompt_is_branch1_behind_branch2 "$branch" "$remote_branch"; then echo -n '0'; else echo -n '1'; fi
|
||
}
|
||
|
||
function _prompt_parse_git_dirty() {
|
||
# If the git status has *any* changes (e.g. dirty), printf our character
|
||
if [[ -n "$(git status --porcelain 2> /dev/null)" ]]; then echo -n '0'; else echo -n '1'; fi
|
||
}
|
||
|
||
# start counter on git
|
||
function _git_dirty_count() {
|
||
local _dirty_status
|
||
local _git_status
|
||
_dirty_status="$(_prompt_parse_git_dirty)"
|
||
_git_status="$(git status --porcelain 2> /dev/null)"
|
||
if [[ "$_dirty_status" == 0 ]]; then
|
||
local change_count
|
||
change_count="$(echo "$_git_status" | wc -l | tr -d '[:space:]')"
|
||
case $change_count in
|
||
1) printf '%b\u2022%s' "${BOLD}${GREY}" "$change_count";;
|
||
2) printf '%b\u2236%s' "${BOLD}${GREY}" "$change_count";;
|
||
3) printf '%b\u2026%s' "${BOLD}${GREY}" "$change_count";;
|
||
*) printf '%b\u00BB%s' "${BOLD}${GREY}" "$change_count";;
|
||
esac
|
||
fi
|
||
}
|
||
|
||
___upstream="$(git rev-parse --symbolic-full-name --abbrev-ref "@{upstream}" 2> /dev/null)"
|
||
|
||
function _git_behind_count() {
|
||
local __behind_count
|
||
if [[ ! -z $___upstream ]]; then
|
||
__behind_count="$(git rev-list --left-right --count "$___upstream"...HEAD | cut -f1 2> /dev/null)"
|
||
case $__behind_count in
|
||
0) echo -n '';;
|
||
*) echo -n "$__behind_count";;
|
||
esac
|
||
fi
|
||
}
|
||
|
||
function _git_ahead_count() {
|
||
local __ahead_count
|
||
if [[ ! -z $___upstream ]]; then
|
||
__ahead_count="$(git rev-list --left-right --count "$___upstream"...HEAD | cut -f2 2> /dev/null)"
|
||
case $__ahead_count in
|
||
0) echo -n '';;
|
||
*) echo -n "$__ahead_count";;
|
||
esac
|
||
fi
|
||
}
|
||
# ends counter on git
|
||
|
||
function _prompt_parse_git_untracked() {
|
||
local untracked
|
||
local evaltask
|
||
untracked="$(git status 2>&1 | tee)"
|
||
grep -E 'Untracked files:' <<<"$untracked" &> /dev/null
|
||
evaltask=$?
|
||
if [ "$evaltask" -eq 0 ]; then echo -n '0'; else echo -n '1'; fi
|
||
}
|
||
|
||
function _prompt_parse_git_newfile() {
|
||
local newfile
|
||
local evaltask
|
||
newfile="$(git status 2>&1 | tee)"
|
||
grep -E 'new file:' <<<"$newfile" &> /dev/null
|
||
evaltask=$?
|
||
if [ "$evaltask" -eq 0 ]; then echo -n '0'; else echo -n '1'; fi
|
||
}
|
||
|
||
function _prompt_parse_git_deleted_file() {
|
||
local deleted_file
|
||
local evaltask
|
||
deleted_file="$(git status 2>&1 | tee)"
|
||
grep -E 'deleted:' <<<"$deleted_file" &> /dev/null
|
||
evaltask=$?
|
||
if [ "$evaltask" -eq 0 ]; then echo -n '0'; else echo -n '1'; fi
|
||
}
|
||
|
||
function _prompt_parse_git_renamed() {
|
||
local renamed
|
||
local evaltask
|
||
renamed="$(git status 2>&1 | tee)"
|
||
grep -E 'renamed:' <<<"$renamed" &> /dev/null
|
||
evaltask=$?
|
||
if [ "$evaltask" -eq 0 ]; then echo -n '0'; else echo -n '1'; fi
|
||
}
|
||
|
||
function _prompt_parse_git_unstage() {
|
||
local unstage
|
||
local evaltask
|
||
unstage="$(git status 2>&1 | tee)"
|
||
grep -E 'not staged' <<<"$unstage" &> /dev/null
|
||
evaltask=$?
|
||
if [ "$evaltask" -eq 0 ]; then echo -n '0'; else echo -n '1'; fi
|
||
}
|
||
|
||
function _prompt_parse_git_stage() {
|
||
local stage
|
||
local evaltask
|
||
stage="$(git status -s 2>&1 | tee)"
|
||
grep -E 'M' <<<"$stage" &> /dev/null
|
||
evaltask=$?
|
||
if [ "$evaltask" -eq 0 ]; then echo -n '0'; else echo -n '1'; fi
|
||
}
|
||
|
||
function _prompt_is_on_git() {
|
||
git rev-parse 2> /dev/null
|
||
}
|
||
|
||
function _prompt_get_git_status() {
|
||
|
||
_symbols "$@"
|
||
|
||
# Grab the git dirty and git behind
|
||
count_dirty="$(_git_dirty_count)"
|
||
count_behind="$(_git_behind_count)"
|
||
count_ahead="$(_git_ahead_count)"
|
||
dirty_branch="$(_prompt_parse_git_dirty)"
|
||
branch_ahead="$(_prompt_parse_git_ahead)"
|
||
branch_behind="$(_prompt_parse_git_behind)"
|
||
branch_stage="$(_prompt_parse_git_stage)"
|
||
branch_unstage="$(_prompt_parse_git_unstage)"
|
||
branch_untracked="$(_prompt_parse_git_untracked)"
|
||
branch_newfile="$(_prompt_parse_git_newfile)"
|
||
branch_deleted_file="$(_prompt_parse_git_deleted_file)"
|
||
branch_renamed="$(_prompt_parse_git_renamed)"
|
||
|
||
# Iterate through all the cases and if it matches, then printf
|
||
case ${dirty_branch}${branch_ahead}${branch_behind}${branch_stage}${branch_unstage}${branch_newfile}${branch_untracked}${branch_deleted_file}${branch_renamed} in
|
||
111111111) printf '%s' "${__ss}";;
|
||
100111111) printf '%s' "${__ps}${__ahs}$count_ahead${__ps}${__bhs}$count_behind";;
|
||
110111111) printf '%s%s' "${__upulls}" "$count_behind";;
|
||
101111111) printf '%s%s' "${__ahs}" "$count_ahead";;
|
||
010111111) printf '%s%s%s' "${__duplls}" "$count_behind" "$count_dirty";;
|
||
001111111) printf '%s%s%s' "${__duphs}" "$count_ahead" "$count_dirty";;
|
||
000111111) printf '%s%s%s' "${__duus}" "$count_behind-$count_ahead" "$count_dirty";;
|
||
|
||
000111011) printf '%s%s' "${__ps}${__ahs}$count_ahead${__ps}${__bhs}$count_behind${__ps}${__uts}${__ps}" "$count_dirty" ;;
|
||
|
||
010111011) printf '%s%s' "${__ps}${__bhs}$count_behind${__ps}${__dss}${__uts}" "${__ps}$count_dirty";;
|
||
010110111) printf '%s%s' "${__ps}${__bhs}$count_behind${__ps}${__dss}${__nfs}" "${__ps}$count_dirty";;
|
||
010110011) printf '%s%s' "${__ps}${__bhs}$count_behind${__ps}${__dss}${__nfs}${__uts}" "${__ps}$count_dirty";;
|
||
010100001) printf '%s%s' "${__ps}${__bhs}$count_behind${__ps}${__dss}${__nfs}${__usts}${__uts}${__dfs}" "${__ps}$count_dirty";;
|
||
010000001) printf '%s%s' "${__ps}${__bhs}$count_behind${__ps}${__dss}${__nfs}${__stusts}${__uts}${__dfs}" "${__ps}$count_dirty";;
|
||
010010100) printf '%s%s' "${__ps}${__bhs}$count_behind${__ps}${__dss}${__nfs}${__dfs}${__rns}" "${__ps}${__sts}${__ps}$count_dirty";;
|
||
010010000) printf '%s%s' "${__ps}${__bhs}$count_behind${__ps}${__dss}${__nfs}${__dfs}${__rns}${__ps}${__uts}" "${__ps}${__sts}${__ps}$count_dirty";;
|
||
|
||
011001111) printf '%s%s' "${__ps}${__dss}${__stusts}" "$count_dirty";;
|
||
011000111) printf '%s%s' "${__ps}${__dss}${__stusts}${__nfs}" "$count_dirty";;
|
||
011001101) printf '%s%s' "${__ps}${__dss}${__stusts}${__dfs}" "$count_dirty";;
|
||
011001011) printf '%s%s' "${__ps}${__dss}${__stusts}${__uts}" "$count_dirty" ;;
|
||
011001001) printf '%s%s' "${__ps}${__dss}${__stusts}${__uts}${__dfs}" "$count_dirty";;
|
||
011000101) printf '%s%s' "${__ps}${__dss}${__stusts}${__nfs}${__dfs}" "$count_dirty";;
|
||
011000001) printf '%s%s' "${__ps}${__dss}${__stusts}${__nfs}${__uts}${__dfs}" "$count_dirty";;
|
||
011011111) printf '%s%s' "${__ps}${__dss}${__sts}" "$count_dirty";;
|
||
011010111) printf '%s%s' "${__ps}${__dss}${__sts}${__nfs}" "$count_dirty";;
|
||
011010101) printf '%s%s' "${__ps}${__dss}${__sts}${__nfs}${__dfs}" "$count_dirty" ;;
|
||
011010001) printf '%s%s' "${__ps}${__dss}${__sts}${__nfs}${__uts}${__dfs}" "$count_dirty";;
|
||
011011011) printf '%s%s' "${__ps}${__dss}${__sts}${__uts}" "$count_dirty";;
|
||
011011101) printf '%s%s' "${__ps}${__dss}${__sts}${__dfs}" "$count_dirty";;
|
||
011110111) printf '%s%s' "${__ps}${__dss}${__nfs}" "$count_dirty";;
|
||
011110011) printf '%s%s' "${__ps}${__dss}${__nfs}${__uts}" "$count_dirty";;
|
||
011111011) printf '%s%s' "${__ps}${__dss}${__uts}" "$count_dirty";;
|
||
011101001) printf '%s%s' "${__ps}${__dss}${__usts}${__uts}${__dfs}" "$count_dirty";;
|
||
011001111) printf '%s%s' "${__ps}${__dss}${__stusts}" "$count_dirty";;
|
||
011111110) printf '%s%s' "${__ps}${__dss}${__rns}" "$count_dirty";;
|
||
011110110) printf '%s%s' "${__ps}${__dss}${__nfs}${__rns}" "$count_dirty";;
|
||
011110010) printf '%s%s' "${__ps}${__dss}${__nfs}${__uts}${__rns}" "$count_dirty";;
|
||
011010100) printf '%s%s' "${__ps}${__dss}${__sts}${__nfs}${__dfs}${__rns}" "$count_dirty" ;;
|
||
011010000) printf '%s%s' "${__ps}${__dss}${__sts}${__nfs}${__uts}${__dfs}${__rns}" "$count_dirty";;
|
||
011001010) printf '%s%s' "${__ps}${__dss}${__stusts}${__uts}${__rns}" "$count_dirty";;
|
||
011001000) printf '%s%s' "${__ps}${__dss}${__stusts}${__uts}${__dfs}${__rns}" "$count_dirty";;
|
||
011000110) printf '%s%s' "${__ps}${__dss}${__stusts}${__nfs}${__rns}" "$count_dirty";;
|
||
011000010) printf '%s%s' "${__ps}${__dss}${__stusts}${__nfs}${__uts}${__rns}" "$count_dirty";;
|
||
011000000) printf '%s%s' "${__ps}${__dss}${__stusts}${__nfs}${__uts}${__dfs}${__rns}" "$count_dirty";;
|
||
011000100) printf '%s%s' "${__ps}${__dss}${__stusts}${__nfs}${__dfs}${__rns}" "$count_dirty";;
|
||
011010010) printf '%s%s' "${__ps}${__dss}${__sts}${__nfs}${__uts}${__rns}" "$count_dirty";;
|
||
011011010) printf '%s%s' "${__ps}${__dss}${__sts}${__uts}${__rns}" "$count_dirty";;
|
||
011111010) printf '%s%s' "${__ps}${__dss}${__uts}${__rns}" "$count_dirty";;
|
||
|
||
001001111) printf '%s%s' "${__ps}${__duus}${__stusts}" "$count_dirty";;
|
||
001000111) printf '%s%s' "${__ps}${__duus}${__stusts}${__nfs}" "$count_dirty";;
|
||
001001101) printf '%s%s' "${__ps}${__duus}${__stusts}${__dfs}" "$count_dirty";;
|
||
001001011) printf '%s%s' "${__ps}${__duus}${__stusts}${__uts}" "$count_dirty";;
|
||
001001001) printf '%s%s' "${__ps}${__duus}${__stusts}${__uts}${__dfs}" "$count_dirty";;
|
||
001000101) printf '%s%s' "${__ps}${__duus}${__stusts}${__nfs}${__dfs}" "$count_dirty";;
|
||
001000001) printf '%s%s' "${__ps}${__duus}${__stusts}${__nfs}${__uts}${__dfs}" "$count_dirty";;
|
||
001011111) printf '%s%s' "${__ps}${__duus}${__sts}" "$count_dirty";;
|
||
001010111) printf '%s%s' "${__ps}${__duus}${__sts}${__nfs}" "$count_dirty" ;;
|
||
001010101) printf '%s%s' "${__ps}${__duus}${__sts}${__nfs}${__dfs}" "$count_dirty" ;;
|
||
001010001) printf '%s%s' "${__ps}${__duus}${__sts}${__nfs}${__uts}${__dfs}" "$count_dirty";;
|
||
001011011) printf '%s%s' "${__ps}${__duus}${__sts}${__uts}" "$count_dirty";;
|
||
001011101) printf '%s%s' "${__ps}${__duus}${__sts}${__dfs}" "$count_dirty";;
|
||
001110111) printf '%s%s' "${__ps}${__duus}${__nfs}" "$count_dirty";;
|
||
001110011) printf '%s%s' "${__ps}${__duus}${__nfs}${__uts}" "$count_dirty";;
|
||
001111011) printf '%s%s' "${__ps}${__duus}${__uts}" "$count_dirty";;
|
||
001101001) printf '%s%s' "${__ps}${__duus}${__usts}${__uts}${__dfs}" "$count_dirty";;
|
||
001101101) printf '%s%s' "${__ps}${__duus}${__usts}${__dfs}" "$count_dirty";;
|
||
111001111) printf '%s%s' "${__ps}${__duus}${__stusts}" "$count_dirty";;
|
||
001111110) printf '%s%s' "${__ps}${__duus}${__rns}" "$count_dirty";;
|
||
001110110) printf '%s%s' "${__ps}${__duus}${__nfs}${__rns}" "$count_dirty";;
|
||
001110010) printf '%s%s' "${__ps}${__duus}${__nfs}${__uts}${__rns}" "$count_dirty";;
|
||
001010100) printf '%s%s' "${__ps}${__duus}${__sts}${__nfs}${__dfs}${__rns}" "$count_dirty" ;;
|
||
001010000) printf '%s%s' "${__ps}${__duus}${__sts}${__nfs}${__uts}${__dfs}${__rns}" "$count_dirty";;
|
||
001001010) printf '%s%s' "${__ps}${__duus}${__stusts}${__uts}${__rns}" "$count_dirty";;
|
||
001001000) printf '%s%s' "${__ps}${__duus}${__stusts}${__uts}${__dfs}${__rns}" "$count_dirty";;
|
||
001000110) printf '%s%s' "${__ps}${__duus}${__stusts}${__nfs}${__rns}" "$count_dirty";;
|
||
001000010) printf '%s%s' "${__ps}${__duus}${__stusts}${__nfs}${__uts}${__rns}" "$count_dirty";;
|
||
001000000) printf '%s%s' "${__ps}${__duus}${__stusts}${__nfs}${__uts}${__dfs}${__rns}" "$count_dirty";;
|
||
001000100) printf '%s%s' "${__ps}${__duus}${__stusts}${__nfs}${__dfs}${__rns}" "$count_dirty";;
|
||
001010010) printf '%s%s' "${__ps}${__duus}${__sts}${__nfs}${__uts}${__rns}" "$count_dirty";;
|
||
001011010) printf '%s%s' "${__ps}${__duus}${__sts}${__uts}${__rns}" "$count_dirty";;
|
||
001111010) printf '%s%s' "${__ps}${__duus}${__uts}${__rns}" "$count_dirty";;
|
||
*) echo -n "${__uts}" ;;
|
||
esac
|
||
|
||
#
|
||
# dirty + unpushed = du stage + unstage = <M>
|
||
# ∗ ↑ ↓ →M ←M + ? D ⎇
|
||
# echo "${dirty_branch}${branch_ahead}${branch_behind}${branch_stage}${branch_unstage}${branch_newfile}${branch_untracked}${branch_deleted_file}${branch_renamed}"
|
||
# 0 1 0 1 1 1 0 1 1
|
||
}
|
||
|
||
_prompt_get_git_info() {
|
||
# Import colors
|
||
_colors_bash "$@"
|
||
|
||
# Grab the branch
|
||
branch="$(_get_git_branch)"
|
||
|
||
# If there are any branches
|
||
if [[ -n $branch ]]; then
|
||
# Printf the branch
|
||
output="$branch"
|
||
|
||
# Add on the git status
|
||
output="$output$(_prompt_get_git_status "$@")"
|
||
|
||
# Printf our output
|
||
printf '%b%s%b' "${BOLD}${LEMON}" "git:($output" "${BOLD}${LEMON})"
|
||
fi
|
||
}
|
||
|
||
__prompt_git() {
|
||
if _prompt_is_on_git &> /dev/null; then
|
||
echo -n "${BOLD}${WHITE} on $RESET" && \
|
||
echo -n "$(_prompt_get_git_info "$@")" && \
|
||
echo -n "${BOLD}${RED}$(_get_git_progress)" && \
|
||
echo -n "$RESET"
|
||
fi
|
||
}
|