From c1ebea1e23c1cb5150dbf4631b33e029875833fe Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 14 Sep 2014 21:46:26 +0800 Subject: [PATCH] Add plugin: tig This plugin adds tig command completion for zsh --- plugins/tig/tig-completion.bash | 291 ++++++++++++++++++++++++++++++++ plugins/tig/tig.plugin.zsh | 1 + 2 files changed, 292 insertions(+) create mode 100755 plugins/tig/tig-completion.bash create mode 100755 plugins/tig/tig.plugin.zsh diff --git a/plugins/tig/tig-completion.bash b/plugins/tig/tig-completion.bash new file mode 100755 index 000000000..67303ec0a --- /dev/null +++ b/plugins/tig/tig-completion.bash @@ -0,0 +1,291 @@ +## +# bash completion support for tig +# +# Copyright (C) 2007-2010 Jonas fonseca +# Copyright (C) 2006,2007 Shawn Pearce +# +# Based git's git-completion.sh: http://repo.or.cz/w/git/fastimport.git +# +# The contained completion routines provide support for completing: +# +# *) local and remote branch names +# *) local and remote tag names +# *) tig 'subcommands' +# *) tree paths within 'ref:path/to/file' expressions +# +# To use these routines: +# +# 1) Copy this file to somewhere (e.g. ~/.tig-completion.sh). +# 2) Added the following line to your .bashrc: +# source ~/.tig-completion.sh +# +# 3) You may want to make sure the git executable is available +# in your PATH before this script is sourced, as some caching +# is performed while the script loads. If git isn't found +# at source time then all lookups will be done on demand, +# which may be slightly slower. +# + +__tigdir () +{ + if [ -z "$1" ]; then + if [ -n "$__git_dir" ]; then + echo "$__git_dir" + elif [ -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 +} + +_tigcomp () +{ + local all c s=$'\n' IFS=' '$'\t'$'\n' + local cur="${COMP_WORDS[COMP_CWORD]}" + if [ $# -gt 2 ]; then + cur="$3" + fi + for c in $1; do + case "$c$4" in + --*=*) all="$all$c$4$s" ;; + *.) all="$all$c$4$s" ;; + *) all="$all$c$4 $s" ;; + esac + done + IFS=$s + COMPREPLY=($(compgen -P "$2" -W "$all" -- "$cur")) + return +} + +__tig_refs () +{ + local cmd i is_hash=y dir="$(__tigdir "$1")" + if [ -d "$dir" ]; then + for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do + if [ -e "$dir/$i" ]; then echo $i; fi + done + for i in $(git --git-dir="$dir" \ + for-each-ref --format='%(refname)' \ + refs/tags refs/heads refs/remotes); do + case "$i" in + refs/tags/*) echo "${i#refs/tags/}" ;; + refs/heads/*) echo "${i#refs/heads/}" ;; + refs/remotes/*) echo "${i#refs/remotes/}" ;; + *) echo "$i" ;; + esac + done + return + fi + for i in $(git-ls-remote "$dir" 2>/dev/null); do + case "$is_hash,$i" in + y,*) is_hash=n ;; + n,*^{}) is_hash=y ;; + n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}" ;; + n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;; + n,refs/remotes/*) is_hash=y; echo "${i#refs/remotes/}" ;; + n,*) is_hash=y; echo "$i" ;; + esac + done +} + +__tig_complete_file () +{ + local pfx ls ref cur="${COMP_WORDS[COMP_CWORD]}" + case "$cur" in + ?*:*) + ref="${cur%%:*}" + cur="${cur#*:}" + case "$cur" in + ?*/*) + pfx="${cur%/*}" + cur="${cur##*/}" + ls="$ref:$pfx" + pfx="$pfx/" + ;; + *) + ls="$ref" + ;; + esac + COMPREPLY=($(compgen -P "$pfx" \ + -W "$(git --git-dir="$(__tigdir)" ls-tree "$ls" \ + | sed '/^100... blob /s,^.* ,, + /^040000 tree /{ + s,^.* ,, + s,$,/, + } + s/^.* //')" \ + -- "$cur")) + ;; + *) + _tigcomp "$(__tig_refs)" + ;; + esac +} + +__tig_complete_revlist () +{ + local pfx cur="${COMP_WORDS[COMP_CWORD]}" + case "$cur" in + *...*) + pfx="${cur%...*}..." + cur="${cur#*...}" + _tigcomp "$(__tig_refs)" "$pfx" "$cur" + ;; + *..*) + pfx="${cur%..*}.." + cur="${cur#*..}" + _tigcomp "$(__tig_refs)" "$pfx" "$cur" + ;; + *.) + _tigcomp "$cur." + ;; + *) + _tigcomp "$(__tig_refs)" + ;; + esac +} + +_tig_options () +{ + local cur="${COMP_WORDS[COMP_CWORD]}" + case "$cur" in + --pretty=*) + _tigcomp " + oneline short medium full fuller email raw + " "" "${cur##--pretty=}" + return + ;; + --*) + _tigcomp " + --max-count= --max-age= --since= --after= + --min-age= --before= --until= + --root --not --topo-order --date-order + --no-merges + --abbrev-commit --abbrev= + --relative-date + --author= --committer= --grep= + --all-match + --pretty= --name-status --name-only + --not --all + --help --version + " + return + ;; + -*) + _tigcomp "-v -h" + return + ;; + esac + __tig_complete_revlist +} + +_tig_blame () +{ + local reply="" ref=HEAD cur="${COMP_WORDS[COMP_CWORD]}" p="" + local pfx=$(git rev-parse --show-prefix 2>/dev/null) + + if test "$COMP_CWORD" -lt 3; then + _tigcomp "$(__tig_refs)" + else + ref="${COMP_WORDS[2]}" + fi + + case "$cur" in + */) p=${cur%/} ;; + */*) p=${cur%/*} ;; + *) p= ;; + esac + + i=${#COMPREPLY[@]} + local IFS=$'\n' + for c in $(git --git-dir="$(__tigdir)" ls-tree "$ref:$pfx$p" 2>/dev/null | + sed -n '/^100... blob /{ + s,^.* ,, + s,$, , + p + } + /^040000 tree /{ + s,^.* ,, + s,$,/, + p + }') + do + c="${p:+$p/}$c" + if [[ "$c" == "$cur"* ]]; then + COMPREPLY[i++]=$c + fi + done +} + +_tig_show () +{ + local cur="${COMP_WORDS[COMP_CWORD]}" + case "$cur" in + --pretty=*) + _tigcomp " + oneline short medium full fuller email raw + " "" "${cur##--pretty=}" + return + ;; + --*) + _tigcomp "--pretty=" + return + ;; + esac + __tig_complete_file +} + +_tig () +{ + local i c=1 command __tig_dir + + while [ $c -lt $COMP_CWORD ]; do + i="${COMP_WORDS[c]}" + case "$i" in + --) command="log"; break;; + -*) ;; + *) command="$i"; break ;; + esac + c=$((++c)) + done + + if [ $c -eq $COMP_CWORD -a -z "$command" ]; then + case "${COMP_WORDS[COMP_CWORD]}" in + --*=*) COMPREPLY=() ;; + -*) _tig_options ;; + *) _tigcomp "blame status show log stash grep $(__tig_refs)" ;; + esac + return + fi + + case "$command" in + blame) _tig_blame ;; + show) _tig_show ;; + status) ;; + *) _tigcomp " + $(__tig_complete_file) + $(__tig_refs) + " ;; + esac +} + +# Detect if current shell is ZSH, and if so, load this file in bash +# compatibility mode. +if [ -n "$ZSH_VERSION" ]; then + autoload bashcompinit + bashcompinit +fi + +complete -o default -o nospace -F _tig tig + +# The following are necessary only for Cygwin, and only are needed +# when the user has tab-completed the executable name and consequently +# included the '.exe' suffix. +if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then +complete -o default -o nospace -F _tig tig.exe +fi diff --git a/plugins/tig/tig.plugin.zsh b/plugins/tig/tig.plugin.zsh new file mode 100755 index 000000000..e3ab55109 --- /dev/null +++ b/plugins/tig/tig.plugin.zsh @@ -0,0 +1 @@ +source $(dirname $0)/tig-completion.bash