| 1 | ## |
| 2 | # bash completion support for tig |
| 3 | # |
| 4 | # Copyright (C) 2007 Jonas fonseca |
| 5 | # Copyright (C) 2006,2007 Shawn Pearce |
| 6 | # |
| 7 | # Based git's git-completion.sh: http://repo.or.cz/w/git/fastimport.git |
| 8 | # |
| 9 | # The contained completion routines provide support for completing: |
| 10 | # |
| 11 | # *) local and remote branch names |
| 12 | # *) local and remote tag names |
| 13 | # *) tig 'subcommands' |
| 14 | # *) tree paths within 'ref:path/to/file' expressions |
| 15 | # |
| 16 | # To use these routines: |
| 17 | # |
| 18 | # 1) Copy this file to somewhere (e.g. ~/.tig-completion.sh). |
| 19 | # 2) Added the following line to your .bashrc: |
| 20 | # source ~/.tig-completion.sh |
| 21 | # |
| 22 | # 3) You may want to make sure the git executable is available |
| 23 | # in your PATH before this script is sourced, as some caching |
| 24 | # is performed while the script loads. If git isn't found |
| 25 | # at source time then all lookups will be done on demand, |
| 26 | # which may be slightly slower. |
| 27 | # |
| 28 | |
| 29 | __tigdir () |
| 30 | { |
| 31 | if [ -z "$1" ]; then |
| 32 | if [ -n "$__git_dir" ]; then |
| 33 | echo "$__git_dir" |
| 34 | elif [ -d .git ]; then |
| 35 | echo .git |
| 36 | else |
| 37 | git rev-parse --git-dir 2>/dev/null |
| 38 | fi |
| 39 | elif [ -d "$1/.git" ]; then |
| 40 | echo "$1/.git" |
| 41 | else |
| 42 | echo "$1" |
| 43 | fi |
| 44 | } |
| 45 | |
| 46 | tigcomp () |
| 47 | { |
| 48 | local all c s=$'\n' IFS=' '$'\t'$'\n' |
| 49 | local cur="${COMP_WORDS[COMP_CWORD]}" |
| 50 | if [ $# -gt 2 ]; then |
| 51 | cur="$3" |
| 52 | fi |
| 53 | for c in $1; do |
| 54 | case "$c$4" in |
| 55 | --*=*) all="$all$c$4$s" ;; |
| 56 | *.) all="$all$c$4$s" ;; |
| 57 | *) all="$all$c$4 $s" ;; |
| 58 | esac |
| 59 | done |
| 60 | IFS=$s |
| 61 | COMPREPLY=($(compgen -P "$2" -W "$all" -- "$cur")) |
| 62 | return |
| 63 | } |
| 64 | |
| 65 | __tig_refs () |
| 66 | { |
| 67 | local cmd i is_hash=y dir="$(__tigdir "$1")" |
| 68 | if [ -d "$dir" ]; then |
| 69 | if [ -e "$dir/HEAD" ]; then echo HEAD; fi |
| 70 | for i in $(git --git-dir="$dir" \ |
| 71 | for-each-ref --format='%(refname)' \ |
| 72 | refs/tags refs/heads refs/remotes); do |
| 73 | case "$i" in |
| 74 | refs/tags/*) echo "${i#refs/tags/}" ;; |
| 75 | refs/heads/*) echo "${i#refs/heads/}" ;; |
| 76 | refs/remotes/*) echo "${i#refs/remotes/}" ;; |
| 77 | *) echo "$i" ;; |
| 78 | esac |
| 79 | done |
| 80 | return |
| 81 | fi |
| 82 | for i in $(git-ls-remote "$dir" 2>/dev/null); do |
| 83 | case "$is_hash,$i" in |
| 84 | y,*) is_hash=n ;; |
| 85 | n,*^{}) is_hash=y ;; |
| 86 | n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}" ;; |
| 87 | n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;; |
| 88 | n,refs/remotes/*) is_hash=y; echo "${i#refs/remotes/}" ;; |
| 89 | n,*) is_hash=y; echo "$i" ;; |
| 90 | esac |
| 91 | done |
| 92 | } |
| 93 | |
| 94 | __tig_complete_file () |
| 95 | { |
| 96 | local pfx ls ref cur="${COMP_WORDS[COMP_CWORD]}" |
| 97 | case "$cur" in |
| 98 | ?*:*) |
| 99 | ref="${cur%%:*}" |
| 100 | cur="${cur#*:}" |
| 101 | case "$cur" in |
| 102 | ?*/*) |
| 103 | pfx="${cur%/*}" |
| 104 | cur="${cur##*/}" |
| 105 | ls="$ref:$pfx" |
| 106 | pfx="$pfx/" |
| 107 | ;; |
| 108 | *) |
| 109 | ls="$ref" |
| 110 | ;; |
| 111 | esac |
| 112 | COMPREPLY=($(compgen -P "$pfx" \ |
| 113 | -W "$(git --git-dir="$(__tigdir)" ls-tree "$ls" \ |
| 114 | | sed '/^100... blob /s,^.* ,, |
| 115 | /^040000 tree /{ |
| 116 | s,^.* ,, |
| 117 | s,$,/, |
| 118 | } |
| 119 | s/^.* //')" \ |
| 120 | -- "$cur")) |
| 121 | ;; |
| 122 | *) |
| 123 | tigcomp "$(__tig_refs)" |
| 124 | ;; |
| 125 | esac |
| 126 | } |
| 127 | |
| 128 | __tig_complete_revlist () |
| 129 | { |
| 130 | local pfx cur="${COMP_WORDS[COMP_CWORD]}" |
| 131 | case "$cur" in |
| 132 | *...*) |
| 133 | pfx="${cur%...*}..." |
| 134 | cur="${cur#*...}" |
| 135 | tigcomp "$(__tig_refs)" "$pfx" "$cur" |
| 136 | ;; |
| 137 | *..*) |
| 138 | pfx="${cur%..*}.." |
| 139 | cur="${cur#*..}" |
| 140 | tigcomp "$(__tig_refs)" "$pfx" "$cur" |
| 141 | ;; |
| 142 | *.) |
| 143 | tigcomp "$cur." |
| 144 | ;; |
| 145 | *) |
| 146 | tigcomp "$(__tig_refs)" |
| 147 | ;; |
| 148 | esac |
| 149 | } |
| 150 | |
| 151 | _tig_diff () |
| 152 | { |
| 153 | __tig_complete_file |
| 154 | } |
| 155 | |
| 156 | _tig_log () |
| 157 | { |
| 158 | local cur="${COMP_WORDS[COMP_CWORD]}" |
| 159 | case "$cur" in |
| 160 | --pretty=*) |
| 161 | tigcomp " |
| 162 | oneline short medium full fuller email raw |
| 163 | " "" "${cur##--pretty=}" |
| 164 | return |
| 165 | ;; |
| 166 | --*) |
| 167 | tigcomp " |
| 168 | --max-count= --max-age= --since= --after= |
| 169 | --min-age= --before= --until= |
| 170 | --root --not --topo-order --date-order |
| 171 | --no-merges |
| 172 | --abbrev-commit --abbrev= |
| 173 | --relative-date |
| 174 | --author= --committer= --grep= |
| 175 | --all-match |
| 176 | --pretty= --name-status --name-only |
| 177 | --not --all |
| 178 | " |
| 179 | return |
| 180 | ;; |
| 181 | esac |
| 182 | __tig_complete_revlist |
| 183 | } |
| 184 | |
| 185 | _tig_show () |
| 186 | { |
| 187 | local cur="${COMP_WORDS[COMP_CWORD]}" |
| 188 | case "$cur" in |
| 189 | --pretty=*) |
| 190 | tigcomp " |
| 191 | oneline short medium full fuller email raw |
| 192 | " "" "${cur##--pretty=}" |
| 193 | return |
| 194 | ;; |
| 195 | --*) |
| 196 | tigcomp "--pretty=" |
| 197 | return |
| 198 | ;; |
| 199 | esac |
| 200 | __tig_complete_file |
| 201 | } |
| 202 | |
| 203 | _tig () |
| 204 | { |
| 205 | local i c=1 command __tig_dir |
| 206 | |
| 207 | while [ $c -lt $COMP_CWORD ]; do |
| 208 | i="${COMP_WORDS[c]}" |
| 209 | case "$i" in |
| 210 | --) command="log"; break;; |
| 211 | -*) ;; |
| 212 | *) command="$i"; break ;; |
| 213 | esac |
| 214 | c=$((++c)) |
| 215 | done |
| 216 | |
| 217 | if [ $c -eq $COMP_CWORD -a -z "$command" ]; then |
| 218 | case "${COMP_WORDS[COMP_CWORD]}" in |
| 219 | --*=*) COMPREPLY=() ;; |
| 220 | -*) __tigcomp " |
| 221 | --line-number= --tab-size= --version --help |
| 222 | -b -d -h -l -S -v |
| 223 | " ;; |
| 224 | *) __gitcomp "log diff show $(__tig_refs)" ;; |
| 225 | esac |
| 226 | return |
| 227 | fi |
| 228 | |
| 229 | case "$command" in |
| 230 | diff) _tig_diff ;; |
| 231 | show) _tig_show ;; |
| 232 | log) _tig_log ;; |
| 233 | *) tigcomp " |
| 234 | $(__tig_complete_file) |
| 235 | $(__tig_refs) |
| 236 | " ;; |
| 237 | esac |
| 238 | } |
| 239 | |
| 240 | complete -o default -o nospace -F _tig tig |
| 241 | |
| 242 | # The following are necessary only for Cygwin, and only are needed |
| 243 | # when the user has tab-completed the executable name and consequently |
| 244 | # included the '.exe' suffix. |
| 245 | if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then |
| 246 | complete -o default -o nospace -F _tig tig.exe |
| 247 | fi |