chiark / gitweb /
1867e6bd5de20d5311963984f838a6335dcdc232
[stgit] / contrib / stgit-completion.bash
1 # bash completion support for StGIT                        -*- shell-script -*-
2 #
3 # Copyright (C) 2006, Karl Hasselström <kha@treskal.com>
4 # Based on git-completion.sh
5 #
6 # To use these routines:
7 #
8 #    1. Copy this file to somewhere (e.g. ~/.stgit-completion.bash).
9 #
10 #    2. Add the following line to your .bashrc:
11 #         . ~/.stgit-completion.bash
12
13 _stg_commands="
14     add
15     applied
16     branch
17     delete
18     diff
19     clean
20     clone
21     coalesce
22     commit
23     cp
24     edit
25     export
26     files
27     float
28     fold
29     goto
30     hide
31     id
32     import
33     init
34     log
35     mail
36     new
37     patches
38     pick
39     pop
40     pull
41     push
42     rebase
43     refresh
44     rename
45     repair
46     resolved
47     rm
48     series
49     show
50     sink
51     status
52     sync
53     top
54     unapplied
55     uncommit
56     unhide
57 "
58
59 # The path to .git, or empty if we're not in a repository.
60 _gitdir ()
61 {
62     echo "$(git rev-parse --git-dir 2>/dev/null)"
63 }
64
65 # Name of the current branch, or empty if there isn't one.
66 _current_branch ()
67 {
68     local b=$(git symbolic-ref HEAD 2>/dev/null)
69     echo ${b#refs/heads/}
70 }
71
72 # List of all applied patches.
73 _applied_patches ()
74 {
75     local g=$(_gitdir)
76     [ "$g" ] && cat "$g/patches/$(_current_branch)/applied"
77 }
78
79 # List of all unapplied patches.
80 _unapplied_patches ()
81 {
82     local g=$(_gitdir)
83     [ "$g" ] && cat "$g/patches/$(_current_branch)/unapplied"
84 }
85
86 # List of all applied patches.
87 _hidden_patches ()
88 {
89     local g=$(_gitdir)
90     [ "$g" ] && cat "$g/patches/$(_current_branch)/hidden"
91 }
92
93 # List of all patches.
94 _all_patches ()
95 {
96     local b=$(_current_branch)
97     local g=$(_gitdir)
98     [ "$g" ] && cat "$g/patches/$b/applied" "$g/patches/$b/unapplied"
99 }
100
101 # List of all patches except the current patch.
102 _all_other_patches ()
103 {
104     local b=$(_current_branch)
105     local g=$(_gitdir)
106     [ "$g" ] && cat "$g/patches/$b/applied" "$g/patches/$b/unapplied" \
107         | grep -v "^$(cat $g/patches/$b/current 2> /dev/null)$"
108 }
109
110 _all_branches ()
111 {
112     local g=$(_gitdir)
113     [ "$g" ] && (cd $g/patches/ && echo *)
114 }
115
116 _conflicting_files ()
117 {
118     local g=$(_gitdir)
119     [ "$g" ] && stg status --conflict
120 }
121
122 _dirty_files ()
123 {
124     local g=$(_gitdir)
125     [ "$g" ] && stg status --modified --new --deleted
126 }
127
128 _unknown_files ()
129 {
130     local g=$(_gitdir)
131     [ "$g" ] && stg status --unknown
132 }
133
134 _known_files ()
135 {
136     local g=$(_gitdir)
137     [ "$g" ] && git ls-files
138 }
139
140 # List the command options
141 _cmd_options ()
142 {
143     stg $1 --help 2>/dev/null | grep -e " --[A-Za-z]" | sed -e "s/.*\(--[^ =]\+\).*/\1/"
144 }
145
146 # Generate completions for patches and patch ranges from the given
147 # patch list function, and options from the given list.
148 _complete_patch_range ()
149 {
150     local patchlist="$1" options="$2"
151     local pfx cur="${COMP_WORDS[COMP_CWORD]}"
152     case "$cur" in
153         *..*)
154             pfx="${cur%..*}.."
155             cur="${cur#*..}"
156             COMPREPLY=($(compgen -P "$pfx" -W "$($patchlist)" -- "$cur"))
157             ;;
158         *)
159             COMPREPLY=($(compgen -W "$options $($patchlist)" -- "$cur"))
160             ;;
161     esac
162 }
163
164 _complete_patch_range_options ()
165 {
166     local patchlist="$1" options="$2" patch_options="$3"
167     local prev="${COMP_WORDS[COMP_CWORD-1]}"
168     local cur="${COMP_WORDS[COMP_CWORD]}"
169     local popt
170     for popt in $patch_options; do
171         if [ $prev == $popt ]; then
172             _complete_patch_range $patchlist
173             return
174         fi
175     done
176     COMPREPLY=($(compgen -W "$options" -- "$cur"))
177 }
178
179 _complete_branch ()
180 {
181      COMPREPLY=($(compgen -W "$(_cmd_options $1) $($2)" -- "${COMP_WORDS[COMP_CWORD]}"))
182 }
183
184 # Generate completions for options from the given list.
185 _complete_options ()
186 {
187     local options="$1"
188     COMPREPLY=($(compgen -W "$options" -- "${COMP_WORDS[COMP_CWORD]}"))
189 }
190
191 _complete_files ()
192 {
193     COMPREPLY=($(compgen -W "$(_cmd_options $1) $2" -- "${COMP_WORDS[COMP_CWORD]}"))
194 }
195
196 _stg_common ()
197 {
198     _complete_options "$(_cmd_options $1)"
199 }
200
201 _stg_patches ()
202 {
203     _complete_patch_range "$2" "$(_cmd_options $1)"
204 }
205
206 _stg_patches_options ()
207 {
208     _complete_patch_range_options "$2" "$(_cmd_options $1)" "$3"
209 }
210
211 _stg_help ()
212 {
213     _complete_options "$_stg_commands"
214 }
215
216 _stg ()
217 {
218     local i c=1 command
219
220     while [ $c -lt $COMP_CWORD ]; do
221         if [ $c == 1 ]; then
222             command="${COMP_WORDS[c]}"
223         fi
224         c=$((++c))
225     done
226
227     # Complete name of subcommand.
228     if [ $c -eq $COMP_CWORD -a -z "$command" ]; then
229         COMPREPLY=($(compgen \
230             -W "--help --version copyright help $_stg_commands" \
231             -- "${COMP_WORDS[COMP_CWORD]}"))
232         return;
233     fi
234
235     # Complete arguments to subcommands.
236     case "$command" in
237         # generic commands
238         help)   _stg_help ;;
239         # repository commands
240         id)     _stg_patches $command _all_patches ;;
241         # stack commands
242         coalesce) _stg_patches $command _applied_patches ;;
243         float)  _stg_patches $command _all_patches ;;
244         goto)   _stg_patches $command _all_other_patches ;;
245         hide)   _stg_patches $command _unapplied_patches ;;
246         pop)    _stg_patches $command _applied_patches ;;
247         push)   _stg_patches $command _unapplied_patches ;;
248         series) _stg_patches $command _all_patches ;;
249         sink)   _stg_patches $command _all_patches ;;
250         unhide) _stg_patches $command _hidden_patches ;;
251         # patch commands
252         delete) _stg_patches $command _all_patches ;;
253         edit)   _stg_patches $command _applied_patches ;;
254         export) _stg_patches $command _all_patches ;;
255         files)  _stg_patches $command _all_patches ;;
256         log)    _stg_patches $command _all_patches ;;
257         mail)   _stg_patches $command _all_patches ;;
258         pick)   _stg_patches $command _unapplied_patches ;;
259 #       refresh)_stg_patches_options $command _applied_patches "-p --patch" ;;
260         refresh) _complete_files $command "$(_dirty_files)" ;;
261         rename) _stg_patches $command _all_patches ;;
262         show)   _stg_patches $command _all_patches ;;
263         sync)   _stg_patches $command _applied_patches ;;
264         # working-copy commands
265         diff)   _stg_patches_options $command _applied_patches "-r --range" ;;
266         resolved) _complete_files $command "$(_conflicting_files)" ;;
267         add)    _complete_files $command "$(_unknown_files)" ;;
268 #       rm)     _complete_files $command "$(_known_files)" ;;
269         # commands that usually raher accept branches
270         branch) _complete_branch $command _all_branches ;;
271         rebase) _complete_branch $command _all_branches ;;
272         # all the other commands
273         *)      _stg_common $command ;;
274     esac
275 }
276
277 complete -o default -F _stg stg