#!/usr/bin/zsh function main() { 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 local branch="$REPLY" git_grab_remote_branch local remote="$REPLY" [[ ! -z "$remote" ]] \ && git_local_remote_diffs "$branch" "$remote" \ && local commit_diffs="$REPLY" git_determine_color $modified $staged $deleted $untracked local color="$REPLY" (( modified > 0 )) \ && modified="!$modified " (( staged > 0 )) \ && staged="+$staged " (( deleted > 0 )) \ && deleted="-$deleted " (( untracked > 0 )) \ && untracked="?$untracked" local output="$color" output+=" $branch " output+="$commit_diffs" output+="$modified" output+="$staged" output+="$deleted" output+="$untracked" output+=$'\e[0m' sed 's/[ ]+$//' <<<"$output" # remove trailing whitespace unset REPLY } ### # Check if we're in a git repository # Arguments: none # Returns: 0 if in a git repo, 1 otherwise ### function is_in_git_repository() { git rev-parse --git-dir &>/dev/null || return 1 } ### # Return current branch we're on # Arguments: none ### function git_grab_current_branch() { typeset -g REPLY="$(git branch --show-current)" } ### # Return remote branch that the local one is tracking # Arguemnts: none ### function git_grab_remote_branch() { local symbolic_ref="$(git symbolic-ref -q HEAD)" typeset -g REPLY="$(git for-each-ref --format='%(upstream:short)' $symbolic_ref)" } ### # Find how many things have changed since last git commit # Arguments: none ### function parse_git_status() { git status --porcelain=v1 | while IFS= read -r status_line; do case "$status_line" in ' M '*) ((modified++)) ;; 'A '*|'M '*) ((staged++)) ;; ' D '*) ((deleted++)) ;; '?? '*) ((untracked++)) ;; 'MM '*) ((staged++)) ((modified++)) ;; esac done typeset -g STATUS=("$modified" "$staged" "$deleted" "$untracked") return 0 } ### # 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() { local local_branch="$1" local remote_branch="$2" 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}') local ahead="" behind="" (( $commits_ahead > 0 )) \ && ahead=" ↑$commits_ahead" (( $commits_behind > 0 )) \ && behind=" ↓$commits_behind " typeset -g REPLY="$ahead $behind" return 0 } ### # If there is anything that changed from the past commit, return yelllow color. # Otherwise, green. # Arguments: list of how many things changed ### function git_determine_color() { local green=$'\e[93m' local yellow=$'\e[92m' for i in "$@"; do if (( $i > 0 )); then typeset -g REPLY="$green" return 0 fi done typeset -g REPLY="$yellow" return 0 } main