contrib / completion / git-completion.bashon commit Merge branch 'maint' (a622f6b)
   1#
   2# bash completion support for core Git.
   3#
   4# Copyright (C) 2006 Shawn Pearce
   5# Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/).
   6#
   7# The contained completion routines provide support for completing:
   8#
   9#    *) local and remote branch names
  10#    *) local and remote tag names
  11#    *) .git/remotes file names
  12#    *) git 'subcommands'
  13#    *) tree paths within 'ref:path/to/file' expressions
  14#
  15# To use these routines:
  16#
  17#    1) Copy this file to somewhere (e.g. ~/.git-completion.sh).
  18#    2) Added the following line to your .bashrc:
  19#        source ~/.git-completion.sh
  20#
  21
  22__git_refs ()
  23{
  24        local cmd i is_hash=y
  25        if [ -d "$1" ]; then
  26                cmd=git-peek-remote
  27        else
  28                cmd=git-ls-remote
  29        fi
  30        for i in $($cmd "$1" 2>/dev/null); do
  31                case "$is_hash,$i" in
  32                y,*) is_hash=n ;;
  33                n,*^{}) is_hash=y ;;
  34                n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}" ;;
  35                n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;;
  36                n,*) is_hash=y; echo "$i" ;;
  37                esac
  38        done
  39}
  40
  41__git_refs2 ()
  42{
  43        local cmd i is_hash=y
  44        if [ -d "$1" ]; then
  45                cmd=git-peek-remote
  46        else
  47                cmd=git-ls-remote
  48        fi
  49        for i in $($cmd "$1" 2>/dev/null); do
  50                case "$is_hash,$i" in
  51                y,*) is_hash=n ;;
  52                n,*^{}) is_hash=y ;;
  53                n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}:${i#refs/tags/}" ;;
  54                n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}:${i#refs/heads/}" ;;
  55                n,*) is_hash=y; echo "$i:$i" ;;
  56                esac
  57        done
  58}
  59
  60__git_remotes ()
  61{
  62        local i REVERTGLOB=$(shopt -p nullglob)
  63        shopt -s nullglob
  64        for i in .git/remotes/*; do
  65                echo ${i#.git/remotes/}
  66        done
  67        $REVERTGLOB
  68}
  69
  70__git_complete_file ()
  71{
  72        local cur="${COMP_WORDS[COMP_CWORD]}"
  73        case "$cur" in
  74        ?*:*)
  75                local pfx ls ref="$(echo "$cur" | sed 's,:.*$,,')"
  76                cur="$(echo "$cur" | sed 's,^.*:,,')"
  77                case "$cur" in
  78                ?*/*)
  79                        pfx="$(echo "$cur" | sed 's,/[^/]*$,,')"
  80                        cur="$(echo "$cur" | sed 's,^.*/,,')"
  81                        ls="$ref:$pfx"
  82                        pfx="$pfx/"
  83                        ;;
  84                *)
  85                        ls="$ref"
  86                        ;;
  87            esac
  88                COMPREPLY=($(compgen -P "$pfx" \
  89                        -W "$(git-ls-tree "$ls" \
  90                                | sed '/^100... blob /s,^.*     ,,
  91                                       /^040000 tree /{
  92                                           s,^.*        ,,
  93                                           s,$,/,
  94                                       }
  95                                       s/^.*    //')" \
  96                        -- "$cur"))
  97                ;;
  98        *)
  99                COMPREPLY=($(compgen -W "$(__git_refs .)" -- "$cur"))
 100                ;;
 101        esac
 102}
 103
 104__git_aliases ()
 105{
 106        git repo-config --list | grep '^alias\.' \
 107                | sed -e 's/^alias\.//' -e 's/=.*$//'
 108}
 109
 110__git_aliased_command ()
 111{
 112        local cmdline=$(git repo-config alias.$1)
 113        for word in $cmdline; do
 114                if [ "${word##-*}" ]; then
 115                        echo $word
 116                        return
 117                fi
 118        done
 119}
 120
 121_git_branch ()
 122{
 123        local cur="${COMP_WORDS[COMP_CWORD]}"
 124        COMPREPLY=($(compgen -W "-l -f -d -D $(__git_refs .)" -- "$cur"))
 125}
 126
 127_git_cat_file ()
 128{
 129        local cur="${COMP_WORDS[COMP_CWORD]}"
 130        case "${COMP_WORDS[0]},$COMP_CWORD" in
 131        git-cat-file*,1)
 132                COMPREPLY=($(compgen -W "-p -t blob tree commit tag" -- "$cur"))
 133                ;;
 134        git,2)
 135                COMPREPLY=($(compgen -W "-p -t blob tree commit tag" -- "$cur"))
 136                ;;
 137        *)
 138                __git_complete_file
 139                ;;
 140        esac
 141}
 142
 143_git_checkout ()
 144{
 145        local cur="${COMP_WORDS[COMP_CWORD]}"
 146        COMPREPLY=($(compgen -W "-l -b $(__git_refs .)" -- "$cur"))
 147}
 148
 149_git_diff ()
 150{
 151        __git_complete_file
 152}
 153
 154_git_diff_tree ()
 155{
 156        local cur="${COMP_WORDS[COMP_CWORD]}"
 157        COMPREPLY=($(compgen -W "-r -p -M $(__git_refs .)" -- "$cur"))
 158}
 159
 160_git_fetch ()
 161{
 162        local cur="${COMP_WORDS[COMP_CWORD]}"
 163
 164        case "${COMP_WORDS[0]},$COMP_CWORD" in
 165        git-fetch*,1)
 166                COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
 167                ;;
 168        git,2)
 169                COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
 170                ;;
 171        *)
 172                case "$cur" in
 173                *:*)
 174                cur=$(echo "$cur" | sed 's/^.*://')
 175                        COMPREPLY=($(compgen -W "$(__git_refs .)" -- "$cur"))
 176                        ;;
 177                *)
 178                        local remote
 179                        case "${COMP_WORDS[0]}" in
 180                        git-fetch) remote="${COMP_WORDS[1]}" ;;
 181                        git)       remote="${COMP_WORDS[2]}" ;;
 182                        esac
 183                        COMPREPLY=($(compgen -W "$(__git_refs2 "$remote")" -- "$cur"))
 184                        ;;
 185                esac
 186                ;;
 187        esac
 188}
 189
 190_git_ls_remote ()
 191{
 192        local cur="${COMP_WORDS[COMP_CWORD]}"
 193        COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
 194}
 195
 196_git_ls_tree ()
 197{
 198        __git_complete_file
 199}
 200
 201_git_log ()
 202{
 203        local cur="${COMP_WORDS[COMP_CWORD]}"
 204        case "$cur" in
 205        *..*)
 206                local pfx=$(echo "$cur" | sed 's/\.\..*$/../')
 207                cur=$(echo "$cur" | sed 's/^.*\.\.//')
 208                COMPREPLY=($(compgen -P "$pfx" -W "$(__git_refs .)" -- "$cur"))
 209                ;;
 210        *)
 211                COMPREPLY=($(compgen -W "$(__git_refs .)" -- "$cur"))
 212                ;;
 213        esac
 214}
 215
 216_git_merge_base ()
 217{
 218        local cur="${COMP_WORDS[COMP_CWORD]}"
 219        COMPREPLY=($(compgen -W "$(__git_refs .)" -- "$cur"))
 220}
 221
 222_git_pull ()
 223{
 224        local cur="${COMP_WORDS[COMP_CWORD]}"
 225
 226        case "${COMP_WORDS[0]},$COMP_CWORD" in
 227        git-pull*,1)
 228                COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
 229                ;;
 230        git,2)
 231                COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
 232                ;;
 233        *)
 234                local remote
 235                case "${COMP_WORDS[0]}" in
 236                git-pull)  remote="${COMP_WORDS[1]}" ;;
 237                git)       remote="${COMP_WORDS[2]}" ;;
 238                esac
 239                COMPREPLY=($(compgen -W "$(__git_refs "$remote")" -- "$cur"))
 240                ;;
 241        esac
 242}
 243
 244_git_push ()
 245{
 246        local cur="${COMP_WORDS[COMP_CWORD]}"
 247
 248        case "${COMP_WORDS[0]},$COMP_CWORD" in
 249        git-push*,1)
 250                COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
 251                ;;
 252        git,2)
 253                COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
 254                ;;
 255        *)
 256                case "$cur" in
 257                *:*)
 258                        local remote
 259                        case "${COMP_WORDS[0]}" in
 260                        git-push)  remote="${COMP_WORDS[1]}" ;;
 261                        git)       remote="${COMP_WORDS[2]}" ;;
 262                        esac
 263                cur=$(echo "$cur" | sed 's/^.*://')
 264                        COMPREPLY=($(compgen -W "$(__git_refs "$remote")" -- "$cur"))
 265                        ;;
 266                *)
 267                        COMPREPLY=($(compgen -W "$(__git_refs2 .)" -- "$cur"))
 268                        ;;
 269                esac
 270                ;;
 271        esac
 272}
 273
 274_git_show ()
 275{
 276        local cur="${COMP_WORDS[COMP_CWORD]}"
 277        COMPREPLY=($(compgen -W "$(__git_refs .)" -- "$cur"))
 278}
 279
 280_git ()
 281{
 282        if [ $COMP_CWORD = 1 ]; then
 283                COMPREPLY=($(compgen \
 284                        -W "--version $(git help -a|egrep '^ ') \
 285                            $(__git_aliases)" \
 286                        -- "${COMP_WORDS[COMP_CWORD]}"))
 287        else
 288                local command="${COMP_WORDS[1]}"
 289                local expansion=$(__git_aliased_command "$command")
 290
 291                if [ "$expansion" ]; then
 292                        command="$expansion"
 293                fi
 294
 295                case "$command" in
 296                branch)      _git_branch ;;
 297                cat-file)    _git_cat_file ;;
 298                checkout)    _git_checkout ;;
 299                diff)        _git_diff ;;
 300                diff-tree)   _git_diff_tree ;;
 301                fetch)       _git_fetch ;;
 302                log)         _git_log ;;
 303                ls-remote)   _git_ls_remote ;;
 304                ls-tree)     _git_ls_tree ;;
 305                pull)        _git_pull ;;
 306                push)        _git_push ;;
 307                show)        _git_show ;;
 308                show-branch) _git_log ;;
 309                whatchanged) _git_log ;;
 310                *)           COMPREPLY=() ;;
 311                esac
 312        fi
 313}
 314
 315_gitk ()
 316{
 317        local cur="${COMP_WORDS[COMP_CWORD]}"
 318        COMPREPLY=($(compgen -W "--all $(__git_refs .)" -- "$cur"))
 319}
 320
 321complete -o default -o nospace -F _git git
 322complete -o default            -F _gitk gitk
 323complete -o default            -F _git_branch git-branch
 324complete -o default -o nospace -F _git_cat_file git-cat-file
 325complete -o default            -F _git_checkout git-checkout
 326complete -o default -o nospace -F _git_diff git-diff
 327complete -o default            -F _git_diff_tree git-diff-tree
 328complete -o default -o nospace -F _git_fetch git-fetch
 329complete -o default -o nospace -F _git_log git-log
 330complete -o default            -F _git_ls_remote git-ls-remote
 331complete -o default -o nospace -F _git_ls_tree git-ls-tree
 332complete -o default            -F _git_merge_base git-merge-base
 333complete -o default -o nospace -F _git_pull git-pull
 334complete -o default -o nospace -F _git_push git-push
 335complete -o default            -F _git_show git-show
 336complete -o default -o nospace -F _git_log git-whatchanged
 337
 338# The following are necessary only for Cygwin, and only are needed
 339# when the user has tab-completed the executable name and consequently
 340# included the '.exe' suffix.
 341#
 342complete -o default -o nospace -F _git_cat_file git-cat-file.exe
 343complete -o default -o nospace -F _git_diff git-diff.exe
 344complete -o default -o nospace -F _git_diff_tree git-diff-tree.exe
 345complete -o default -o nospace -F _git_log git-log.exe
 346complete -o default -o nospace -F _git_ls_tree git-ls-tree.exe
 347complete -o default            -F _git_merge_base git-merge-base.exe
 348complete -o default -o nospace -F _git_push git-push.exe
 349complete -o default -o nospace -F _git_log git-whatchanged.exe