From 225ea89e7452b1fed3d7a9a1f5493872b1974342 Mon Sep 17 00:00:00 2001 From: Sorin Ionescu Date: Mon, 5 Sep 2011 00:37:36 -0400 Subject: [PATCH] Rewrote the Git plugin and Sorin theme. --- plugins/git/.gitignore | 1 + plugins/git/_git-info | 8 + plugins/git/alias.zsh | 241 ++++++++++++++++++++ plugins/git/completion.zsh | 15 ++ plugins/git/git.plugin.zsh | 381 +------------------------------- plugins/git/info.zsh | 357 ++++++++++++++++++++++++++++++ plugins/git/utility.zsh | 46 ++++ themes/sorin/prompt_sorin_setup | 45 ++-- 8 files changed, 708 insertions(+), 386 deletions(-) create mode 100644 plugins/git/.gitignore create mode 100644 plugins/git/_git-info create mode 100644 plugins/git/alias.zsh create mode 100644 plugins/git/completion.zsh create mode 100644 plugins/git/info.zsh create mode 100644 plugins/git/utility.zsh diff --git a/plugins/git/.gitignore b/plugins/git/.gitignore new file mode 100644 index 00000000..6c331089 --- /dev/null +++ b/plugins/git/.gitignore @@ -0,0 +1 @@ +_git diff --git a/plugins/git/_git-info b/plugins/git/_git-info new file mode 100644 index 00000000..2cdbc289 --- /dev/null +++ b/plugins/git/_git-info @@ -0,0 +1,8 @@ +#compdef git-info +#autoload + +_arguments "1:toggle:(( + on\:'Turn prompt Git status on for the current repository.' + off\:'Turn prompt Git status off for the current repository.' +))" && return 0 + diff --git a/plugins/git/alias.zsh b/plugins/git/alias.zsh new file mode 100644 index 00000000..67d6000c --- /dev/null +++ b/plugins/git/alias.zsh @@ -0,0 +1,241 @@ +# Git +alias g='git' +compdef g=git + +# Working Copy (w) +alias gws='git status --short' +compdef _git gws=git-status +alias gwS='git status' +compdef _git gwS=git-status +alias gwd='git diff --no-ext-diff' +compdef _git gwd=git-diff +function gwD() { git diff --no-ext-diff --ignore-all-space "$@" | view - } +compdef _git gwD=git-diff +alias gwr='git reset --soft' +compdef _git gwr=git-reset +alias gwR='git reset --hard' +compdef _git gwR=git-reset +alias gwc='git clean -n' +compdef _git gwc=git-clean +alias gwC='git clean -f' +compdef _git gwC=git-clean +alias gwx='git rm -r' +compdef _git gwx=git-rm +alias gwX='git rm -rf' +compdef _git gwX=git-rm +alias gwg='git grep' +compdef _git gwg=git-grep + +# Index +alias gia='git add' +compdef _git gia=git-add +alias giA='git add --patch' +compdef _git giA=git-add +alias giu='git add --update' +compdef _git giu=git-add +alias gid='git diff --no-ext-diff --cached' +compdef _git gid=git-diff +alias gir='git reset' +compdef _git gir=git-reset +alias giR='git reset --mixed' +compdef _git giR=git-reset +alias gix='git rm -r --cached' +compdef _git gix=git-rm +alias giX='git rm -rf --cached' +compdef _git giX=git-rm +alias gig='git grep --cached' +compdef _git gig=git-grep + +# Branah (b) +alias gb='git branch' +compdef _git gb=git-branch +alias gbc='git checkout -b' +compdef _git gbc=git-checkout +alias gbl='git branch -v' +compdef _git gbl=git-branch +alias gbL='git branch -av' +compdef _git gbL=git-branch +alias gbx='git branch -d' +compdef _git gbx=git-branch +alias gbX='git branch -D' +compdef _git gbX=git-branch +alias gbm='git branch -m' +compdef _git gbm=git-branch +alias gbM='git branch -M' +compdef _git gbM=git-branch + +# Commit (c) +alias gc='git commit' +compdef _git gc=git-commit +alias gca='git commit --all' +compdef _git gca=git-commit +alias gcm='git commit --message' +compdef _git gcm=git-commit +alias gco='git checkout' +compdef _git gco=git-checkout +alias gcO='git checkout HEAD --' +compdef _git gcO=git-checkout +alias gcf='git commit --amend --reuse-message HEAD' +compdef _git gcf=git-commit +alias gcp='git cherry-pick --ff' +compdef _git gcp=git-cherry-pick +alias gcP='git cherry-pick --no-commit' +compdef _git gcP=git-cherry-pick +alias gcr='git revert' +compdef _git gcr=git-revert +alias gcR='git reset "HEAD^"' +compdef _git gcR=git-reset +alias gcs='git show' +compdef _git gcs=git-show +alias gcv='git fsck | awk '\''/dangling commit/ {print $3}'\'' | git show --format="SHA1: %C(green)%h%C(reset) %f" --stdin | awk '\''/SHA1/ {sub("SHA1: ", ""); print}'\''' + +# Conflict (k) +alias gkl='git status | sed -n "s/^.*both [a-z]*ed: *//p"' +alias gka='git add $(gkl)' +compdef _git gka=git-add +alias gke='git mergetool $(gkl)' +alias gko='git checkout --ours --' +compdef _git gko=git-checkout +alias gkO='gko $(gkl)' +alias gkt='git checkout --theirs --' +compdef _git gkt=git-checkout +alias gkT='gkt $(gkl)' + +# File Data (d) +alias gd='git ls-files' +compdef _git gd=git-ls-files +alias gdc='git ls-files --cached' +compdef _git gdc=git-ls-files +alias gdx='git ls-files --deleted' +compdef _git gdx=git-ls-files +alias gdm='git ls-files --modified' +compdef _git gdm=git-ls-files +alias gdu='git ls-files --others' +compdef _git gdu=git-ls-files +alias gdk='git ls-files --killed' +compdef _git gdk=git-ls-files +alias gdi='git status --porcelain --short --ignored | sed -n "s/^!! //p"' + +# Merge (m) +alias gm='git merge' +compdef _git gm=git-merge +alias gmC='git merge --no-commit' +compdef _git gmC=git-merge +alias gmF='git merge --no-ff' +compdef _git gmF=git-merge +alias gma='git merge --abort' +compdef _git gma=git-merge +alias gmt='git mergetool' +compdef _git gmt=git-mergetool + +# Pull +alias gf='git fetch' +compdef _git gf=git-fetch +alias gfc='git clone' +compdef _git gfc=git-clone +alias gfm='git pull' +compdef _git gfm=git-pull +alias gfr='git pull --rebase' +compdef _git gfr=git-pull + +# Push +alias gp='git push' +compdef _git gp=git-push +alias gpf='git push --force' +compdef _git gpf=git-push +alias gpa='git push --all' +compdef _git gpa=git-push +alias gpA='git push --all && git push --tags' +compdef _git gpA=git-push +alias gpt='git push --tags' +compdef _git gpt=git-push +alias gpc='git push --set-upstream origin "$(git-branch)"' +compdef _git gpc=git-push +alias gpp='git pull origin "$(git-branch)" && git push origin "$(git-branch)"' + +# Rebase (r) +alias gr='git rebase' +compdef _git gr=git-rebase +alias gra='git rebase --abort' +compdef _git gra=git-rebase +alias grc='git rebase --continue' +compdef _git grc=git-rebase +alias gri='git rebase --interactive' +compdef _git gri=git-rebase +alias grs='git rebase --skip' +compdef _git grs=git-rebase + +# Remote Host (h) +alias gh='git remote' +compdef _git gh=git-remote +alias ghl='git remote --verbose' +compdef _git ghl=git-remote +alias gha='git remote add' +compdef _git gha=git-remote +alias ghx='git remote rm' +compdef _git ghx=git-remote +alias ghm='git remote rename' +compdef _git ghm=git-remote +alias ghu='git remote update' +compdef _git ghu=git-remote +alias ghc='git remote prune' +compdef _git ghc=git-remote +alias ghs='git remote show' +compdef _git ghs=git-remote + +# Stash (t) +alias gta='git stash apply' +compdef _git gta=git-stash +alias gtc='git stash clear' +compdef _git gtc=git-stash +alias gtx='git stash drop' +compdef _git gtx=git-stash +alias gtl='git stash list' +compdef _git gtl=git-stash +alias gtL='git stash show --patch --stat' +compdef _git gtL=git-stash +alias gtp='git stash pop' +compdef _git gtp=git-stash +alias gts='git stash save' +compdef _git gts=git-stash +alias gtS='git stash save --patch --no-keep-index' +compdef _git gtS=git-stash + +# Submodule (u) +alias gu='git submodule' +compdef _git gu=git-submodule +alias gua='git submodule add' +compdef _git gua=git-submodule +alias guf='git submodule foreach' +compdef _git guf=git-submodule +alias gui='git submodule init' +compdef _git gui=git-submodule +alias gul='git submodule status' +compdef _git gul=git-submodule +alias gus='git submodule sync' +compdef _git gus=git-submodule +alias guu='git submodule update' +compdef _git guu=git-submodule +alias guU='git submodule update --init --recursive' +compdef _git guU=git-submdoule + +# Git log (pretty). +git_log_format_oneline='--pretty=format:%C(green)%h%C(reset) %s%C(red)%d%C(reset)' +git_log_format_oneline_more='--pretty=format:%C(green)%h%C(reset) %C(blue)%ad%C(reset) %s%C(red)%d%C(reset) [%C(magenta)%an%C(reset)]' +git_log_format_medium='--pretty=format:%C(green)Commit: %H%C(red)%d%C(reset)%n%C(magenta)Author: %an <%ae>%C(reset)%n%C(blue)Date: %cd%C(reset)%n%+s%n%+b' + +alias gl='git log' +compdef _git gl=git-log +alias glo='git log --topo-order ${git_log_format_oneline}' +compdef _git glo=git-log +alias glO='git log --topo-order --date=short ${git_log_format_oneline_more}' +compdef _git glO=git-log +alias glg='git log --graph --topo-order ${git_log_format_medium}' +compdef _git glg=git-log +alias gls='git log --graph --topo-order --stat ${git_log_format_medium}' +compdef _git gls=git-log +alias gld='git log --graph --topo-order --stat --patch --full-diff ${git_log_format_medium}' +compdef _git gld=git-log +alias glc='git shortlog --summary --numbered' +compdef _git glc=git-shortlog + diff --git a/plugins/git/completion.zsh b/plugins/git/completion.zsh new file mode 100644 index 00000000..4bcf7e96 --- /dev/null +++ b/plugins/git/completion.zsh @@ -0,0 +1,15 @@ +# Get the latest Git completion. +completion_file="${0:h}/_git" +completion_file_url='http://zsh.git.sourceforge.net/git/gitweb.cgi?p=zsh/zsh;a=blob_plain;f=Completion/Unix/Command/_git;hb=HEAD' +if [[ ! -e "$completion_file" ]] && (( $+commands[git] )); then + if (( $+commands[curl] )); then + curl -L "$completion_file_url" -o "$completion_file" &> /dev/null &! + fi + + if (( $+commmands[wget] )); then + wget -C "$completion_file_url" -O "$completion_file" &> /dev/null &! + fi +fi +unset completion_file +unset completion_file_url + diff --git a/plugins/git/git.plugin.zsh b/plugins/git/git.plugin.zsh index c89ce016..74cf9434 100644 --- a/plugins/git/git.plugin.zsh +++ b/plugins/git/git.plugin.zsh @@ -1,370 +1,13 @@ -# Set the default Git prompt theme. -ZSH_THEME_GIT_PROMPT_PREFIX="git:(" # Prefix before the branch name. -ZSH_THEME_GIT_PROMPT_SUFFIX=")" # Suffix after the branch name. -ZSH_THEME_GIT_PROMPT_SHA_BEFORE="" # Prefix before the SHA-1 hash. -ZSH_THEME_GIT_PROMPT_SHA_AFTER="" # Suffix after the SHA-1 hash. -ZSH_THEME_GIT_PROMPT_DIRTY="*" # Indicator to notify of dirty branch. -ZSH_THEME_GIT_PROMPT_CLEAN="" # Indicator to notify of clean branch. -ZSH_THEME_GIT_PROMPT_AHEAD="" # Indicator to notify of ahead branch -ZSH_THEME_GIT_PROMPT_UNTRACKED="" # Indicator to notify of untracked files. -ZSH_THEME_GIT_PROMPT_ADDED="" # Indicator to notify of added files. -ZSH_THEME_GIT_PROMPT_MODIFIED="" # Indicator to notify of modified files. -ZSH_THEME_GIT_PROMPT_RENAMED="" # Indicator to notify of renamed files. -ZSH_THEME_GIT_PROMPT_DELETED="" # Indicator to notify of deleted files. -ZSH_THEME_GIT_PROMPT_UNMERGED="" # Indicator to notify of unmerged files. - -# Checks if the working tree is dirty. -function __git-parse-dirty() { - if [[ -n "$(git status -s 2> /dev/null)" ]]; then - echo "$ZSH_THEME_GIT_PROMPT_DIRTY" - else - echo "$ZSH_THEME_GIT_PROMPT_CLEAN" - fi -} - -# 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}$(__git-parse-dirty)${ZSH_THEME_GIT_PROMPT_SUFFIX}" - else - return 1 - 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/}" - else - return 1 - fi -} - -# Gets the repository root. -function git-root() { - git rev-parse --show-toplevel -} - -# 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" - else - return 1 - 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}" - else - return 1 - 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}" - else - return 1 - fi -} - -# Gets the status of the working tree. -function git-prompt-status() { - local indicators line untracked added modified renamed deleted unmerged - - if ! git rev-parse &>/dev/null; then - return 1 - fi - - while IFS=$'\n' read line; do - if [[ "$line" == \?\?\ * ]] && ! check-bool "$untracked"; then - untracked='yes' - indicators="${ZSH_THEME_GIT_PROMPT_UNTRACKED}${indicators}" - fi - if [[ "$line" == (((A|M|D|T) )|(AD|AM|AT|MM))\ * ]] && ! check-bool "$added"; then - added='yes' - indicators="${ZSH_THEME_GIT_PROMPT_ADDED}${indicators}" - fi - if [[ "$line" == (( (M|T))|(AM|AT|MM))\ * ]] && ! check-bool "$modified"; then - modified='yes' - indicators="${ZSH_THEME_GIT_PROMPT_MODIFIED}${indicators}" - fi - if [[ "$line" == R\ \ * ]] && ! check-bool "$renamed"; then - renamed='yes' - indicators="${ZSH_THEME_GIT_PROMPT_RENAMED}${indicators}" - fi - if [[ "$line" == ( D|AD)\ * ]] && ! check-bool "$deleted"; then - deleted='yes' - indicators="${ZSH_THEME_GIT_PROMPT_DELETED}${indicators}" - fi - if [[ "$line" == UU\ * ]] && ! check-bool "$unmerged"; then - unmerged='yes' - indicators="${ZSH_THEME_GIT_PROMPT_UNMERGED}${indicators}" - fi - done < <(git status --porcelain 2> /dev/null) - - if [[ -n "$indicators" ]]; then - echo $indicators - fi -} - -# Open the GitHub repository in the browser. -function git-hub() { - local url=$( - git config -l \ - | grep "remote.origin.url" \ - | sed -En "s/remote.origin.url=(git|https?)(@|:\/\/)github.com(:|\/)(.+)\/(.+).git/https:\/\/github.com\/\4\/\5/p" - ) - - if [[ -n "$url" ]]; then - url="${url}/tree/${$(git-current-branch):-master}" - - if (( $+commands[$BROWSER] )); then - "$BROWSER" "$url" - else - echo "fatal: Browser not set or set to a non-existent browser." >&2 - return 1 - fi - else - echo "fatal: Not a Git repository or origin remote not set." >&2 - return 1 - fi -} - -# Git -alias g='git' -compdef g=git - -# Working Copy (w) -alias gws='git status --short' -compdef _git gws=git-status -alias gwS='git status' -compdef _git gwS=git-status -alias gwd='git diff --no-ext-diff' -compdef _git gwd=git-diff -function gwD() { git diff --no-ext-diff --ignore-all-space "$@" | view - } -compdef _git gwD=git-diff -alias gwr='git reset --soft' -compdef _git gwr=git-reset -alias gwR='git reset --hard' -compdef _git gwR=git-reset -alias gwc='git clean -n' -compdef _git gwc=git-clean -alias gwC='git clean -f' -compdef _git gwC=git-clean -alias gwx='git rm -r' -compdef _git gwx=git-rm -alias gwX='git rm -rf' -compdef _git gwX=git-rm - -# Index -alias gia='git add' -compdef _git gia=git-add -alias giA='git add --patch' -compdef _git giA=git-add -alias giu='git add --update' -compdef _git giu=git-add -alias gid='git diff --no-ext-diff --cached' -compdef _git gid=git-diff -alias gir='git reset' -compdef _git gir=git-reset -alias giR='git reset --mixed' -compdef _git giR=git-reset -alias gix='git rm -r --cached' -compdef _git gix=git-rm -alias giX='git rm -rf --cached' -compdef _git giX=git-rm - -# Branah (b) -alias gb='git branch' -compdef _git gb=git-branch -alias gbc='git checkout -b' -compdef _git gbc=git-checkout -alias gbl='git branch -v' -compdef _git gbl=git-branch -alias gbL='git branch -av' -compdef _git gbL=git-branch -alias gbx='git branch -d' -compdef _git gbx=git-branch -alias gbX='git branch -D' -compdef _git gbX=git-branch -alias gbm='git branch -m' -compdef _git gbm=git-branch -alias gbM='git branch -M' -compdef _git gbM=git-branch - -# Commit (c) -alias gc='git commit' -compdef _git gc=git-commit -alias gca='git commit --all' -compdef _git gca=git-commit -alias gcm='git commit --message' -compdef _git gcm=git-commit -alias gco='git checkout' -compdef _git gco=git-checkout -alias gcO='git checkout HEAD --' -compdef _git gcO=git-checkout -alias gcf='git commit --amend --reuse-message HEAD' -compdef _git gcf=git-commit -alias gcp='git cherry-pick' -compdef _git gcp=git-cherry-pick -alias gcr='git revert' -compdef _git gcr=git-revert -alias gcR='git reset "HEAD^"' -compdef _git gcR=git-reset -alias gcs='git show' -compdef _git gcs=git-show -alias gcv='git fsck | awk '\''/dangling commit/ {print $3}'\'' | git show --format="SHA1: %C(green)%h%C(reset) %f" --stdin | awk '\''/SHA1/ {sub("SHA1: ", ""); print}'\''' - -# Conflict (k) -alias gkl='git status | sed -n "s/^.*both [a-z]*ed: *//p"' -alias gka='git add $(gkl)' -compdef _git gka=git-add -alias gke='git mergetool $(gkl)' -alias gko='git checkout --ours --' -compdef _git gko=git-checkout -alias gkO='gko $(gkl)' -alias gkt='git checkout --theirs --' -compdef _git gkt=git-checkout -alias gkT='gkt $(gkl)' - -# File Data (d) -alias gd='git ls-files' -compdef _git gd=git-ls-files -alias gdc='git ls-files --cached' -compdef _git gdc=git-ls-files -alias gdx='git ls-files --deleted' -compdef _git gdx=git-ls-files -alias gdm='git ls-files --modified' -compdef _git gdm=git-ls-files -alias gdu='git ls-files --others' -compdef _git gdu=git-ls-files -alias gdk='git ls-files --killed' -compdef _git gdk=git-ls-files -alias gdi='git status --porcelain --short --ignored | sed -n "s/^!! //p"' - -# Merge (m) -alias gm='git merge --no-ff' -compdef _git gm=git-merge -alias gmf='git merge --ff' -compdef _git gmf=git-merge -alias gma='git merge --abort' -compdef _git gma=git-merge - -# Pull -alias gf='git fetch' -compdef _git gf=git-fetch -alias gfc='git clone' -compdef _git gfc=git-clone -alias gfm='git pull' -compdef _git gfm=git-pull -alias gfr='git pull --rebase' -compdef _git gfr=git-pull - -# Push -alias gp='git push' -compdef _git gp=git-push -alias gpf='git push --force' -compdef _git gpf=git-push -alias gpa='git push --all' -compdef _git gpa=git-push -alias gpA='git push --all && git push --tags' -compdef _git gpA=git-push -alias gpt='git push --tags' -compdef _git gpt=git-push -alias gpc='git push --set-upstream origin $(git-current-branch)' -compdef _git gpc=git-push -alias gpp='git pull origin $(git-current-branch) && git push origin $(git-current-branch)' - -# Rebase (r) -alias gr='git rebase' -compdef _git gr=git-rebase -alias gra='git rebase --abort' -compdef _git gra=git-rebase -alias grc='git rebase --continue' -compdef _git grc=git-rebase -alias gri='git rebase --interactive' -compdef _git gri=git-rebase -alias grs='git rebase --skip' -compdef _git grs=git-rebase - -# Remote Host (h) -alias gh='git remote' -compdef _git gh=git-remote -alias ghl='git remote --verbose' -compdef _git ghl=git-remote -alias gha='git remote add' -compdef _git gha=git-remote -alias ghx='git remote rm' -compdef _git ghx=git-remote -alias ghm='git remote rename' -compdef _git ghm=git-remote -alias ghu='git remote update' -compdef _git ghu=git-remote -alias ghc='git remote prune' -compdef _git ghc=git-remote -alias ghs='git remote show' -compdef _git ghs=git-remote - -# Stash (t) -alias gta='git stash apply' -compdef _git gta=git-stash -alias gtc='git stash clear' -compdef _git gtc=git-stash -alias gtx='git stash drop' -compdef _git gtx=git-stash -alias gtl='git stash list' -compdef _git gtl=git-stash -alias gtL='git stash show --patch --stat' -compdef _git gtL=git-stash -alias gtp='git stash pop' -compdef _git gtp=git-stash -alias gts='git stash save' -compdef _git gts=git-stash - -# Submodule (u) -alias gu='git submodule' -compdef _git gu=git-submodule -alias gua='git submodule add' -compdef _git gua=git-submodule -alias guf='git submodule foreach' -compdef _git guf=git-submodule -alias gui='git submodule init' -compdef _git gui=git-submodule -alias gul='git submodule status' -compdef _git gul=git-submodule -alias gus='git submodule sync' -compdef _git gus=git-submodule -alias guu='git submodule update' -compdef _git guu=git-submodule -alias guU='git submodule update --init --recursive' -compdef _git guU=git-submdoule - -# Git log (pretty). -git_log_format_oneline='--pretty=format:%C(green)%h%C(reset) %s%C(red)%d%C(reset)' -git_log_format_oneline_more='--pretty=format:%C(green)%h%C(reset) %C(blue)%ad%C(reset) %s%C(red)%d%C(reset) [%C(magenta)%an%C(reset)]' -git_log_format_medium='--pretty=format:%C(green)Commit: %H%C(red)%d%C(reset)%n%C(magenta)Author: %an <%ae>%C(reset)%n%C(blue)Date: %cd%C(reset)%n%+s%n%+b' - -alias gl='git log' -compdef _git gl=git-log -alias glo='git log --topo-order ${git_log_format_oneline}' -compdef _git glo=git-log -alias glO='git log --topo-order --date=short ${git_log_format_oneline_more}' -compdef _git glO=git-log -alias glg='git log --graph --topo-order ${git_log_format_medium}' -compdef _git glg=git-log -alias gls='git log --graph --topo-order --stat ${git_log_format_medium}' -compdef _git gls=git-log -alias gld='git log --graph --topo-order --stat --patch --full-diff ${git_log_format_medium}' -compdef _git gld=git-log -alias glc='git shortlog --summary --numbered' -compdef _git glc=git-shortlog +# ------------------------------------------------------------------------------ +# FILE: git.plugin.zsh +# DESCRIPTION: oh-my-zsh plugin file. +# AUTHOR: Sorin Ionescu +# VERSION: 1.0.0 +# ------------------------------------------------------------------------------ + +# Source plugin files. +source "${0:h}/utility.zsh" +source "${0:h}/alias.zsh" +source "${0:h}/info.zsh" +source "${0:h}/completion.zsh" diff --git a/plugins/git/info.zsh b/plugins/git/info.zsh new file mode 100644 index 00000000..34e267bc --- /dev/null +++ b/plugins/git/info.zsh @@ -0,0 +1,357 @@ +# The default styles. +zstyle ':git-info:' action 'action:%s' # %s - Special action name (am, merge, rebase). +zstyle ':git-info:' added 'added:%a' # %a - Indicator to notify of added files. +zstyle ':git-info:' ahead 'ahead:%A' # %A - Indicator to notify of ahead branch. +zstyle ':git-info:' behind 'behind:%B' # %B - Indicator to notify of behind branch. +zstyle ':git-info:' branch '%b' # %b - Branch name. +zstyle ':git-info:' clean 'clean' # %C - Indicator to notify of clean branch. +zstyle ':git-info:' commit 'commit:%c' # %c - SHA-1 hash. +zstyle ':git-info:' deleted 'deleted:%d' # %d - Indicator to notify of deleted files. +zstyle ':git-info:' dirty 'dirty' # %D - Indicator to notify of dirty branch. +zstyle ':git-info:' modified 'modified:%m' # %m - Indicator to notify of modified files. +zstyle ':git-info:' remote '%R' # %R - Remote name. +zstyle ':git-info:' renamed 'renamed:%r' # %r - Indicator to notify of renamed files. +zstyle ':git-info:' stashed 'stashed:%S' # %S - Indicator to notify of stashed files. +zstyle ':git-info:' unmerged 'unmerged:%U' # %U - Indicator to notify of unmerged files. +zstyle ':git-info:' untracked 'untracked:%u' # %u - Indicator to notify of untracked files. +zstyle ':git-info:' prompt ' git:(%b %D%C)' # Left prompt. +zstyle ':git-info:' rprompt '' # Right prompt. + +# Gets the Git special action (am, merge, rebase, etc.). +# Borrowed from vcs_info and edited. +function _git-action() { + local action='' + local action_dir + local git_dir="$(git-root)/.git" + + for action_dir in \ + "${git_dir}/rebase-apply" \ + "${git_dir}/rebase" \ + "${git_dir}/../.dotest"; do + if [[ -d "$action_dir" ]] ; then + if [[ -f "${action_dir}/rebasing" ]] ; then + action='rebase' + elif [[ -f "${action_dir}/applying" ]] ; then + action='am' + else + action='am/rebase' + fi + echo "$action" + return 0 + fi + done + + for action_dir in \ + "${git_dir}/rebase-merge/interactive" \ + "${git_dir}/.dotest-merge/interactive"; do + if [[ -f "$action_dir" ]]; then + echo 'rebase-i' + return 0 + fi + done + + for action_dir in \ + "${git_dir}/rebase-merge" \ + "${git_dir}/.dotest-merge"; do + if [[ -d "$action_dir" ]]; then + echo 'rebase-m' + return 0 + fi + done + + if [[ -f "${git_dir}/MERGE_HEAD" ]]; then + echo 'merge' + return 0 + fi + + if [[ -f "${git_dir}/CHERRY_PICK_HEAD" ]]; then + echo 'cherry-pick' + return 0 + fi + + if [[ -f "${git_dir}/BISECT_LOG" ]]; then + echo 'bisect' + return 0 + fi + + return 1 +} + +# Turns off git-info for the current repository. +function _git-info-abort() { + if ! check-bool "$_git_info_executing"; then + return 1 + fi + + cat > /dev/stderr < /dev/null)"; then + return 1 + fi + + if (( $# > 0 )); then + if [[ "$1" == [Oo][Nn] ]]; then + git config --bool prompt.showinfo true + elif [[ "$1" == [Oo][Ff][Ff] ]]; then + git config --bool prompt.showinfo false + else + echo "Usage: $0 [ on | off ]" + fi + return 0 + fi + + # Return if git-info is disabled. + if ! check-bool "${$(git config --bool prompt.showinfo):-true}"; then + return 1 + fi + + # Used to abort and turn git-info off on SIGINT. + _git_info_executing=true + + # Get commit. + commit="$(git rev-parse HEAD 2> /dev/null)" + + # Format commit (short). + commit_short="$commit[1,7]" + zstyle -s ':git-info:' commit commit_format + zformat -f commit_formatted "$commit_format" "c:$commit_short" + + # Stashed + if [[ -f "$(git-root)/.git/refs/stash" ]]; then + stashed="$(git stash list 2>/dev/null | wc -l)" + zstyle -s ':git-info:' stashed stashed_format + zformat -f stashed_formatted "$stashed_format" "S:$stashed" + fi + + # Assume that the working copy is clean. + zstyle -s ':git-info:' clean clean_formatted + + while IFS=$'\n' read line; do + (( line_number++ )) + + if (( line_number == 1)) && [[ "$line" == *'(no branch)'* ]]; then + # Set branch to commit (short) when the branch is not found. + branch="$commit_short" + + # Get action. + action="$(_git-action)" + if [[ -n "$action" ]]; then + zstyle -s ':git-info:' action action_format + zformat -f action_formatted "$action_format" "s:$action" + fi + elif (( line_number == 1 )) \ + && [[ "$line" == (#b)'## Initial commit on '(?##) ]]; then + branch="$match[1]" + elif (( line_number == 1 )); then + # Split the line into an array for parsing. + branch_info=(${(s: :)line}) + + # Match: master...origin/master + if [[ $branch_info[2] == (#b)(?##)...(?##/?##) ]]; then + branch="$match[1]" + remote="$match[2]" + + # Match: [ahead or [behind + if [[ $branch_info[3] == (#b)\[(ahead|behind) ]]; then + ahead_or_behind="$match[1]" + if [[ "$ahead_or_behind" == 'behind' ]]; then + # Extract digits: 10] + behind="${branch_info[4]%\]}" + else + # Extract digits: 10] or 10, + ahead="${branch_info[4]%[,\]]}" + # Extract digits: 10] + behind="${branch_info[6]%\]}" + fi + fi + # Match: master + elif [[ $branch_info[2] == (#b)(?##) ]]; then + branch=$match[1] + fi + else + # Format dirty. + [[ -z "$dirty" ]] && zstyle -s ':git-info:' dirty dirty_formatted && unset clean_formatted + + # Count: added/deleted/modified/renamed/unmerged/untracked + [[ "$line" == (((A|M|D|T) )|(AD|AM|AT|MM))\ * ]] && (( added++ )) + [[ "$line" == ( D|AD)\ * ]] && (( deleted++ )) + [[ "$line" == (( (M|T))|(AM|AT|MM))\ * ]] && (( modified++ )) + [[ "$line" == R\ \ * ]] && (( renamed++ )) + [[ "$line" == UU\ * ]] && (( unmerged++ )) + [[ "$line" == \?\?\ * ]] && (( untracked++ )) + fi + done < <(git status --short --branch 2> /dev/null) + + # Format branch. + zstyle -s ':git-info:' branch branch_format + zformat -f branch_formatted "$branch_format" "b:$branch" + + # Format remote. + if [[ "$branch" != "$commit" ]]; then + [[ -z $remote ]] \ + && remote=${$(git rev-parse --verify ${branch}@{upstream} \ + --symbolic-full-name 2> /dev/null)#refs/remotes/} + zstyle -s ':git-info:' remote remote_format + zformat -f remote_formatted "$remote_format" "R:$remote" + fi + + # Format ahead. + if [[ -n "$ahead" ]]; then + zstyle -s ':git-info:' ahead ahead_format + zformat -f ahead_formatted "$ahead_format" "A:$ahead" + fi + + # Format behind. + if [[ -n "$behind" ]]; then + zstyle -s ':git-info:' behind behind_format + zformat -f behind_formatted "$behind_format" "B:$behind" + fi + + # Format added. + if (( $added > 0 )); then + zstyle -s ':git-info:' added added_format + zformat -f added_formatted "$added_format" "a:$added_format" + fi + + # Format deleted. + if (( $deleted > 0 )); then + zstyle -s ':git-info:' deleted deleted_format + zformat -f deleted_formatted "$deleted_format" "d:$deleted_format" + fi + + # Format modified. + if (( $modified > 0 )); then + zstyle -s ':git-info:' modified modified_format + zformat -f modified_formatted "$modified_format" "m:$modified" + fi + + # Format renamed. + if (( $renamed > 0 )); then + zstyle -s ':git-info:' renamed renamed_format + zformat -f renamed_formatted "$renamed_format" "r:$renamed" + fi + + # Format unmerged. + if (( $unmerged > 0 )); then + zstyle -s ':git-info:' unmerged unmerged_format + zformat -f unmerged_formatted "$unmerged_format" "U:$unmerged" + fi + + # Format untracked. + if (( $untracked > 0 )); then + zstyle -s ':git-info:' untracked untracked_format + zformat -f untracked_formatted "$untracked_format" "u:$untracked" + fi + + # Format prompts. + zstyle -s ':git-info:' prompt prompt_format + zstyle -s ':git-info:' rprompt rprompt_format + + git_info_vars=( + git_prompt_info "$prompt_format" + git_rprompt_info "$rprompt_format" + ) + + for git_info_var in ${(k)git_info_vars}; do + zformat -f $git_info_var $git_info_vars[$git_info_var] \ + "s:$action_formatted" \ + "a:$added_formatted" \ + "A:$ahead_formatted" \ + "B:$behind_formatted" \ + "b:$branch_formatted" \ + "C:$clean_formatted" \ + "c:$commit_formatted" \ + "d:$deleted_formatted" \ + "D:$dirty_formatted" \ + "m:$modified_formatted" \ + "R:$remote_formatted" \ + "r:$renamed_formatted" \ + "S:$stashed_formatted" \ + "U:$unmerged_formatted" \ + "u:$untracked_formatted" + done + + unset _git_info_executing + return 0 +} + diff --git a/plugins/git/utility.zsh b/plugins/git/utility.zsh new file mode 100644 index 00000000..c50fc55f --- /dev/null +++ b/plugins/git/utility.zsh @@ -0,0 +1,46 @@ +# Gets the current branch. +function git-branch() { + local ref="$(git symbolic-ref HEAD 2> /dev/null)" + if [[ -n "$ref" ]]; then + echo "${ref#refs/heads/}" + return 0 + else + return 1 + fi +} + +# Gets the repository root. +function git-root() { + local root="$(git rev-parse --show-toplevel 2> /dev/null)" + if [[ -n "$root" ]]; then + echo "$root" + return 0 + else + return 1 + fi +} + +# Open the GitHub repository in the browser. +function git-hub() { + local url=$( + git config -l \ + | grep "remote.origin.url" \ + | sed -En "s/remote.origin.url=(git|https?)(@|:\/\/)github.com(:|\/)(.+)\/(.+).git/https:\/\/github.com\/\4\/\5/p" + ) + + if [[ -n "$url" ]]; then + url="${url}/tree/${$(git-branch):-master}" + + if (( $+commands[$BROWSER] )); then + "$BROWSER" "$url" + return 0 + else + echo "fatal: Browser not set or set to a non-existent browser." >&2 + return 1 + fi + else + echo "fatal: Not a Git repository or origin remote not set." >&2 + return 1 + fi +} + diff --git a/themes/sorin/prompt_sorin_setup b/themes/sorin/prompt_sorin_setup index 72e8a96a..e254a948 100644 --- a/themes/sorin/prompt_sorin_setup +++ b/themes/sorin/prompt_sorin_setup @@ -2,32 +2,43 @@ # FILE: prompt_sorin_setup # DESCRIPTION: oh-my-zsh theme file. # AUTHOR: Sorin Ionescu -# VERSION: 1.0.4 +# VERSION: 1.0.5 # SCREENSHOT: http://i.imgur.com/aipDQ.png # ------------------------------------------------------------------------------ +function prompt_sorin_precmd () { + setopt noxtrace noksharrays localoptions + if (( $+functions[git-info] )); then + git-info + fi +} function prompt_sorin_setup() { setopt localoptions noxtrace noksharrays prompt_opts=(cr subst percent) - + + autoload -Uz add-zsh-hook + add-zsh-hook precmd prompt_sorin_precmd + MODE_INDICATOR="%B%F{red}❮%f%b%F{red}❮❮%f" - ZSH_THEME_GIT_PROMPT_SHA_BEFORE="" - ZSH_THEME_GIT_PROMPT_SHA_AFTER="" - ZSH_THEME_GIT_PROMPT_AHEAD="" - ZSH_THEME_GIT_PROMPT_DIRTY="" - ZSH_THEME_GIT_PROMPT_CLEAN="" - ZSH_THEME_GIT_PROMPT_PREFIX=" %F{blue}git%f:%F{red}" - ZSH_THEME_GIT_PROMPT_SUFFIX="%f" - ZSH_THEME_GIT_PROMPT_ADDED="%F{green} ✚%f" - ZSH_THEME_GIT_PROMPT_MODIFIED="%F{blue} ✹%f" - ZSH_THEME_GIT_PROMPT_DELETED="%F{red} ✖%f" - ZSH_THEME_GIT_PROMPT_RENAMED="%F{magenta} ➜%f" - ZSH_THEME_GIT_PROMPT_UNMERGED="%F{yellow} ═%f" - ZSH_THEME_GIT_PROMPT_UNTRACKED="%F{cyan} ✭%f" + zstyle ':git-info:' action ':%%B%F{yellow}%s%f%%b' + zstyle ':git-info:' added ' %%B%F{green}✚%f%%b' + zstyle ':git-info:' ahead ' %%B%F{yellow}⬆%f%%b' + zstyle ':git-info:' behind ' %%B%F{yellow}⬇%f%%b' + zstyle ':git-info:' branch ':%F{red}%b%f' + zstyle ':git-info:' deleted ' %%B%F{red}✖%f%%b' + zstyle ':git-info:' modified ' %%B%F{blue}✹%f%%b' + zstyle ':git-info:' renamed ' %%B%F{magenta}➜%f%%b' + zstyle ':git-info:' commit '%c' + zstyle ':git-info:' stashed ' %%B%F{white}✭%f%%b' + zstyle ':git-info:' unmerged ' %%B%F{yellow}═%f%%b' + zstyle ':git-info:' untracked ' %%B%F{cyan}•%f%%b' + zstyle ':git-info:' prompt ' %F{blue}git%f%b%s' + zstyle ':git-info:' rprompt '%A%B%S%a%d%m%r%U%u' - PROMPT='%F{cyan}%~%f$(git-prompt-info) %(!.%B%F{red}#%f%b.%B%F{green}❯%f%b) ' - RPROMPT='%(?::%F{red}⏎%f)$(git-prompt-status)' + PROMPT='%F{cyan}%1~%f${git_prompt_info} %(!.%B%F{red}#%f%b.%B%F{green}❯%f%b) ' + RPROMPT='%(?::%F{red}⏎%f)${git_rprompt_info}' + SPROMPT='zsh: correct %F{red}%R%f to %F{green}%r%f [nyae]? ' } prompt_sorin_setup "$@"