aboutsummaryrefslogtreecommitdiff
path: root/bash/bash_completion.d/git.bash
blob: 2fd1bb98dfb330512ffb0516f385f57d81d08dc9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# Some simple completion for Git
_git() {

    # Subcommands for this function to stack words onto COMPREPLY; if the first
    # argument is not given, the rest of the function is reached
    case $1 in

        # No argument; continue normal completion
        '') ;;

        # Symbolic references, remote or local
        refs)
            local ref
            while IFS= read -r ref ; do
                [[ -n $ref ]] || continue
                ref=${ref#refs/*/}
                case $ref in
                    "${COMP_WORDS[COMP_CWORD]}"*)
                        COMPREPLY[${#COMPREPLY[@]}]=$ref
                        ;;
                esac
            done < <(git for-each-ref \
                --format '%(refname)' \
                2>/dev/null)
            return
            ;;

        # Remote names
        remotes)
            local remote
            while IFS= read -r remote ; do
                case $remote in
                    '') continue ;;
                    "${COMP_WORDS[COMP_CWORD]}"*)
                        COMPREPLY[${#COMPREPLY[@]}]=$remote
                        ;;
                esac
            done < <(git remote 2>/dev/null)
            return
            ;;

        # Git aliases
        aliases)
            local alias
            while IFS= read -r alias ; do
                alias=${alias#alias.}
                alias=${alias%% *}
                case $alias in
                    '') continue ;;
                    "${COMP_WORDS[COMP_CWORD]}"*)
                        COMPREPLY[${#COMPREPLY[@]}]=$alias
                        ;;
                esac
            done < <(git config \
                --get-regexp '^alias\.' \
                2>/dev/null)
            return
            ;;

        # Git subcommands
        subcommands)
            local execpath
            execpath=$(git --exec-path) || return
            local path
            for path in "$execpath"/git-"${COMP_WORDS[COMP_CWORD]}"* ; do
                [[ -f $path ]] || continue
                [[ -x $path ]] || continue
                COMPREPLY[${#COMPREPLY[@]}]=${path#"$execpath"/git-}
            done
            return
            ;;
    esac

    # Try to find the index of the Git subcommand
    local -i sci i
    for ((i = 1; !sci && i <= COMP_CWORD; i++)) ; do
        case ${COMP_WORDS[i]} in

            # Skip --option=value
            --*=*) ;;

            # These ones have arguments, so bump the index up one more
            -C|-c|--exec-path|--git-dir|--work-tree|--namespace) ((i++)) ;;

            # Skip --option
            --?*) ;;

            # We have hopefully found our subcommand
            *) ((sci = i)) ;;
        esac
    done

    # Complete initial subcommand or alias
    if ((sci == COMP_CWORD)) ; then
        "${FUNCNAME[0]}" subcommands
        "${FUNCNAME[0]}" aliases
        return
    fi

    # Test subcommand to choose completions
    case ${COMP_WORDS[sci]} in

        # Help on real subcommands (not aliases)
        help)
            "${FUNCNAME[0]}" subcommands
            return
            ;;

        # Complete with remote subcommands and then remote names
        remote)
            if ((COMP_CWORD == 2)) ; then
                local word
                while IFS= read -r word ; do
                    [[ -n $word ]] || continue
                    COMPREPLY[${#COMPREPLY[@]}]=$word
                done < <(compgen -W '
                    add
                    get-url
                    prune
                    remove
                    rename
                    set-branches
                    set-head
                    set-url
                    show
                    update
                ' -- "${COMP_WORDS[COMP_CWORD]}")
            else
                "${FUNCNAME[0]}" remotes
            fi
            return
            ;;

        # Complete with stash subcommands
        stash)
            ((COMP_CWORD == 2)) || return
            local word
            while IFS= read -r word ; do
                [[ -n $word ]] || continue
                COMPREPLY[${#COMPREPLY[@]}]=$word
            done < <(compgen -W '
                apply
                branch
                clear
                create
                drop
                list
                pop
                save
                show
                store
            ' -- "${COMP_WORDS[COMP_CWORD]}")
            return
            ;;

        # Complete with submodule subcommands
        submodule)
            ((COMP_CWORD == 2)) || return
            local word
            while IFS= read -r word ; do
                [[ -n $word ]] || continue
                COMPREPLY[${#COMPREPLY[@]}]=$word
            done < <(compgen -W '
                add
                deinit
                foreach
                init
                status
                summary
                sync
                update
            ' -- "${COMP_WORDS[COMP_CWORD]}")
            return
            ;;

        # Complete with remotes and then refs
        fetch|pull|push)
            if ((COMP_CWORD == 2)) ; then
                "${FUNCNAME[0]}" remotes
            else
                "${FUNCNAME[0]}" refs
            fi
            ;;

        # Commands for which I'm likely to want a ref
        branch|checkout|merge|rebase|tag)
            "${FUNCNAME[0]}" refs
            ;;

        # I normally only want a refspec for "reset" if I'm using the --hard or
        # --soft option; otherwise, files are fine
        reset)
            case ${COMP_WORDS[COMP_CWORD-1]} in
                --hard|--soft)
                    "${FUNCNAME[0]}" refs
                    ;;
            esac
            ;;
    esac
}
complete -F _git -o bashdefault -o default git