github.com/jingweno/gh@v2.1.1-0.20221007190738-04a7985fa9a1+incompatible/etc/gh.bash_completion.sh (about) 1 # hub tab-completion script for bash. 2 # This script complements the completion script that ships with git. 3 4 # Check that git tab completion is available 5 if declare -F _git > /dev/null; then 6 # Duplicate and rename the 'list_all_commands' function 7 eval "$(declare -f __git_list_all_commands | \ 8 sed 's/__git_list_all_commands/__git_list_all_commands_without_hub/')" 9 10 # Wrap the 'list_all_commands' function with extra hub commands 11 __git_list_all_commands() { 12 cat <<-EOF 13 alias 14 pull-request 15 fork 16 create 17 browse 18 compare 19 ci-status 20 release 21 issue 22 update 23 EOF 24 __git_list_all_commands_without_hub 25 } 26 27 # Ensure cached commands are cleared 28 __git_all_commands="" 29 30 ########################## 31 # hub command completions 32 ########################## 33 34 # hub alias [-s] [SHELL] 35 _git_alias() { 36 local i c=2 s=-s sh shells="bash zsh sh ksh csh fish" 37 while [ $c -lt $cword ]; do 38 i="${words[c]}" 39 case "$i" in 40 -s) 41 unset s 42 ;; 43 *) 44 for sh in $shells; do 45 if [ "$sh" = "$i" ]; then 46 unset shells 47 break 48 fi 49 done 50 ;; 51 esac 52 ((c++)) 53 done 54 __gitcomp "$s $shells" 55 } 56 57 # hub browse [-u] [--|[USER/]REPOSITORY] [SUBPAGE] 58 _git_browse() { 59 local i c=2 u=-u repo subpage 60 local subpages_="commits issues tree wiki pulls branches stargazers 61 contributors network network/ graphs graphs/" 62 local subpages_network="members" 63 local subpages_graphs="commit-activity code-frequency punch-card" 64 while [ $c -lt $cword ]; do 65 i="${words[c]}" 66 case "$i" in 67 -u) 68 unset u 69 ;; 70 *) 71 if [ -z "$repo" ]; then 72 repo=$i 73 else 74 subpage=$i 75 fi 76 ;; 77 esac 78 ((c++)) 79 done 80 if [ -z "$repo" ]; then 81 __gitcomp "$u -- $(__hub_github_repos '\p')" 82 elif [ -z "$subpage" ]; then 83 case "$cur" in 84 */*) 85 local pfx="${cur%/*}" cur_="${cur#*/}" 86 local subpages_var="subpages_$pfx" 87 __gitcomp "${!subpages_var}" "$pfx/" "$cur_" 88 ;; 89 *) 90 __gitcomp "$u ${subpages_}" 91 ;; 92 esac 93 else 94 __gitcomp "$u" 95 fi 96 } 97 98 # hub compare [-u] [USER[/REPOSITORY]] [[START...]END] 99 _git_compare() { 100 local i c=$((cword - 1)) u=-u user remote owner repo arg_repo rev 101 while [ $c -gt 1 ]; do 102 i="${words[c]}" 103 case "$i" in 104 -u) 105 unset u 106 ;; 107 *) 108 if [ -z "$rev" ]; then 109 # Even though the logic below is able to complete both user/repo 110 # and revision in the right place, when there is only one argument 111 # (other than -u) in the command, that argument will be taken as 112 # revision. For example: 113 # $ hub compare -u upstream 114 # > https://github.com/USER/REPO/compare/upstream 115 if __hub_github_repos '\p' | grep -Eqx "^$i(/[^/]+)?"; then 116 arg_repo=$i 117 else 118 rev=$i 119 fi 120 elif [ -z "$arg_repo" ]; then 121 arg_repo=$i 122 fi 123 ;; 124 esac 125 ((c--)) 126 done 127 128 # Here we want to find out the git remote name of user/repo, in order to 129 # generate an appropriate revision list 130 if [ -z "$arg_repo" ]; then 131 user=$(__hub_github_user) 132 if [ -z "$user" ]; then 133 for i in $(__hub_github_repos); do 134 remote=${i%%:*} 135 repo=${i#*:} 136 if [ "$remote" = origin ]; then 137 break 138 fi 139 done 140 else 141 for i in $(__hub_github_repos); do 142 remote=${i%%:*} 143 repo=${i#*:} 144 owner=${repo%%/*} 145 if [ "$user" = "$owner" ]; then 146 break 147 fi 148 done 149 fi 150 else 151 for i in $(__hub_github_repos); do 152 remote=${i%%:*} 153 repo=${i#*:} 154 owner=${repo%%/*} 155 case "$arg_repo" in 156 "$repo"|"$owner") 157 break 158 ;; 159 esac 160 done 161 fi 162 163 local pfx cur_="$cur" 164 case "$cur_" in 165 *..*) 166 pfx="${cur_%%..*}..." 167 cur_="${cur_##*..}" 168 __gitcomp_nl "$(__hub_revlist $remote)" "$pfx" "$cur_" 169 ;; 170 *) 171 if [ -z "${arg_repo}${rev}" ]; then 172 __gitcomp "$u $(__hub_github_repos '\o\n\p') $(__hub_revlist $remote)" 173 elif [ -z "$rev" ]; then 174 __gitcomp "$u $(__hub_revlist $remote)" 175 else 176 __gitcomp "$u" 177 fi 178 ;; 179 esac 180 } 181 182 # hub create [NAME] [-p] [-d DESCRIPTION] [-h HOMEPAGE] 183 _git_create() { 184 local i c=2 name repo flags="-p -d -h" 185 while [ $c -lt $cword ]; do 186 i="${words[c]}" 187 case "$i" in 188 -d|-h) 189 ((c++)) 190 flags=${flags/$i/} 191 ;; 192 -p) 193 flags=${flags/$i/} 194 ;; 195 *) 196 name=$i 197 ;; 198 esac 199 ((c++)) 200 done 201 if [ -z "$name" ]; then 202 repo=$(basename "$(pwd)") 203 fi 204 case "$prev" in 205 -d|-h) 206 COMPREPLY=() 207 ;; 208 -p|*) 209 __gitcomp "$repo $flags" 210 ;; 211 esac 212 } 213 214 # hub fork [--no-remote] 215 _git_fork() { 216 local i c=2 remote=yes 217 while [ $c -lt $cword ]; do 218 i="${words[c]}" 219 case "$i" in 220 --no-remote) 221 unset remote 222 ;; 223 esac 224 ((c++)) 225 done 226 if [ -n "$remote" ]; then 227 __gitcomp "--no-remote" 228 fi 229 } 230 231 # hub pull-request [-f] [-m <MESSAGE>|-F <FILE>|-i <ISSUE>|<ISSUE-URL>] [-b <BASE>] [-h <HEAD>] 232 _git_pull_request() { 233 local i c=2 flags="-f -m -F -i -b -h" 234 while [ $c -lt $cword ]; do 235 i="${words[c]}" 236 case "$i" in 237 -m|-F|-i|-b|-h) 238 ((c++)) 239 flags=${flags/$i/} 240 ;; 241 -f) 242 flags=${flags/$i/} 243 ;; 244 esac 245 ((c++)) 246 done 247 case "$prev" in 248 -i) 249 COMPREPLY=() 250 ;; 251 -b|-h) 252 # (Doesn't seem to need this...) 253 # Uncomment the following line when 'owner/repo:[TAB]' misbehaved 254 #_get_comp_words_by_ref -n : cur 255 __gitcomp_nl "$(__hub_heads)" 256 # __ltrim_colon_completions "$cur" 257 ;; 258 -F) 259 COMPREPLY=( "$cur"* ) 260 ;; 261 -f|*) 262 __gitcomp "$flags" 263 ;; 264 esac 265 } 266 267 ################### 268 # Helper functions 269 ################### 270 271 # __hub_github_user [HOST] 272 # Return $GITHUB_USER or the default github user defined in hub config 273 # HOST - Host to be looked-up in hub config. Default is "github.com" 274 __hub_github_user() { 275 if [ -n "$GITHUB_USER" ]; then 276 echo $GITHUB_USER 277 return 278 fi 279 local line h k v host=${1:-github.com} config=${HUB_CONFIG:-~/.config/gh} 280 if [ -f "$config" ]; then 281 while read line; do 282 if [ "$line" = "---" ]; then 283 continue 284 fi 285 k=${line%%:*} 286 v=${line#*:} 287 if [ -z "$v" ]; then 288 if [ "$h" = "$host" ]; then 289 break 290 fi 291 h=$k 292 continue 293 fi 294 k=${k#* } 295 v=${v#* } 296 if [ "$h" = "$host" ] && [ "$k" = "user" ]; then 297 echo "$v" 298 break 299 fi 300 done < "$config" 301 fi 302 } 303 304 # __hub_github_repos [FORMAT] 305 # List all github hosted repository 306 # FORMAT - Format string contains multiple of these: 307 # \m remote 308 # \p owner/repo 309 # \o owner 310 # escaped characters (\n, \t ...etc) work 311 # If omitted, prints all github repos in the format of "remote:owner/repo" 312 __hub_github_repos() { 313 local f format=$1 314 if [ -z "$(__gitdir)" ]; then 315 return 316 fi 317 if [ -z "$format" ]; then 318 format='\1:\2' 319 else 320 format=${format//\m/\1} 321 format=${format//\p/\2} 322 format=${format//\o/\3} 323 fi 324 command git config --get-regexp 'remote\.[^.]*\.url' | 325 grep -E ' ((https?|git)://|git@)github\.com[:/][^:/]+/[^/]+$' | 326 sed -E 's#^remote\.([^.]+)\.url +.+[:/](([^/]+)/[^.]+)(\.git)?$#'"$format"'#' 327 } 328 329 # __hub_heads 330 # List all local "branch", and remote "owner/repo:branch" 331 __hub_heads() { 332 local i remote repo branch dir=$(__gitdir) 333 if [ -d "$dir" ]; then 334 command git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ 335 "refs/heads/" 336 for i in $(__hub_github_repos); do 337 remote=${i%%:*} 338 repo=${i#*:} 339 command git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ 340 "refs/remotes/${remote}/" | while read branch; do 341 echo "${repo}:${branch#${remote}/}" 342 done 343 done 344 fi 345 } 346 347 # __hub_revlist [REMOTE] 348 # List all tags, and branches under REMOTE, without the "remote/" prefix 349 # REMOTE - Remote name to search branches from. Default is "origin" 350 __hub_revlist() { 351 local i remote=${1:-origin} dir=$(__gitdir) 352 if [ -d "$dir" ]; then 353 command git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ 354 "refs/remotes/${remote}/" | while read i; do 355 echo "${i#${remote}/}" 356 done 357 command git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ 358 "refs/tags/" 359 fi 360 } 361 362 # Enable completion for hub even when not using the alias 363 complete -o bashdefault -o default -o nospace -F _git gh 2>/dev/null \ 364 || complete -o default -o nospace -F _git gh 365 fi