mirror of
https://github.com/ohmyzsh/ohmyzsh.git
synced 2025-12-26 02:12:33 +01:00
new vcs prompt plugin
This plugin is designed to provide a uniform prompt status that
accommodates multiple vcs systems. The intent is to have reasonable
defaults for displaying each element of work tree status but also the
flexbility to make modifications without copying and pasting entire
functions into your own theme (or reimplementing a function just to
change one aspect of its behavior).
FEATURE HIGHLIGHTS
- uniform PROMPT interface for multiple vcs types
one addition to your PROMPT gets you all
- supports git, hg, svn
- indicators and (optional) counts for the primary dirty file types of
each supported vcs (e.g. `1N 3A 2U` for 1 new, 3 added, 2 untracked)
- inspired by the `git_status_prompt` function from lib/git.zsh
- rewritten as inline awk script to:
- optionally include counts for each dirty type
- provide more readable code
- move towards more modular code to support more vcs systems
- indicators for ahead-by and behind-by with counts; commits from
upstream not yet merged or local commits not yet pushed,respectively
(git-only for now)
- dirt age indicator to show how long it has been since a
significant action in the work tree (i.e. commit, file edited)
- reworked `git_time_since_commit` function found in multiple themes
- now centralized in a plugin
- and generalized to support hg and svn
- highly configurable, with many hooks for adding style information to
each element
- can rearrange order of elements
- uses an associative array, VCS_PLUGIN, for (almost) all of its
configuration settings
- incorporates functionally equivalent replacments of all functions from
from the git, svn, and hg oh-my-zsh plugins (but not any of their
aliases)
- handles ignored subdirectories of git work trees
This commit is contained in:
parent
762b55bb2b
commit
4244a79148
1 changed files with 623 additions and 0 deletions
623
plugins/vcs/vcs.plugin.zsh
Normal file
623
plugins/vcs/vcs.plugin.zsh
Normal file
|
|
@ -0,0 +1,623 @@
|
|||
# =====[ NAME ]=================================================================
|
||||
#
|
||||
# VCS Plugin
|
||||
|
||||
# =====[ DESCRIPTION ]==========================================================
|
||||
#
|
||||
# Uniform prompt status for work trees originating from multiple vcs systems.
|
||||
#
|
||||
# =====[ FUNCTIONS ]============================================================
|
||||
#
|
||||
# DISPLAY
|
||||
# $(vcs_status_prompt) : top-level status indicator
|
||||
#
|
||||
# $(vcs_dirt_status) : indicator of and count for each type of dirty file
|
||||
# : simple form can indicate just clean or dirty
|
||||
# $(vcs_dirt_age) : time since last significant action on the work tree
|
||||
# : helpful for determining staleness of a tree
|
||||
# $(vcs_rev_short) : abbreviated form of current revision
|
||||
# $(vcs_rev_long) : more verbose current revision information
|
||||
#
|
||||
# ------------------------------------------
|
||||
# FEATURE SUPPORT BY VCS
|
||||
# ------------------------------------------
|
||||
#
|
||||
# feature | git | hg | svn | bzr |
|
||||
# ----------------------------------------------
|
||||
# vcs_status_prompt | O | O | O | X |
|
||||
# vcs_dirt_status | O | O | O | X |
|
||||
# vcs_dirt_age | O | O | O | X |
|
||||
# vcs_rev_short | O | O | O | X |
|
||||
# vcs_rev_long | O | O | O | X |
|
||||
#
|
||||
# O = implemented
|
||||
# X = unimplemented
|
||||
|
||||
# DETECTION
|
||||
# $(vcs_is_git) : true if cwd is in a git work tree
|
||||
# : (but returns false if in an ignored subdirectory)
|
||||
# $(vcs_is_hg) : true if cwd is in a mercurial work tree
|
||||
# $(vcs_is_svn) : true if cwd is in a subversion work tree
|
||||
#
|
||||
# CUSTOMIZATION
|
||||
# see default implementations below for examples
|
||||
# implement your own function with these names to override default behavior
|
||||
#
|
||||
# _vcs_prompt_git
|
||||
# _vcs_prompt_hg
|
||||
# _vcs_prompt_svn
|
||||
#
|
||||
# _vcs_rev_short_git
|
||||
# _vcs_rev_short_hg
|
||||
# _vcs_rev_short_svn
|
||||
#
|
||||
# _vcs_rev_long_git
|
||||
# _vcs_rev_long_hg
|
||||
# _vcs_rev_long_svn
|
||||
|
||||
# =====[ CONFIGURABLE SETTINGS (and default values) ]===========================
|
||||
# Associative array for plugin settings
|
||||
typeset -gA VCS_PLUGIN
|
||||
|
||||
# $VCS_PLUGIN[separator] : [string] separates elements in the vcs prompt
|
||||
VCS_PLUGIN[separator]=" | "
|
||||
|
||||
# $VCS_PLUGIN[prompt_prefix] : [string] precedes contents of the vcs prompt
|
||||
VCS_PLUGIN[prompt_prefix]="("
|
||||
# $$VCS_PLUGIN[prompt_suffix] : [string] proceeds contents of the vcs prompt
|
||||
VCS_PLUGIN[prompt_suffix]=")"
|
||||
|
||||
# $VCS_PLUGIN[dirt_status_verbosity] : [string] show symbols each type of dirty file
|
||||
# : or a single dirty or clean symbol
|
||||
VCS_PLUGIN[dirt_status_verbosity]="full"
|
||||
#VCS_PLUGIN[dirt_status_verbosity]="simple"
|
||||
|
||||
# $VCS_PLUGIN[is_clean_symbol] : [string] show when the work tree has no dirty files
|
||||
VCS_PLUGIN[is_clean_symbol]="%{$fg[green]%}"
|
||||
VCS_PLUGIN[is_clean_symbol]+="✔"
|
||||
VCS_PLUGIN[is_clean_symbol]+="%{$reset_color%}"
|
||||
|
||||
# $VCS_PLUGIN[is_dirty_symbol] : [string] show when the work tree has dirty files
|
||||
VCS_PLUGIN[is_dirty_symbol]="%{$fg[red]%}"
|
||||
VCS_PLUGIN[is_dirty_symbol]+="✖"
|
||||
VCS_PLUGIN[is_dirty_symbol]+="%{$reset_color%}"
|
||||
|
||||
#VCS_PLUGIN[untracked_is_dirty] : [flag] "true" to consider untracked files as dirty
|
||||
VCS_PLUGIN[untracked_is_dirty]=
|
||||
#VCS_PLUGIN[untracked_is_dirty]=true
|
||||
|
||||
# $VCS_PLUGIN[untracked_symbol] : [string] show when there is at least one untracked file
|
||||
VCS_PLUGIN[untracked_symbol]="%{$fg_bold[white]%}"
|
||||
VCS_PLUGIN[untracked_symbol]+="✭"
|
||||
VCS_PLUGIN[untracked_symbol]+="%{$reset_color%}"
|
||||
|
||||
# $VCS_PLUGIN[added_symbol] : [string] show when there is at least one added file
|
||||
VCS_PLUGIN[added_symbol]="%{$fg[green]%}"
|
||||
VCS_PLUGIN[added_symbol]+="✚"
|
||||
VCS_PLUGIN[added_symbol]+="%{$reset_color%}"
|
||||
|
||||
# $VCS_PLUGIN[modified_symbol] : [string] show when there is at least one modified file
|
||||
VCS_PLUGIN[modified_symbol]="%{$fg_bold[green]%}"
|
||||
VCS_PLUGIN[modified_symbol]+="✹"
|
||||
VCS_PLUGIN[modified_symbol]+="%{$reset_color%}"
|
||||
|
||||
# $VCS_PLUGIN[renamed_symbol] : [string] show when there is at least one renamed file
|
||||
VCS_PLUGIN[renamed_symbol]="%{$fg[yellow]%}"
|
||||
VCS_PLUGIN[renamed_symbol]+="➜"
|
||||
VCS_PLUGIN[renamed_symbol]+="%{$reset_color%}"
|
||||
|
||||
# $VCS_PLUGIN[deleted_symbol] : [string] show when there is at least one deleted file
|
||||
VCS_PLUGIN[deleted_symbol]="%{$fg[red]%}"
|
||||
VCS_PLUGIN[deleted_symbol]+="✖"
|
||||
VCS_PLUGIN[deleted_symbol]+="%{$reset_color%}"
|
||||
|
||||
# $VCS_PLUGIN[unmerged_symbol] : [string] show when there is at least one unmerged or conflicted file
|
||||
VCS_PLUGIN[unmerged_symbol]="%{$fg[blue]%}"
|
||||
VCS_PLUGIN[unmerged_symbol]+="═"
|
||||
VCS_PLUGIN[unmerged_symbol]+="%{$reset_color%}"
|
||||
|
||||
# $VCS_PLUGIN[copied_symbol] : [string] show when there is at least one copied file
|
||||
VCS_PLUGIN[copied_symbol]="%{fg_bold[blue]%}"
|
||||
VCS_PLUGIN[copied_symbol]+="ⓒ"
|
||||
VCS_PLUGIN[copied_symbol]+="%{$reset_color%}"
|
||||
|
||||
# $VCS_PLUGIN[include_dirty_counts] : [flag] "true" to include counts preceding status symbols
|
||||
VCS_PLUGIN[include_dirty_counts]=true
|
||||
#VCS_PLUGIN[include_dirty_counts]=
|
||||
|
||||
# $VCS_PLUGIN[git_vcs_symbol] : [string] show when the cwd is in a git work tree
|
||||
VCS_PLUGIN[git_vcs_symbol]="%F{154}"
|
||||
VCS_PLUGIN[git_vcs_symbol]+="±"
|
||||
VCS_PLUGIN[git_vcs_symbol]+="%f"
|
||||
|
||||
# $VCS_PLUGIN[hg_vcs_symbol] : [string] show when the cwd is in an hg work tree
|
||||
VCS_PLUGIN[hg_vcs_symbol]="%{$fg_bold[red]%}"
|
||||
VCS_PLUGIN[hg_vcs_symbol]+="☿"
|
||||
VCS_PLUGIN[hg_vcs_symbol]+="%{$reset_color%} "
|
||||
#
|
||||
# $VCS_PLUGIN[svn_vcs_symbol] : [string] show when the cwd is in an svn work tree
|
||||
VCS_PLUGIN[svn_vcs_symbol]="Ⓢ "
|
||||
#VCS_PLUGIN[svn_vcs_symbol]="⚡ "
|
||||
|
||||
# $VCS_PLUGIN[no_vcs_symbol] : [string] show when cwd is not associated with a vcs
|
||||
VCS_PLUGIN[no_vcs_symbol]="◯ "
|
||||
|
||||
# $VCS_PLUGIN[branch_prefix]
|
||||
VCS_PLUGIN[branch_prefix]="%{$fg[white]%}"
|
||||
# $VCS_PLUGIN[branch_suffix]
|
||||
VCS_PLUGIN[branch_suffix]="%{$reset_color%}"
|
||||
|
||||
# $VCS_PLUGIN[rev_prefix]
|
||||
VCS_PLUGIN[rev_prefix]=
|
||||
# $VCS_PLUGIN[rev_suffix]
|
||||
VCS_PLUGIN[rev_suffix]=
|
||||
|
||||
# $VCS_PLUGIN[ahead_by_prefix]
|
||||
VCS_PLUGIN[ahead_by_prefix]=
|
||||
# $VCS_PLUGIN[ahead_by_symbol] : [string] shown when there are local commits not yet pushed upstream
|
||||
VCS_PLUGIN[ahead_by_symbol]="%{$fg_bold[blue]%}"
|
||||
VCS_PLUGIN[ahead_by_symbol]+="⬆"
|
||||
VCS_PLUGIN[ahead_by_symbol]+="%{$reset_color%}"
|
||||
# $VCS_PLUGIN[ahead_by_suffix]
|
||||
VCS_PLUGIN[ahead_by_suffix]=
|
||||
|
||||
# $VCS_PLUGIN[behind_by_prefix]
|
||||
VCS_PLUGIN[behind_by_prefix]=
|
||||
# $VCS_PLUGIN[behind_by_symbol] : [string] shown when there are commits not yet merged in from upstream
|
||||
VCS_PLUGIN[behind_by_symbol]="%{$fg_bold[red]%}"
|
||||
VCS_PLUGIN[behind_by_symbol]+="⬇"
|
||||
VCS_PLUGIN[behind_by_symbol]+="%{$reset_color%}"
|
||||
#VCS_PLUGIN[behind_by_suffix
|
||||
VCS_PLUGIN[behind_by_suffix]=
|
||||
|
||||
# $VCS_PLUGIN[ahead_behind_prefix] : for combined ahead and behind indicators
|
||||
VCS_PLUGIN[ahead_behind_prefix]=
|
||||
# $VCS_PLUGIN[ahead_behind_separator] : [string] appears between ahead and behind status indicators if both are present
|
||||
VCS_PLUGIN[ahead_behind_separator]=" "
|
||||
# $VCS_PLUGIN[ahead_behind_suffix]
|
||||
VCS_PLUGIN[ahead_behind_suffix]=$VCS_PLUGIN[separator]
|
||||
|
||||
# $VCS_PLUGIN[long_age_threshold] : [number] time in minutes a work tree can be stale before its age is considered long
|
||||
VCS_PLUGIN[long_age_threshold]="360"
|
||||
# $VCS_PLUGIN[medium_age_threshold] : [number] time in minutes a work tree can be stale before its age is considered medium
|
||||
# : anything less stale will be considered short
|
||||
# : a directory is not considered stale (is neutral) if it is not dirty
|
||||
VCS_PLUGIN[medium_age_threshold]="120"
|
||||
# $VCS_PLUGIN[time_since_commit_neutral] : [color] used for neutral indicator
|
||||
VCS_PLUGIN[time_since_commit_neutral]="%{$fg[white]%}"
|
||||
# $VCS_PLUGIN[time_since_commit_short] : [color] used for short age
|
||||
VCS_PLUGIN[time_since_commit_short]="%{$fg[green]%}"
|
||||
# $VCS_PLUGIN[time_short_commit_medium] : [color] used for medium age
|
||||
VCS_PLUGIN[time_short_commit_medium]="%{$fg[yellow]%}"
|
||||
# $VCS_PLUGIN[time_since_commit_long] : [color] used for long age
|
||||
VCS_PLUGIN[time_since_commit_long]="%{$fg[red]%}"
|
||||
# $VCS_PLUGIN[time_verbose] : [flag] "true" to see a more verbose age indicator
|
||||
VCS_PLUGIN[time_verbose]=
|
||||
#VCS_PLUGIN[time_verbose]=true
|
||||
|
||||
# VCS_DETECTION_ORDER : [hash] order in which cwd will be inspected for vcs type
|
||||
VCS_DETECTION_ORDER=(svn git hg)
|
||||
|
||||
# =====[ IMPLEMENTATION ]=======================================================
|
||||
|
||||
# =====[ detection ]============================================================
|
||||
function vcs_is_git() {
|
||||
# this invocation handles ignored subdirectories of git work trees
|
||||
[[ -n $(git ls-files --exclude-standard 2> /dev/null) ]]
|
||||
}
|
||||
|
||||
function vcs_is_hg() {
|
||||
hg root >/dev/null 2>/dev/null && true
|
||||
}
|
||||
|
||||
function vcs_is_svn() {
|
||||
[[ -d .svn ]] && true
|
||||
}
|
||||
|
||||
# =====[ display ]==============================================================
|
||||
|
||||
function vcs_status_prompt() {
|
||||
for vcs in $VCS_DETECTION_ORDER; do
|
||||
vcs_is_${vcs} && _vcs_prompt ${vcs} && return
|
||||
done
|
||||
echo "$VCS_PLUGIN[no_vcs_symbol]"
|
||||
}
|
||||
|
||||
function _vcs_prompt() {
|
||||
local vcs=$1
|
||||
local result=''
|
||||
result+="$VCS_PLUGIN[prompt_prefix]"
|
||||
result+=$(_vcs_prompt_${vcs})
|
||||
result+="$VCS_PLUGIN[prompt_suffix]"
|
||||
echo $result
|
||||
}
|
||||
|
||||
# Default status prompts; override by defining your own functions of the same
|
||||
# name in your theme but still use $(vcs_status_prompt) in your PROMPT.
|
||||
|
||||
function _vcs_prompt_git() {
|
||||
local result=''
|
||||
result+="$(vcs_dirt_age)"
|
||||
result+="$VCS_PLUGIN[separator]"
|
||||
result+="$(vcs_ahead_behind)"
|
||||
result+="$(vcs_dirt_status) "
|
||||
result+="$VCS_PLUGIN[git_vcs_symbol]"
|
||||
result+="$(vcs_branch)"
|
||||
echo $result
|
||||
}
|
||||
|
||||
function _vcs_prompt_svn() {
|
||||
local result=''
|
||||
result+="$(vcs_dirt_age)"
|
||||
result+="$VCS_PLUGIN[separator]"
|
||||
result+="$(vcs_dirt_status) "
|
||||
result+="$VCS_PLUGIN[svn_vcs_symbol]"
|
||||
result+="${$(vcs_branch)#trunk}" # show nothing if "trunk"
|
||||
result+="$(vcs_rev_long)"
|
||||
echo $result
|
||||
}
|
||||
|
||||
function _vcs_prompt_hg() {
|
||||
local result=''
|
||||
result+="$(vcs_dirt_age)"
|
||||
result+="$VCS_PLUGIN[separator]"
|
||||
result+="$(vcs_dirt_status) "
|
||||
result+="$VCS_PLUGIN[hg_vcs_symbol]"
|
||||
result+="$(vcs_branch)"
|
||||
result+="$(vcs_rev_long)"
|
||||
echo $result
|
||||
}
|
||||
|
||||
# =====[ branch information ]===================================================
|
||||
|
||||
function vcs_branch() {
|
||||
local length=$1
|
||||
local value=''
|
||||
for vcs in $VCS_DETECTION_ORDER; do
|
||||
vcs_is_${vcs} && value+=$(_vcs_branch_${vcs}) && break
|
||||
done
|
||||
[[ -z $value ]] && return
|
||||
local result=''
|
||||
result+="$VCS_PLUGIN[branch_prefix]"
|
||||
result+=$value
|
||||
result+="$VCS_PLUGIN[branch_suffix]"
|
||||
echo $result
|
||||
}
|
||||
|
||||
function _vcs_branch_git() {
|
||||
echo ${$(git symbolic-ref HEAD 2> /dev/null)#refs/heads/} || return
|
||||
}
|
||||
|
||||
function _vcs_branch_hg() {
|
||||
echo $(hg branch) || return
|
||||
}
|
||||
|
||||
function _vcs_branch_svn() {
|
||||
# Strip out '/trunk/'
|
||||
echo $(svn info | awk '/Root/{root=$3 "\/(trunk/)?"};/URL/{url=$2};END{gsub(root,"",url);print url}')
|
||||
}
|
||||
|
||||
# =====[ current revision ]=====================================================
|
||||
|
||||
function vcs_rev_short() { _vcs_rev "short"; }
|
||||
|
||||
function vcs_rev_long() { _vcs_rev "long"; }
|
||||
|
||||
function _vcs_rev() {
|
||||
local length=$1
|
||||
local value=''
|
||||
for vcs in $VCS_DETECTION_ORDER; do
|
||||
vcs_is_${vcs} && value+=$(_vcs_rev_${length}_${vcs}) && break
|
||||
done
|
||||
[[ -z $value ]] && return
|
||||
local result=''
|
||||
result+="$VCS_PLUGIN[rev_prefix]"
|
||||
result+=$value
|
||||
result+="$VCS_PLUGIN[rev_suffix]"
|
||||
echo $result
|
||||
}
|
||||
|
||||
function _vcs_rev_short_git() { echo $(git rev-parse --short HEAD 2> /dev/null); }
|
||||
|
||||
function _vcs_rev_short_hg() { echo $(hg log -l 1 | awk '/changeset/{split($2,revs,":")};END{print revs[1]}'); }
|
||||
|
||||
function _vcs_rev_short_svn() { echo $(svn info | awk '/Revision/{print $2}'); }
|
||||
|
||||
function _vcs_rev_long_git() { echo $(git rev-parse HEAD 2> /dev/null); }
|
||||
|
||||
function _vcs_rev_long_hg() { echo $(hg log -l 1 | awk '/changeset/{print $2}'); }
|
||||
|
||||
function _vcs_rev_long_svn() { echo "r"$(_vcs_rev_short_svn); }
|
||||
|
||||
function vcs_ahead_behind() {
|
||||
local ahead_by="$(vcs_ahead_by)"
|
||||
local behind_by="$(vcs_behind_by)"
|
||||
[[ -z "${ahead_by}${behind_by}" ]] && return
|
||||
local result=''
|
||||
result+="$VCS_PLUGIN[ahead_behind_prefix]"
|
||||
result+=$ahead_by
|
||||
[[ -n $ahead_by && -n $behind_by ]] && result+="$VCS_PLUGIN[ahead_behind_separator]"
|
||||
result+=$behind_by
|
||||
result+="$VCS_PLUGIN[ahead_behind_suffix]"
|
||||
echo $result
|
||||
}
|
||||
|
||||
function vcs_ahead_by() {
|
||||
local value=''
|
||||
for vcs in $VCS_DETECTION_ORDER; do
|
||||
vcs_is_${vcs} && value+="$(_vcs_ahead_by_${vcs})" && break
|
||||
done
|
||||
[[ -z $value ]] && return
|
||||
local result=''
|
||||
result+="$VCS_PLUGIN[ahead_by_prefix]"
|
||||
result+=$value
|
||||
result+="$VCS_PLUGIN[ahead_by_symbol]"
|
||||
result+="$VCS_PLUGIN[ahead_by_suffix]"
|
||||
echo $result
|
||||
}
|
||||
|
||||
function _vcs_ahead_by_git() { git status --porcelain --branch --short | awk -F'[' '/ahead/{sub(/ahead /,"",$2);sub(/[],].*/,"",$2); print $2}'; }
|
||||
|
||||
function _vcs_ahead_by_svn() { return } # FIXME: unimplemented
|
||||
|
||||
function _vcs_ahead_by_hg() { return } # FIXME: unimplemented
|
||||
|
||||
function vcs_behind_by() {
|
||||
local value=''
|
||||
for vcs in $VCS_DETECTION_ORDER; do
|
||||
vcs_is_${vcs} && value+="$(_vcs_behind_by_${vcs})" && break
|
||||
done
|
||||
[[ -z $value ]] && return
|
||||
local result=''
|
||||
result+="$VCS_PLUGIN[behind_by_prefix]"
|
||||
result+=$value
|
||||
result+="$VCS_PLUGIN[behind_by_symbol]"
|
||||
result+="$VCS_PLUGIN[behind_by_suffix]"
|
||||
echo $result
|
||||
}
|
||||
|
||||
function _vcs_behind_by_git() { git status --porcelain --branch --short | awk -F'[' '/behind/{sub(/.*behind /,"",$2);sub(/]/,"",$2)};END{print $2}'; }
|
||||
|
||||
function _vcs_behind_by_svn() { return } # FIXME: unimplemented
|
||||
|
||||
function _vcs_behind_by_hg() { return } # FIXME: unimplemented
|
||||
|
||||
# =====[ dirt status ]==========================================================
|
||||
# "simple": Show a clean or dirty status indicator.
|
||||
# "full": Show the count of files for each type of non-clean status type next to an
|
||||
# indicator of that type. e.g `6✭ 1✚ 4✹` for 6 untracked, 1 new, and 4 modified
|
||||
# files.
|
||||
|
||||
function vcs_dirt_status() {
|
||||
for vcs in $VCS_DETECTION_ORDER; do
|
||||
vcs_is_${vcs} && _vcs_dirt_status_${VCS_PLUGIN[dirt_status_verbosity]} ${vcs} && return
|
||||
done
|
||||
}
|
||||
|
||||
function _vcs_dirt_status_simple() {
|
||||
local vcs=$1
|
||||
if _vcs_is_clean_${vcs}; then
|
||||
echo "$VCS_PLUGIN[is_clean_symbol]"
|
||||
else
|
||||
echo "$VCS_PLUGIN[is_dirty_symbol]"
|
||||
fi
|
||||
}
|
||||
|
||||
function _vcs_is_clean_git() {
|
||||
local untracked=''
|
||||
[[ -z $VCS_PLUGIN[untracked_is_dirty] ]] && untracked+="--untracked=no"
|
||||
[[ -z $(git status --short --porcelain $untracked 2> /dev/null) ]] && true
|
||||
}
|
||||
|
||||
function _vcs_is_clean_svn() {
|
||||
local untracked=''
|
||||
[[ -z $VCS_PLUGIN[untracked_is_dirty] ]] && untracked+="-q"
|
||||
[[ -z $(svn status $untracked 2> /dev/null) ]] && true
|
||||
}
|
||||
|
||||
|
||||
function _vcs_is_clean_hg() {
|
||||
local untracked=''
|
||||
[[ -z $VCS_PLUGIN[untracked_is_dirty] ]] && untracked+="-q"
|
||||
[[ -z $(hg status $untracked 2> /dev/null) ]] && true
|
||||
}
|
||||
|
||||
function _vcs_dirt_status_full() {
|
||||
local vcs=$1
|
||||
echo $(_vcs_dirt_status_${vcs})
|
||||
}
|
||||
|
||||
function _vcs_dirt_status_git() {
|
||||
git status --porcelain 2> /dev/null | awk "
|
||||
|
||||
/^\?\? / { untracked++ ; total++ };
|
||||
/^[AM] / { added++ ; total++ };
|
||||
/^[A ][MT] / { modified++ ; total++ };
|
||||
/^R / { renamed++ ; total++ };
|
||||
/^[A ]D / { deleted++ ; total++ };
|
||||
/^UU / { unmerged++ ; total++ };
|
||||
/^C / { copied++ ; total++ };
|
||||
|
||||
END {
|
||||
if (total+0 == 0) { printf(\"%s\", \"$VCS_PLUGIN[is_clean_symbol]\"); exit; }
|
||||
|
||||
count[\"untracked\"] = untracked+0 ; symbol[\"untracked\"] = \"$VCS_PLUGIN[untracked_symbol]\";
|
||||
count[\"added\"] = added+0 ; symbol[\"added\"] = \"$VCS_PLUGIN[added_symbol]\" ;
|
||||
count[\"modified\"] = modified+0 ; symbol[\"modified\"] = \"$VCS_PLUGIN[modified_symbol]\" ;
|
||||
count[\"renamed\"] = renamed+0 ; symbol[\"renamed\"] = \"$VCS_PLUGIN[renamed_symbol]\" ;
|
||||
count[\"deleted\"] = deleted+0 ; symbol[\"deleted\"] = \"$VCS_PLUGIN[deleted_symbol]\" ;
|
||||
count[\"unmerged\"] = unmerged+0 ; symbol[\"unmerged\"] = \"$VCS_PLUGIN[unmerged_symbol]\" ;
|
||||
count[\"copied\"] = copied+0 ; symbol[\"copied\"] = \"$VCS_PLUGIN[copied_symbol]\" ;
|
||||
|
||||
for (i in count) {
|
||||
if (count[i]+0 != 0) {
|
||||
if (\"${VCS_PLUGIN[include_dirty_counts]}\" == \"\") {
|
||||
printf(\"%s\", symbol[i]);
|
||||
} else {
|
||||
printf(\"%s%s \", count[i], symbol[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
" | sed -e 's/ $//' &
|
||||
}
|
||||
|
||||
function _vcs_dirt_status_hg() {
|
||||
hg status 2> /dev/null | awk "
|
||||
|
||||
/^\? / { untracked++ ; total++ };
|
||||
/^A / { added++ ; total++ };
|
||||
/^M / { modified++ ; total++ };
|
||||
/^! / { renamed++ ; total++ };
|
||||
/^R / { deleted++ ; total++ };
|
||||
/^_ / { unmerged++ ; total++ };
|
||||
/^_ / { copied++ ; total++ };
|
||||
|
||||
END {
|
||||
if (total+0 == 0) { printf(\"%s\", \"$VCS_PLUGIN[is_clean_symbol]\"); exit; }
|
||||
|
||||
count[\"untracked\"] = untracked+0 ; symbol[\"untracked\"] = \"$VCS_PLUGIN[untracked_symbol]\";
|
||||
count[\"added\"] = added+0 ; symbol[\"added\"] = \"$VCS_PLUGIN[added_symbol]\" ;
|
||||
count[\"modified\"] = modified+0 ; symbol[\"modified\"] = \"$VCS_PLUGIN[modified_symbol]\" ;
|
||||
count[\"renamed\"] = renamed+0 ; symbol[\"renamed\"] = \"$VCS_PLUGIN[renamed_symbol]\" ;
|
||||
count[\"deleted\"] = deleted+0 ; symbol[\"deleted\"] = \"$VCS_PLUGIN[deleted_symbol]\" ;
|
||||
count[\"unmerged\"] = unmerged+0 ; symbol[\"unmerged\"] = \"$VCS_PLUGIN[unmerged_symbol]\" ;
|
||||
count[\"copied\"] = copied+0 ; symbol[\"copied\"] = \"$VCS_PLUGIN[copied_symbol]\" ;
|
||||
|
||||
for (i in count) {
|
||||
if (count[i]+0 != 0) {
|
||||
if (\"$VCS_PLUGIN[include_dirty_counts]\" == \"\") {
|
||||
printf(\"%s\", symbol[i]);
|
||||
} else {
|
||||
printf(\"%s%s \", count[i], symbol[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
" | sed -e 's/ $//' &
|
||||
}
|
||||
|
||||
function _vcs_dirt_status_svn() {
|
||||
svn status 2> /dev/null | awk "
|
||||
|
||||
/^\? / { untracked++ ; total++ };
|
||||
/^A / { added++ ; total++ };
|
||||
/^M / { modified++ ; total++ };
|
||||
/^! / { renamed++ ; total++ };
|
||||
/^D / { deleted++ ; total++ };
|
||||
/^C / { unmerged++ ; total++ };
|
||||
/^R / { copied++ ; total++ };
|
||||
|
||||
END {
|
||||
if (total+0 == 0) { printf(\"%s\", \"$VCS_PLUGIN[is_clean_symbol]\"); exit; }
|
||||
|
||||
count[\"untracked\"] = untracked+0 ; symbol[\"untracked\"] = \"$VCS_PLUGIN[untracked_symbol]\";
|
||||
count[\"added\"] = added+0 ; symbol[\"added\"] = \"$VCS_PLUGIN[added_symbol]\" ;
|
||||
count[\"modified\"] = modified+0 ; symbol[\"modified\"] = \"$VCS_PLUGIN[modified_symbol]\" ;
|
||||
count[\"renamed\"] = renamed+0 ; symbol[\"renamed\"] = \"$VCS_PLUGIN[renamed_symbol]\" ;
|
||||
count[\"deleted\"] = deleted+0 ; symbol[\"deleted\"] = \"$VCS_PLUGIN[deleted_symbol]\" ;
|
||||
count[\"unmerged\"] = unmerged+0 ; symbol[\"unmerged\"] = \"$VCS_PLUGIN[unmerged_symbol]\" ;
|
||||
count[\"copied\"] = copied+0 ; symbol[\"copied\"] = \"$VCS_PLUGIN[copied_symbol]\" ;
|
||||
|
||||
for (i in count) {
|
||||
if (count[i]+0 != 0) {
|
||||
if (\"${VCS_PLUGIN[include_dirty_counts]}\" == \"\") {
|
||||
printf(\"%s\", symbol[i]);
|
||||
} else {
|
||||
printf(\"%s%s \", count[i], symbol[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
" | sed -e 's/ $//' &
|
||||
}
|
||||
|
||||
# =====[ dirt age ]=============================================================
|
||||
# Determine the time since last commit. If branch is clean,
|
||||
# use a neutral color, otherwise colors will vary according to time.
|
||||
|
||||
function vcs_dirt_age() {
|
||||
for vcs in $VCS_DETECTION_ORDER; do
|
||||
vcs_is_${vcs} && _vcs_dirt_age ${vcs} && return
|
||||
done
|
||||
}
|
||||
|
||||
function _vcs_dirt_age() {
|
||||
local vcs=$1
|
||||
echo $(_vcs_dirt_age_${vcs})
|
||||
}
|
||||
|
||||
function _vcs_dirt_age_hg() {
|
||||
local changed_date="$(hg log -l 1 --template '{date|hgdate}' | awk '{print $1 + $2}')"
|
||||
_vcs_is_clean_hg && local is_dirty=false
|
||||
echo $(_vcs_dirt_age_calculate ${changed_date} ${is_dirty:-true})
|
||||
}
|
||||
|
||||
function _vcs_dirt_age_svn() {
|
||||
local changed_date="$(svn info | awk -F'e: ' '/Changed Date:/{gsub(" \\(.*", "", $2); print $2}')"
|
||||
_vcs_is_clean_svn && local is_dirty=false
|
||||
echo $(_vcs_dirt_age_calculate $(date -j -f "%Y-%m-%d %T %z" "${changed_date}" "+%s") ${is_dirty:-true})
|
||||
}
|
||||
|
||||
function _vcs_dirt_age_git() {
|
||||
if git rev-parse --git-dir > /dev/null 2>&1; then
|
||||
# Only proceed if there is actually a commit.
|
||||
if [[ $(git log 2>&1 > /dev/null | grep -c "^fatal: bad default revision") == 0 ]]; then
|
||||
# Get the last commit.
|
||||
local last_commit=$(git log --pretty=format:'%at' -1 2> /dev/null)
|
||||
_vcs_is_clean_git && local is_dirty=false
|
||||
echo $(_vcs_dirt_age_calculate $last_commit ${is_dirty:-true})
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function _vcs_dirt_age_calculate() {
|
||||
local last_commit=$1
|
||||
local is_dirty=$2
|
||||
local result=''
|
||||
local now=$(date +%s)
|
||||
local seconds_since_last_commit=$((now-last_commit))
|
||||
|
||||
# totals
|
||||
local minutes=$((seconds_since_last_commit / 60))
|
||||
local hours=$((seconds_since_last_commit/3600))
|
||||
local years=$((seconds_since_last_commit / (86400 * 365) ))
|
||||
|
||||
# sub-hours and sub-minutes
|
||||
local days=$((seconds_since_last_commit / 86400))
|
||||
local sub_hours=$((hours % 24))
|
||||
local sub_minutes=$((minutes % 60))
|
||||
|
||||
if $is_dirty; then
|
||||
if [ "$minutes" -gt "$VCS_PLUGIN[long_age_threshold]" ]; then
|
||||
color="$VCS_PLUGIN[time_since_commit_long]"
|
||||
elif [ "$minutes" -gt "$VCS_PLUGIN[long_age_threshold]" ]; then
|
||||
color="$VCS_PLUGIN[time_short_commit_medium]"
|
||||
else
|
||||
color="$VCS_PLUGIN[time_since_commit_short]"
|
||||
fi
|
||||
else
|
||||
color="$VCS_PLUGIN[time_since_commit_neutral]"
|
||||
fi
|
||||
|
||||
if [ "$days" -gt 365 ]; then
|
||||
result=${years}y
|
||||
else
|
||||
if [ "$hours" -gt 24 ]; then
|
||||
if [[ -n $VCS_PLUGIN[time_verbose] ]]; then
|
||||
result="${days}d${sub_hours}h${sub_minutes}m"
|
||||
else
|
||||
result="${days}d"
|
||||
fi
|
||||
elif [ "$minutes" -gt 60 ]; then
|
||||
if [[ -n $VCS_PLUGIN[time_verbose] ]]; then
|
||||
result="${hours}h${sub_minutes}m"
|
||||
else
|
||||
result="${hours}h"
|
||||
fi
|
||||
else
|
||||
result="${minutes}m"
|
||||
fi
|
||||
fi
|
||||
echo "${color}${result}%{$reset_color%}"
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue