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