From 384c594abbf847dff8a89fc919d7f9c326a56870 Mon Sep 17 00:00:00 2001 From: Ashley Dev Date: Thu, 2 Jun 2011 11:07:00 -0700 Subject: [PATCH] Update plugins/git: - move aliases into plugins/git/git-aliases.plugin.zsh - move git prompt info into plugins/git/git-prompt-old.plugin.zsh - add revamped git prompt info into plugins/git/git-prompt.plugin.zsh - plugins/git/git.plugin.zsh now just sources the above files Added themes/ashleydev.theme.zsh that takes advantage of the new git prompt info --- plugins/git/git-aliases.plugin.zsh | 60 +++ plugins/git/git-prompt-old.plugin.zsh | 79 ++++ plugins/git/git-prompt.plugin.zsh | 604 ++++++++++++++++++++++++++ plugins/git/git.plugin.zsh | 120 +---- themes/ashleydev.zsh-theme | 144 ++++++ 5 files changed, 890 insertions(+), 117 deletions(-) create mode 100644 plugins/git/git-aliases.plugin.zsh create mode 100644 plugins/git/git-prompt-old.plugin.zsh create mode 100644 plugins/git/git-prompt.plugin.zsh create mode 100644 themes/ashleydev.zsh-theme diff --git a/plugins/git/git-aliases.plugin.zsh b/plugins/git/git-aliases.plugin.zsh new file mode 100644 index 00000000..859b637c --- /dev/null +++ b/plugins/git/git-aliases.plugin.zsh @@ -0,0 +1,60 @@ +# Aliases +alias g='git' ; compdef g=git +alias ga='git add' ; compdef _git ga=git-add +alias gaa='git add --all' ; compdef _git gaa=git-add +alias gs='git status' ; compdef _git gs=git-status +alias gst='git status' ; compdef _git gst=git-status +# for `gsts ""` +alias gsts='git stash save' ; compdef _git gsts=git-stash +alias gstp='git stash pop' ; compdef _git gstp=git-stash +alias gstl='git stash list' ; compdef _git gstl=git-stash +alias gstll='git stash show -p --stat' ; compdef _git gstll=git-stash +alias gl='git pull' ; compdef _git gl=git-pull +alias gup='git fetch && git rebase' ; compdef _git gup=git-fetch +alias gf='git fetch' ; compdef _git gf=git-fetch +alias gp='git push' ; compdef _git gp=git-push +alias gd='git diff --no-ext-diff -b' ; compdef _git gd=git-diff +alias gdd='git diff --no-ext-diff' ; compdef _git gdd=git-diff +gdv() { git-diff -w "$@" | view - } ; compdef _git gdv=git-diff +alias gc='git commit -v' ; compdef _git gc=git-commit +alias gca='git commit -v -a' ; compdef _git gca=git-commit +alias gco='git checkout' ; compdef _git gco=git-checkout +alias gb='git branch' ; compdef _git gb=git-branch +alias gba='git branch -a' ; compdef _git gba=git-branch +alias gcount='git shortlog -sn' ; compdef gcount=git +alias gcp='git cherry-pick' ; compdef _git gcp=git-cherry-pick +alias gm='git merge' ; compdef _git gm=git-merge +alias glg='git log --stat --max-count=5'; compdef _git glg=git-log + +# Git history (pretty) +local pretty_format_oneline='--pretty=format:"%C(yellow)%h %C(green)%cd %C(cyan)%an %C(bold cyan)%d%C(reset) %s" --date=short' +local pretty_format_medium='--pretty=format:"%C(yellow)commit %H %C(bold cyan)%d%C(reset) +%C(cyan)Author: %an <%ae>%C(reset) +%C(green)Date: %cd%C(reset) +%+s +%+b"' +alias gh="git log --graph $pretty_format_oneline" ; compdef _git gh=git-log +alias ghh="git log --graph $pretty_format_medium" ; compdef _git gh=git-log +alias ghhh="git log --graph --stat $pretty_format_medium" ; compdef _git gh=git-log +alias ghhhh="git log --graph --stat -p --full-diff $pretty_format_medium"; compdef _git gh=git-log + +# Git and svn mix +alias git-svn-dcommit-push='git svn dcommit && git push github master:svntrunk' +compdef _git git-svn-dcommit-push=git + +# +# Will return the current branch name +# Usage example: git pull origin $(current_branch) +# +function current_branch() { + ref=$(git symbolic-ref HEAD 2> /dev/null) || return + echo ${ref#refs/heads/} +} + +# these aliases take advantage of the previous function +alias ggpull='git pull origin $(current_branch)' +compdef _git ggpull=git +alias ggpush='git push origin $(current_branch)' +compdef _git ggpush=git +alias ggpnp='git pull origin $(current_branch) && git push origin $(current_branch)' +compdef _git ggpnp=git diff --git a/plugins/git/git-prompt-old.plugin.zsh b/plugins/git/git-prompt-old.plugin.zsh new file mode 100644 index 00000000..ece86e6d --- /dev/null +++ b/plugins/git/git-prompt-old.plugin.zsh @@ -0,0 +1,79 @@ +# Renders the name of the current branch. +function git_prompt_info() { + local branch=$(git_current_branch) + if [[ -n "$branch" ]]; then + echo "${ZSH_THEME_GIT_PROMPT_PREFIX}${branch}$(parse_git_dirty)${ZSH_THEME_GIT_PROMPT_SUFFIX}" + fi +} + +# Gets the current branch. +function git_current_branch() { + local ref=$(git symbolic-ref HEAD 2> /dev/null) + if [[ -n "$ref" ]]; then + echo "${ref#refs/heads/}" + fi +} + +# Checks if the working tree is dirty. +function parse_git_dirty() { + if [[ -n $(git status -s 2> /dev/null) ]]; then + echo "$ZSH_THEME_GIT_PROMPT_DIRTY" + else + echo "$ZSH_THEME_GIT_PROMPT_CLEAN" + fi +} + +# Checks if there are commits ahead from remote. +function git_prompt_ahead() { + if $(echo "$(git log origin/$(git_current_branch)..HEAD 2> /dev/null)" | grep '^commit' &> /dev/null); then + echo "$ZSH_THEME_GIT_PROMPT_AHEAD" + fi +} + +# Formats the prompt string for current git commit short SHA. +function git_prompt_short_sha() { + local sha=$(git rev-parse --short HEAD 2> /dev/null) + if [[ -n "$sha" ]]; then + echo "${ZSH_THEME_GIT_PROMPT_SHA_BEFORE}${sha}${ZSH_THEME_GIT_PROMPT_SHA_AFTER}" + fi +} + +# Formats the prompt string for current git commit long SHA. +function git_prompt_long_sha() { + local sha=$(git rev-parse HEAD 2> /dev/null) + if [[ -n "$sha" ]]; then + echo "${ZSH_THEME_GIT_PROMPT_SHA_BEFORE}${sha}${ZSH_THEME_GIT_PROMPT_SHA_AFTER}" + fi +} + +# Gets the status of the working tree. +function git_prompt_status() { + local indicators line untracked added modified renamed deleted + while IFS=$'\n' read line; do + if [[ "$line" =~ '^\?\? ' ]]; then + [[ -n $untracked ]] && continue || untracked='yes' + indicators="${ZSH_THEME_GIT_PROMPT_UNTRACKED}${indicators}" + fi + if [[ "$line" =~ '^(((A|M|D|T) )|(AD|AM|AT|MM)) ' ]]; then + [[ -n $added ]] && continue || added='yes' + indicators="${ZSH_THEME_GIT_PROMPT_ADDED}${indicators}" + fi + if [[ "$line" =~ '^(( (M|T))|(AM|AT|MM)) ' ]]; then + [[ -n $modified ]] && continue || modified='yes' + indicators="${ZSH_THEME_GIT_PROMPT_MODIFIED}${indicators}" + fi + if [[ "$line" =~ '^R ' ]]; then + [[ -n $renamed ]] && continue || renamed='yes' + indicators="${ZSH_THEME_GIT_PROMPT_RENAMED}${indicators}" + fi + if [[ "$line" =~ '^( D|AD) ' ]]; then + [[ -n $deleted ]] && continue || deleted='yes' + indicators="${ZSH_THEME_GIT_PROMPT_DELETED}${indicators}" + fi + if [[ "$line" =~ '^UU ' ]]; then + [[ -n $unmerged ]] && continue || unmerged='yes' + indicators="${ZSH_THEME_GIT_PROMPT_UNMERGED}${indicators}" + fi + done < <(git status --porcelain 2> /dev/null) + echo $indicators +} diff --git a/plugins/git/git-prompt.plugin.zsh b/plugins/git/git-prompt.plugin.zsh new file mode 100644 index 00000000..5b575be6 --- /dev/null +++ b/plugins/git/git-prompt.plugin.zsh @@ -0,0 +1,604 @@ +# ------------------------------------------------------------------------------ +# FILE: git-prompt.plugin.zsh +# DESCRIPTION: oh-my-zsh git information for your PROMPT. +# AUTHOR: Ashley Dev (the.ashley.dev+git-prompt@gmail.com) +# VERSION: 2.1 +# SCREENSHOT: +# ------------------------------------------------------------------------------ + +# USAGE: +# +# Add 'git' to your list of oh-my-zsh plugins (in your .zshrc) otherwise this +# git prompt info will not show up in your prompt. +# +# This example shows some of the things you can do with this plugin. This is +# how the author uses it: +# ---------------------- SAMPLE THEME FILE ------------------------ +# +# # this is a simple example PROMPT with only git +# # info from this plugin in it: +# PROMPT='$__GIT_PROMPT_INFO# ' +# +# # Set GIT_PROMPT_SHORTCIRCUIT='off' to turn the +# # short-circuit logic off. The short-circuit +# # logic will turn off the showing of dirty +# # state in your git prompt if ctrl-c is pressed +# # while the prompt is updating the dirty state +# # info. Gathering dirty-state info can take a +# # long time on large repositories, so if you +# # find that your prompt is taking for ever to +# # return, and you press ctrl-c, the short- +# # circuit logic will turn off the showing of +# # dirty state for this repository (locally) and +# # let you know, that way you won't be slowed +# # down waiting for your prompt in large git +# # repositories. +# #GIT_PROMPT_SHORTCIRCUIT='off' +# +# GIT_PROMPT_SHOWUPSTREAM="verbose" +# #GIT_PROMPT_SHOWREBASEINFO='off' +# #GIT_PROMPT_SHOWBRANCH='off' +# #GIT_PROMPT_SHOWSTASHSTATE='off' +# #GIT_PROMPT_SHORTCIRCUIT='off' +# #GIT_PROMPT_SHOWDIRTYSTATE='off' +# +# # Some color settings for my prompt format +# # '_C' for color: +# if [[ "$DISABLE_COLOR" != "true" ]]; then +# local _Cerror_="%{$fg[yellow]%}" # bad (empty) .git/ directory +# local _Cb_new_repo_="%{$fg_bold[default]%}" # branch color of new repo +# local _Cb_clean_="%{$fg_no_bold[green]%}" # branch color when clean +# local _Cb_dirty_="%{$fg_no_bold[red]%}" # branch color when dirty +# local _Cr_="%{$bold_color$fg[yellow]%}" # rebase info +# local _Ci_="%{$bold_color$fg[red]%}" # index info +# local _Cu_clean_="" # untracked files state when clean +# local _Cu_dirty_="%{$fg_bold[red]%}" # untracked files state when dirty +# local _Cp_="%{${fg[cyan]}%}" # upstream info +# local _Cs_="" # stash state +# # 'R'eset formating +# local R="%{$terminfo[sgr0]%}" +# fi +# +# # GIT_PROMPT_INFO_FUNC must be set to the +# # function that defines your prompt info +# # in order to turn this plugin on. +# # $GIT_PROMPT_INFO_FUNC to be called when the +# # git prompt info variable needs to be updated. +# GIT_PROMPT_INFO_FUNC='update__GIT_PROMPT_INFO' +# +# # update__GIT_PROMPT_INFO creates the format and +# # content of the git prompt info and puts the +# # result in $__GIT_PROMPT_INFO. Which you can +# # use in your $PROMPT (see above). This is an +# # example of some of the ways you can set up +# # your prompt with this plugin. +# # +# # NOTE: This function must set a global variable +# # (with the your git prompt format) that you +# # include in your PROMPT string. +# # It cannot echo this info as in: +# # PROMPT="$(update__GIT_PROMPT_INFO)" +# # or the short-circuit logic will not work. +# # +# local __GIT_PROMPT_INFO='' +# update__GIT_PROMPT_INFO () +# { +# local g="$(_git_promt__git_dir)" +# # short circuit if we're not in a git repo: +# if [ -z "$g" ]; then +# __GIT_PROMPT_INFO='' +# return +# fi +# +# _git_prompt__stash +# local s=$GIT_PROMPT_STASH_STATE_DIRTY +# +# _git_prompt__upstream +# local p=$GIT_PROMPT_UPSTREAM_STATE +# +# _git_prompt__branch +# local b=$GIT_PROMPT_BRANCH +# +# _git_prompt__rebase_info +# local r=$GIT_PROMPT_REBASE_INFO +# +# _git_prompt__dirty_state +# local w=$GIT_PROMPT_DIRTY_STATE_WORKTREE_DIRTY +# local i=$GIT_PROMPT_DIRTY_STATE_INDEX_DIRTY +# local u=$GIT_PROMPT_DIRTY_STATE_WORKTREE_UNTRACKED +# local f=$GIT_PROMPT_DIRTY_STATE_FRESH_REPO +# +# if [ -z "$b$i$w$u" ]; then +# if [ -n "$g" ]; then +# __GIT_PROMPT_INFO="$R$_Cerror_(Error: bad ./$g dir)$R" +# return +# fi +# fi +# +# if [ "$s" = 'yes' ]; then +# s="$_Cs_\$$R" +# else +# s="" +# fi +# +# if [ -n "$p" ]; then +# p="$_Cp_$p$R" +# fi +# +# if [ "$i" = "yes" ]; then +# i="$_Ci_+$R" +# else +# i="" +# fi +# +# if [ -n "$b" ]; then +# if [ "$f" = "yes" ]; then +# # this is a fresh repo, nothing here... +# b="$_Cb_new_repo_$b$R" +# elif [ "$w" = 'yes' ]; then +# b="$_Cb_dirty_$b$R" +# elif [ "$w" = 'no' ]; then +# b="$_Cb_clean_$b$R" +# fi +# fi +# +# if [ -n "$r" ]; then +# r="$_Cr_$r$R" +# fi +# +# local _prompt="$b$r$i$s$p" +# # add ( ) around _prompt: +# if [ $f = 'yes' ]; then +# _prompt="($_prompt)" +# elif [ "$u" = "yes" ]; then +# _prompt="$_Cu_dirty_($_prompt$_Cu_dirty_)" +# elif [ "$u" = "no" ]; then +# _prompt="$_Cu_clean_($_prompt$_Cu_clean_)" +# else +# fi +# +# __GIT_PROMPT_INFO="$R$_prompt$R" +# } +# ----------------------------------------------------------------- +# +# + + +#------------------ git information utils ------------------ +# For some of the following functions, I borrowed some from: +# https://github.com/git/git/blob/master/contrib/completion/git-completion.bash +# + +# _git_promt__git_dir accepts 0 or 1 arguments (i.e., location) +# echos the location of .git repo. +# Useful for quickly figuring out if cwd is under a git repo. +_git_promt__git_dir () +{ + if [ -z "${1-}" ]; then + if [ -d .git ]; then + echo .git + else + git rev-parse --git-dir 2>/dev/null + fi + elif [ -d "$1/.git" ]; then + echo "$1/.git" + else + echo "$1" + fi +} + +# sets GIT_PROMPT_UPSTREAM_STATE +# +# output format: +# A "<" indicates you are behind, ">" indicates you are ahead, "<>" +# indicates you have diverged, "=" indicates no divergence, and "" indicates +# there is no upstream or this feature is turned 'off' (see below). +# +# You can control behaviour by setting GIT_PROMPT_SHOWUPSTREAM to a +# space-separated list of values: +# off no output +# verbose show number of commits ahead/behind (+/-) upstream instead +# of using "<" and ">". +# legacy don't use the '--count' option available in recent +# versions of git-rev-list +# git always compare HEAD to @{upstream} +# svn always compare HEAD to your SVN upstream +# By default, _git_prompt__upstream will compare HEAD to your SVN upstream +# if it can find one, or @{upstream} otherwise. Once you have +# set GIT_PROMPT_SHOWUPSTREAM, you can override it on a +# per-repository basis by setting the prompt.showUpstream config +# variable (i.e. `git config prompt.showUpstream 'verbose legacy'`). +# +# _git_prompt__upstream accepts 0 or 1 arguments. If an argument is given, it +# must be a string of the form specified above for GIT_PROMPT_SHOWUPSTREAM. +# Setting this argument will override any value set for GIT_PROMPT_SHOWUPSTREAM +# or in the .git/config. +_git_prompt__upstream () +{ + GIT_PROMPT_UPSTREAM_STATE='' + + if [ "true" != "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then + return + fi + + local key value + local svn_remote svn_url_pattern count n + local upstream=git legacy="" verbose="" + local p + + # get some config options from git-config + while read key value; do + case "$key" in + prompt.showupstream*) + GIT_PROMPT_SHOWUPSTREAM="$value" + ;; + svn-remote.*.url) + svn_remote=( "${svn_remote[@]}" $value ) + svn_url_pattern="$svn_url_pattern\\|$value" + upstream=svn+git # default upstream is SVN if available, else git + ;; + esac + done < <(git config --get-regexp '^(svn-remote\..*\.url|prompt\.showupstream)' 2>/dev/null) + + if [ -n "${1-}" ]; then + GIT_PROMPT_SHOWUPSTREAM=$1 + fi + + # parse configuration values + for option in ${GIT_PROMPT_SHOWUPSTREAM}; do + case "$option" in + off) return ;; + git|svn) upstream="$option" ;; + verbose) verbose=1 ;; + legacy) legacy=1 ;; + esac + done + + # Find our upstream + case "$upstream" in + git) upstream="@{upstream}" ;; + svn*) + # get the upstream from the "git-svn-id: ..." in a commit message + # (git-svn uses essentially the same procedure internally) + local svn_upstream=$(git log --first-parent -1 --grep="^git-svn-id: \(${svn_url_pattern#??}\)" 2>/dev/null | awk '/commit / { print $2 }') + if [[ 0 -ne ${#svn_upstream[@]} ]]; then + if [[ -z "$svn_upstream" ]]; then + # default branch name for checkouts with no layout: + upstream='git-svn' + else + upstream=${svn_upstream#/} + fi + elif [[ "svn+git" = "$upstream" ]]; then + upstream="@{upstream}" + fi + ;; + esac + + # Find how many commits we are ahead/behind our upstream + # produce equivalent output to --count for older versions of git + local ahead behind + if git rev-list --left-right "$upstream"...HEAD >/dev/null 2>&1; then + behind="$(git rev-list --left-right "$upstream"...HEAD 2>/dev/null | grep '^<' | wc -l | tr -d ' ' 2>/dev/null)" + ahead="$(git rev-list --left-right "$upstream"...HEAD 2>/dev/null | grep '^[^<]' | wc -l | tr -d ' ' 2>/dev/null)" + count="$behind $ahead" + fi + + # calculate the result + if [[ -z "$verbose" ]]; then + case "$count" in + "") # no upstream + p="" ;; + "0 0") # equal to upstream + p="=" ;; + "0 "*) # ahead of upstream + p=">" ;; + *" 0") # behind upstream + p="<" ;; + *) # diverged from upstream + p="<>" ;; + esac + else + case "$count" in + "") # no upstream + p="" ;; + "0 0") # equal to upstream + p="=" ;; + "0 "*) # ahead of upstream + p="+${count#0 }" ;; + *" 0") # behind upstream + p="-${count% 0}" ;; + *) # diverged from upstream + p="-${count% *}+${count#* }" ;; + esac + fi + + GIT_PROMPT_UPSTREAM_STATE=$p +} + +_git_prompt__rebase_info () +{ + GIT_PROMPT_REBASE_INFO='' + + if [ "true" != "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then + return + fi + if [ "$GIT_PROMPT_SHOWREBASEINFO" = 'off' ]; then + return + fi + if [ "$(git config --bool prompt.showRebaseInfo)" = "false" ]; then + return + fi + + local r="" + local g="$(_git_promt__git_dir)" + if [ -n "$g" ]; then + if [ -f "$g/rebase-merge/interactive" ]; then + r="|REBASE-i" + elif [ -d "$g/rebase-merge" ]; then + r="|REBASE-m" + else + if [ -d "$g/rebase-apply" ]; then + if [ -f "$g/rebase-apply/rebasing" ]; then + r="|REBASE" + elif [ -f "$g/rebase-apply/applying" ]; then + r="|AM" + else + r="|AM/REBASE" + fi + elif [ -f "$g/MERGE_HEAD" ]; then + r="|MERGING" + elif [ -f "$g/CHERRY_PICK_HEAD" ]; then + r="|CHERRY-PICKING" + elif [ -f "$g/BISECT_LOG" ]; then + r="|BISECTING" + fi + + fi + fi + + GIT_PROMPT_REBASE_INFO=$r +} + +_git_prompt__branch () +{ + GIT_PROMPT_BRANCH='' + + if [ "true" != "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then + return + fi + + if [ "$GIT_PROMPT_SHOWBRANCH" = 'off' ]; then + return + fi + if [ "$(git config --bool prompt.showBranch)" = "false" ]; then + return + fi + + local b="" + local g="$(_git_promt__git_dir)" + if [ -n "$g" ]; then + if [ -f "$g/rebase-merge/interactive" ]; then + b="$(cat "$g/rebase-merge/head-name")" + elif [ -d "$g/rebase-merge" ]; then + b="$(cat "$g/rebase-merge/head-name")" + else + b="$(git symbolic-ref HEAD 2>/dev/null)" || { + + b="$( + case "${GIT_PROMPT_DESCRIBE_STYLE-}" in + (contains) + git describe --contains HEAD ;; + (branch) + git describe --contains --all HEAD ;; + (describe) + git describe HEAD ;; + (* | default) + git describe --tags --exact-match HEAD ;; + esac 2>/dev/null)" || + + b="$(cut -c1-7 "$g/HEAD" 2>/dev/null)" || + b="$b" + } + fi + b=${b##refs/heads/} + if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then + if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then + b="BARE:$b" + else + b="GIT_DIR!" + fi + fi + fi + + GIT_PROMPT_BRANCH=$b +} + + +_git_prompt__stash () +{ + GIT_PROMPT_STASH_STATE_DIRTY='' + + if [ "true" != "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then + return + fi + + if [ "$GIT_PROMPT_SHOWSTASHSTATE" = 'off' ]; then + return + fi + if [ "$(git config --bool prompt.showStashState)" = "false" ]; then + return + fi + + if git rev-parse --verify refs/stash >/dev/null 2>&1; then + GIT_PROMPT_STASH_STATE_DIRTY='yes' + else + GIT_PROMPT_STASH_STATE_DIRTY='no' + fi +} + + +# This is the short-circuit logic: +local _big_repo='init' +__git_prompt_shortcircuit () +{ + if [[ "$_big_repo" == 'yes' ]]; then + _big_repo='' + if [ "$GIT_PROMPT_SHORTCIRCUIT" != 'off' ]; then + echo "$fg[red]" > /dev/stderr + echo "${bold_color}SHELL PROMPT$fg_no_bold[red]: Looks like you hit ctrl-c." > /dev/stderr + echo "${bold_color}SHELL PROMPT$fg_no_bold[red]: So for this repo I'm setting:" > /dev/stderr + echo "${bold_color}SHELL PROMPT$fg_no_bold[red]: git config prompt.showDirtyState false" > /dev/stderr + echo "${bold_color}SHELL PROMPT$fg_no_bold[red]: On big git repos it takes a long time to get info for your prompt." > /dev/stderr + echo "${bold_color}SHELL PROMPT$fg_no_bold[red]: To revert it, run:" > /dev/stderr + echo "${bold_color}SHELL PROMPT$fg_no_bold[red]:$reset_color git config prompt.showDirtyState true" > /dev/stderr + echo '' > /dev/stderr + + git config prompt.showDirtyState 'false' + $GIT_PROMPT_INFO_FUNC + fi + fi +} +TRAPINT () +{ + __git_prompt_shortcircuit + return $(( 128 + $1 )) +} + +_git_prompt__dirty_state () +{ + GIT_PROMPT_DIRTY_STATE_FRESH_REPO='' + GIT_PROMPT_DIRTY_STATE_INDEX_ADDED='' + GIT_PROMPT_DIRTY_STATE_INDEX_COPIED='' + GIT_PROMPT_DIRTY_STATE_INDEX_DELETED='' + GIT_PROMPT_DIRTY_STATE_INDEX_DIRTY='' + GIT_PROMPT_DIRTY_STATE_INDEX_MODIFIED='' + GIT_PROMPT_DIRTY_STATE_INDEX_RENAMED='' + GIT_PROMPT_DIRTY_STATE_INDEX_UNMERGED='' + GIT_PROMPT_DIRTY_STATE_WORKTREE_DELETED='' + GIT_PROMPT_DIRTY_STATE_WORKTREE_DIRTY='' + GIT_PROMPT_DIRTY_STATE_WORKTREE_MODIFIED='' + GIT_PROMPT_DIRTY_STATE_WORKTREE_UNTRACKED='' + + if [ "true" != "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then + return + fi + + local g="$(_git_promt__git_dir)" + if [ -z "$g" ]; then + return + fi + if [ "$GIT_PROMPT_SHOWDIRTYSTATE" = 'off' ]; then + return + fi + if [ "$(git config --bool prompt.showDirtyState)" = "false" ]; then + return + fi + + GIT_PROMPT_DIRTY_STATE_FRESH_REPO='no' + GIT_PROMPT_DIRTY_STATE_INDEX_ADDED='no' + GIT_PROMPT_DIRTY_STATE_INDEX_COPIED='no' + GIT_PROMPT_DIRTY_STATE_INDEX_DELETED='no' + GIT_PROMPT_DIRTY_STATE_INDEX_DIRTY='no' + GIT_PROMPT_DIRTY_STATE_INDEX_MODIFIED='no' + GIT_PROMPT_DIRTY_STATE_INDEX_RENAMED='no' + GIT_PROMPT_DIRTY_STATE_INDEX_UNMERGED='no' + GIT_PROMPT_DIRTY_STATE_WORKTREE_DELETED='no' + GIT_PROMPT_DIRTY_STATE_WORKTREE_DIRTY='no' + GIT_PROMPT_DIRTY_STATE_WORKTREE_MODIFIED='no' + GIT_PROMPT_DIRTY_STATE_WORKTREE_UNTRACKED='no' + + if git rev-parse --quiet --verify HEAD >/dev/null; then + else + GIT_PROMPT_DIRTY_STATE_FRESH_REPO='yes' + fi + + _big_repo='yes' + local line + while IFS=$'\n' read line; do + if [[ "$line" = M* ]]; then + GIT_PROMPT_DIRTY_STATE_INDEX_MODIFIED='yes' + GIT_PROMPT_DIRTY_STATE_INDEX_DIRTY='yes' + fi + if [[ "$line" = A* ]]; then + GIT_PROMPT_DIRTY_STATE_INDEX_ADDED='yes' + GIT_PROMPT_DIRTY_STATE_INDEX_DIRTY='yes' + fi + if [[ "$line" = R* ]]; then + GIT_PROMPT_DIRTY_STATE_INDEX_RENAMED='yes' + GIT_PROMPT_DIRTY_STATE_INDEX_DIRTY='yes' + fi + if [[ "$line" = C* ]]; then + GIT_PROMPT_DIRTY_STATE_INDEX_COPIED='yes' + GIT_PROMPT_DIRTY_STATE_INDEX_DIRTY='yes' + fi + if [[ "$line" = D* ]]; then + GIT_PROMPT_DIRTY_STATE_INDEX_DELETED='yes' + GIT_PROMPT_DIRTY_STATE_INDEX_DIRTY='yes' + fi + + if [[ "$line" = \?\?* ]]; then + GIT_PROMPT_DIRTY_STATE_WORKTREE_UNTRACKED='yes' + fi + if [[ "$line" = \ M* ]]; then + GIT_PROMPT_DIRTY_STATE_WORKTREE_MODIFIED='yes' + GIT_PROMPT_DIRTY_STATE_WORKTREE_DIRTY='yes' + fi + if [[ "$line" = \ D* ]]; then + GIT_PROMPT_DIRTY_STATE_WORKTREE_DELETED='yes' + GIT_PROMPT_DIRTY_STATE_WORKTREE_DIRTY='yes' + fi + + if [[ "$line" = UU* ]]; then + GIT_PROMPT_DIRTY_STATE_INDEX_UNMERGED='yes' + GIT_PROMPT_DIRTY_STATE_INDEX_DIRTY='yes' + fi + done < <(git status --porcelain 2> /dev/null) + _big_repo='' +} + +#------------------ Fast Prompt ------------------ +# This section sets up some functions that get called infrequently as possible +# and therefore don't slow your prompt down as you are using zsh. +# +# I borrowed from: http://sebastiancelis.com/2009/nov/16/zsh-prompt-git-users/ + +# Enable auto-execution of functions. +typeset -Uga preexec_functions +typeset -Uga precmd_functions +typeset -Uga chpwd_functions +typeset -Uga periodic_functions + +# Append git functions needed for prompt. +preexec_functions+='_git_prompt__preexec_update_git_vars' +precmd_functions+='_git_prompt__precmd_update_git_vars' +chpwd_functions+="_git_prompt_info" +PERIOD=15 +periodic_functions+="_git_prompt_info" + +_git_prompt_info () { $GIT_PROMPT_INFO_FUNC } +_git_prompt_info + +_git_prompt__precmd_update_git_vars() +{ + if [[ $ZSH_VERSION = *\ 4.2* ]]; then + # some older versions of zsh don't have periodic_functions, so do the + # slow path if that's the case: + $GIT_PROMPT_INFO_FUNC + + elif [ -n "$__EXECUTED_GIT_COMMAND" ]; then + $GIT_PROMPT_INFO_FUNC + unset __EXECUTED_GIT_COMMAND + fi +} +_git_prompt__preexec_update_git_vars () +{ + case "$1" in + $EDITOR*) __EXECUTED_GIT_COMMAND=1 ;; + g*) __EXECUTED_GIT_COMMAND=1 ;; + rm*) __EXECUTED_GIT_COMMAND=1 ;; + touch*) __EXECUTED_GIT_COMMAND=1 ;; + mkdir*) __EXECUTED_GIT_COMMAND=1 ;; + esac +} + +#-------------------------------------------------- diff --git a/plugins/git/git.plugin.zsh b/plugins/git/git.plugin.zsh index baf34b83..bb515c73 100644 --- a/plugins/git/git.plugin.zsh +++ b/plugins/git/git.plugin.zsh @@ -1,117 +1,3 @@ -# Renders the name of the current branch. -function git_prompt_info() { - local branch=$(git_current_branch) - if [[ -n "$branch" ]]; then - echo "${ZSH_THEME_GIT_PROMPT_PREFIX}${branch}$(parse_git_dirty)${ZSH_THEME_GIT_PROMPT_SUFFIX}" - fi -} - -# Gets the current branch. -function git_current_branch() { - local ref=$(git symbolic-ref HEAD 2> /dev/null) - if [[ -n "$ref" ]]; then - echo "${ref#refs/heads/}" - fi -} - -# Checks if the working tree is dirty. -function parse_git_dirty() { - if [[ -n $(git status -s 2> /dev/null) ]]; then - echo "$ZSH_THEME_GIT_PROMPT_DIRTY" - else - echo "$ZSH_THEME_GIT_PROMPT_CLEAN" - fi -} - -# Checks if there are commits ahead from remote. -function git_prompt_ahead() { - if $(echo "$(git log origin/$(git_current_branch)..HEAD 2> /dev/null)" | grep '^commit' &> /dev/null); then - echo "$ZSH_THEME_GIT_PROMPT_AHEAD" - fi -} - -# Formats the prompt string for current git commit short SHA. -function git_prompt_short_sha() { - local sha=$(git rev-parse --short HEAD 2> /dev/null) - if [[ -n "$sha" ]]; then - echo "${ZSH_THEME_GIT_PROMPT_SHA_BEFORE}${sha}${ZSH_THEME_GIT_PROMPT_SHA_AFTER}" - fi -} - -# Formats the prompt string for current git commit long SHA. -function git_prompt_long_sha() { - local sha=$(git rev-parse HEAD 2> /dev/null) - if [[ -n "$sha" ]]; then - echo "${ZSH_THEME_GIT_PROMPT_SHA_BEFORE}${sha}${ZSH_THEME_GIT_PROMPT_SHA_AFTER}" - fi -} - -# Gets the status of the working tree. -function git_prompt_status() { - local indicators line untracked added modified renamed deleted - while IFS=$'\n' read line; do - if [[ "$line" =~ '^\?\? ' ]]; then - [[ -n $untracked ]] && continue || untracked='yes' - indicators="${ZSH_THEME_GIT_PROMPT_UNTRACKED}${indicators}" - fi - if [[ "$line" =~ '^(((A|M|D|T) )|(AD|AM|AT|MM)) ' ]]; then - [[ -n $added ]] && continue || added='yes' - indicators="${ZSH_THEME_GIT_PROMPT_ADDED}${indicators}" - fi - if [[ "$line" =~ '^(( (M|T))|(AM|AT|MM)) ' ]]; then - [[ -n $modified ]] && continue || modified='yes' - indicators="${ZSH_THEME_GIT_PROMPT_MODIFIED}${indicators}" - fi - if [[ "$line" =~ '^R ' ]]; then - [[ -n $renamed ]] && continue || renamed='yes' - indicators="${ZSH_THEME_GIT_PROMPT_RENAMED}${indicators}" - fi - if [[ "$line" =~ '^( D|AD) ' ]]; then - [[ -n $deleted ]] && continue || deleted='yes' - indicators="${ZSH_THEME_GIT_PROMPT_DELETED}${indicators}" - fi - if [[ "$line" =~ '^UU ' ]]; then - [[ -n $unmerged ]] && continue || unmerged='yes' - indicators="${ZSH_THEME_GIT_PROMPT_UNMERGED}${indicators}" - fi - done < <(git status --porcelain 2> /dev/null) - echo $indicators -} - -alias g='git' -compdef g=git -alias gst='git status' -compdef _git gst=git-status -alias gl='git pull' -compdef _git gl=git-pull -alias gup='git fetch && git rebase' -compdef _git gup=git-fetch -alias gp='git push' -compdef _git gp=git-push -gdv() { git-diff -w "$@" | view - } -compdef _git gdv=git-diff -alias gc='git commit -v' -compdef _git gc=git-commit -alias gca='git commit -v -a' -compdef _git gca=git-commit -alias gco='git checkout' -compdef _git gco=git-checkout -alias gb='git branch' -compdef _git gb=git-branch -alias gba='git branch -a' -compdef _git gba=git-branch -alias gcount='git shortlog -sn' -compdef gcount=git -alias gcp='git cherry-pick' -compdef _git gcp=git-cherry-pick -alias glg='git log --stat --max-count=5' -compdef _git glg=git-log -alias git-svn-dcommit-push='git svn dcommit && git push github master:svntrunk' -compdef git-svn-dcommit-push=git -alias ggpull='git pull origin $(git_current_branch)' -compdef ggpull=git -alias ggpush='git push origin $(git_current_branch)' -compdef ggpush=git -alias ggpnp='git pull origin $(git_current_branch) && git push origin $(git_current_branch)' -compdef ggpnp=git - +source $ZSH/plugins/git/git-aliases.plugin.zsh +source $ZSH/plugins/git/git-prompt-old.plugin.zsh +source $ZSH/plugins/git/git-prompt.plugin.zsh diff --git a/themes/ashleydev.zsh-theme b/themes/ashleydev.zsh-theme new file mode 100644 index 00000000..bf093276 --- /dev/null +++ b/themes/ashleydev.zsh-theme @@ -0,0 +1,144 @@ +# NOTE: make sure to add 'git' to your list of oh-my-zsh plugins (in your +# ~/.zshrc), otherwise the git prompt info will not be shown. + +#-------------------- Colors ---------------------- +# Colors ('_C' for color): +if [[ "$DISABLE_COLOR" != "true" ]]; then + # git prompt info colors: + local _Cerror_="%{$fg[yellow]%}" # bad (empty) .git/ directory + local _Cb_new_repo_="%{$fg_bold[default]%}" # branch color of new repo + local _Cb_clean_="%{$fg_no_bold[green]%}" # branch color when clean + local _Cb_dirty_="%{$fg_no_bold[red]%}" # branch color when dirty + local _Cr_="%{$bold_color$fg[yellow]%}" # rebase info + local _Ci_="%{$bold_color$fg[red]%}" # index info + local _Cu_clean_="" # untracked files state when clean + local _Cu_dirty_="%{$fg_bold[red]%}" # untracked files state when dirty + local _Cp_="%{${fg[cyan]}%}" # upstream info + local _Cs_="" # stash state + + # Reset formating: + local R="%{$terminfo[sgr0]%}" + + # PROMPT colors: + local _Cuser_root_="%{$fg_bold[yellow]$bg[red]%}" + local _Chost_root_="%{$fg[red]%}" + local _Cpath_root_="%{$fg_bold[white]%}" + local _Cuser_="%{$fg_bold[cyan]%}" + local _Chost_="%{$fg_bold[blue]%}" + local _Cpath_="%{$fg_bold[white]%}" + local _Cjobs_="%{$fg[blue]%}" + + # RPROMPT colors: + local _Cdate_="%{$fg[green]%}" + local _Creturn_code_="%{$fg[red]%}" + local _Cvi_mode_="%{$fg_bold[cyan]%}" +fi + +#----------------------------------------------------- +# git prompt info: + +# The git prompt plugin will cause $GIT_PROMPT_INFO_FUNC to be called +# when $__GIT_PROMPT_INFO needs to be updated. +GIT_PROMPT_INFO_FUNC="update__GIT_PROMPT_INFO" +GIT_PROMPT_SHOWUPSTREAM="verbose" +GIT_PROMPT_SHORTCIRCUIT='on' + +local __GIT_PROMPT_INFO='' +# will set __GIT_PROMPT_INFO +update__GIT_PROMPT_INFO () +{ + local g="$(_git_promt__git_dir)" + if [ -z "$g" ]; then + __GIT_PROMPT_INFO='' + return + fi + + _git_prompt__stash + local s=$GIT_PROMPT_STASH_STATE_DIRTY + + _git_prompt__upstream + local p=$GIT_PROMPT_UPSTREAM_STATE + + _git_prompt__branch + local b=$GIT_PROMPT_BRANCH + + _git_prompt__rebase_info + local r=$GIT_PROMPT_REBASE_INFO + + _git_prompt__dirty_state + local w=$GIT_PROMPT_DIRTY_STATE_WORKTREE_DIRTY + local i=$GIT_PROMPT_DIRTY_STATE_INDEX_DIRTY + local u=$GIT_PROMPT_DIRTY_STATE_WORKTREE_UNTRACKED + local f=$GIT_PROMPT_DIRTY_STATE_FRESH_REPO + + if [ -z "$b$i$w$u" ]; then + if [ -n "$g" ]; then + __GIT_PROMPT_INFO="$R$_Cerror_(Error: bad ./$g dir)$R" + return + fi + fi + + if [ "$s" = 'yes' ]; then + s="$_Cs_\$$R" + else + s="" + fi + + if [ -n "$p" ]; then + p="$_Cp_$p$R" + fi + + if [ "$i" = "yes" ]; then + i="$_Ci_+$R" + else + i="" + fi + + if [ -n "$b" ]; then + if [ "$f" = "yes" ]; then + # this is a fresh repo, nothing here... + b="$_Cb_new_repo_$b$R" + elif [ "$w" = 'yes' ]; then + b="$_Cb_dirty_$b$R" + elif [ "$w" = 'no' ]; then + b="$_Cb_clean_$b$R" + fi + fi + + if [ -n "$r" ]; then + r="$_Cr_$r$R" + fi + + local _prompt="$b$r$i$s$p" + # add ( ) around _prompt: + if [ "$f" = 'yes' ]; then + _prompt="($_prompt)" + elif [ "$u" = "yes" ]; then + _prompt="$_Cu_dirty_($_prompt$_Cu_dirty_)" + elif [ "$u" = "no" ]; then + _prompt="$_Cu_clean_($_prompt$_Cu_clean_)" + else + fi + + __GIT_PROMPT_INFO="$R$_prompt$R" +} + + +#-------------------- PROMPT definition: ---------------------- +# +local user_="%(!.$_Cuser_root_.$_Cuser_)%n$R" +local host_="%(!.$_Chost_root_.$_Chost_)%m$R" +local path_="%(!.$_Cpath_root_.$_Cpath_)%~$R" +local jobs_="%(1j.$_Cjobs_%j$R.)" + +PROMPT='$user_$host_$path_ $__GIT_PROMPT_INFO$jobs_# ' + +local date_format_='%D{%a %b %d}, %*' +local date_="${_Cdate_}[$date_format_]$R" +local return_code_="%(?..$_Creturn_code_%? ↵ )$R" + +RPROMPT='$return_code_$date_' + +# use the vi-mode oh-my-zsh plugin to get this: +MODE_INDICATOR="${_Cvi_mode_}-- CMD MODE -- $R" +