##// END OF EJS Templates
bash_completion: allow overriding completion for arguments that start with "-"
Alexis S. L. Carvalho -
r3485:26285469 default
parent child Browse files
Show More
@@ -1,435 +1,442 b''
1 1 # bash completion for the Mercurial distributed SCM
2 2
3 3 # Docs:
4 4 #
5 5 # If you source this file from your .bashrc, bash should be able to
6 6 # complete a command line that uses hg with all the available commands
7 7 # and options and sometimes even arguments.
8 8 #
9 9 # Mercurial allows you to define additional commands through extensions.
10 10 # Bash should be able to automatically figure out the name of these new
11 # commands and their options. If you also want to tell it how to
12 # complete non-option arguments, see below for how to define an
13 # _hg_cmd_foo function.
11 # commands and their options. See below for how to define _hg_opt_foo
12 # and _hg_cmd_foo functions to fine-tune the completion for option and
13 # non-option arguments, respectively.
14 14 #
15 15 #
16 16 # Notes about completion for specific commands:
17 17 #
18 18 # - the completion function for the email command from the patchbomb
19 19 # extension will try to call _hg_emails to get a list of e-mail
20 20 # addresses. It's up to the user to define this function. For
21 21 # example, put the addresses of the lists that you usually patchbomb
22 22 # in ~/.patchbomb-to and the addresses that you usually use to send
23 23 # the patchbombs in ~/.patchbomb-from and use something like this:
24 24 #
25 25 # _hg_emails()
26 26 # {
27 27 # if [ -r ~/.patchbomb-$1 ]; then
28 28 # cat ~/.patchbomb-$1
29 29 # fi
30 30 # }
31 31 #
32 32 #
33 33 # Writing completion functions for additional commands:
34 34 #
35 35 # If it exists, the function _hg_cmd_foo will be called without
36 36 # arguments to generate the completion candidates for the hg command
37 # "foo".
37 # "foo". If the command receives some arguments that aren't options
38 # even though they start with a "-", you can define a function called
39 # _hg_opt_foo to generate the completion candidates. If _hg_opt_foo
40 # doesn't return 0, regular completion for options is attempted.
38 41 #
39 42 # In addition to the regular completion variables provided by bash,
40 43 # the following variables are also set:
41 44 # - $hg - the hg program being used (e.g. /usr/bin/hg)
42 45 # - $cmd - the name of the hg command being completed
43 46 # - $cmd_index - the index of $cmd in $COMP_WORDS
44 47 # - $cur - the current argument being completed
45 48 # - $prev - the argument before $cur
46 49 # - $global_args - "|"-separated list of global options that accept
47 50 # an argument (e.g. '--cwd|-R|--repository')
48 51 # - $canonical - 1 if we canonicalized $cmd before calling the function
49 52 # 0 otherwise
50 53 #
51 54
52 55 shopt -s extglob
53 56
54 57 _hg_commands()
55 58 {
56 59 local commands
57 60 commands="$("$hg" debugcomplete "$cur" 2>/dev/null)" || commands=""
58 61 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$commands' -- "$cur"))
59 62 }
60 63
61 64 _hg_paths()
62 65 {
63 66 local paths="$("$hg" paths 2>/dev/null | sed -e 's/ = .*$//')"
64 67 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$paths' -- "$cur"))
65 68 }
66 69
67 70 _hg_repos()
68 71 {
69 72 local i
70 73 for i in $(compgen -d -- "$cur"); do
71 74 test ! -d "$i"/.hg || COMPREPLY=(${COMPREPLY[@]:-} "$i")
72 75 done
73 76 }
74 77
75 78 _hg_status()
76 79 {
77 80 local files="$("$hg" status -n$1 . 2>/dev/null)"
78 81 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
79 82 }
80 83
81 84 _hg_tags()
82 85 {
83 86 local tags="$("$hg" tags -q 2>/dev/null)"
84 87 local IFS=$'\n'
85 88 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$tags' -- "$cur"))
86 89 }
87 90
88 91 # this is "kind of" ugly...
89 92 _hg_count_non_option()
90 93 {
91 94 local i count=0
92 95 local filters="$1"
93 96
94 97 for ((i=1; $i<=$COMP_CWORD; i++)); do
95 98 if [[ "${COMP_WORDS[i]}" != -* ]]; then
96 99 if [[ ${COMP_WORDS[i-1]} == @($filters|$global_args) ]]; then
97 100 continue
98 101 fi
99 102 count=$(($count + 1))
100 103 fi
101 104 done
102 105
103 106 echo $(($count - 1))
104 107 }
105 108
106 109 _hg()
107 110 {
108 111 local cur prev cmd cmd_index opts i
109 112 # global options that receive an argument
110 113 local global_args='--cwd|-R|--repository'
111 114 local hg="$1"
115 local canonical=0
112 116
113 117 COMPREPLY=()
114 118 cur="$2"
115 119 prev="$3"
116 120
117 121 # searching for the command
118 122 # (first non-option argument that doesn't follow a global option that
119 123 # receives an argument)
120 124 for ((i=1; $i<=$COMP_CWORD; i++)); do
121 125 if [[ ${COMP_WORDS[i]} != -* ]]; then
122 126 if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
123 127 cmd="${COMP_WORDS[i]}"
124 128 cmd_index=$i
125 129 break
126 130 fi
127 131 fi
128 132 done
129 133
130 134 if [[ "$cur" == -* ]]; then
135 if [ "$(type -t "_hg_opt_$cmd")" = function ] && "_hg_opt_$cmd"; then
136 return
137 fi
138
131 139 opts=$("$hg" debugcomplete --options "$cmd" 2>/dev/null)
132 140
133 141 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$opts' -- "$cur"))
134 142 return
135 143 fi
136 144
137 145 # global options
138 146 case "$prev" in
139 147 -R|--repository)
140 148 _hg_repos
141 149 return
142 150 ;;
143 151 --cwd)
144 152 # Stick with default bash completion
145 153 return
146 154 ;;
147 155 esac
148 156
149 157 if [ -z "$cmd" ] || [ $COMP_CWORD -eq $i ]; then
150 158 _hg_commands
151 159 return
152 160 fi
153 161
154 162 # try to generate completion candidates for whatever command the user typed
155 163 local help
156 local canonical=0
157 164 if _hg_command_specific; then
158 165 return
159 166 fi
160 167
161 168 # canonicalize the command name and try again
162 169 help=$("$hg" help "$cmd" 2>/dev/null)
163 170 if [ $? -ne 0 ]; then
164 171 # Probably either the command doesn't exist or it's ambiguous
165 172 return
166 173 fi
167 174 cmd=${help#hg }
168 175 cmd=${cmd%%[$' \n']*}
169 176 canonical=1
170 177 _hg_command_specific
171 178 }
172 179
173 180 _hg_command_specific()
174 181 {
175 182 if [ "$(type -t "_hg_cmd_$cmd")" = function ]; then
176 183 "_hg_cmd_$cmd"
177 184 return 0
178 185 fi
179 186
180 187 if [ "$cmd" != status ] && [ "$prev" = -r ] || [ "$prev" == --rev ]; then
181 188 if [ $canonical = 1 ]; then
182 189 _hg_tags
183 190 return 0
184 191 elif [[ status != "$cmd"* ]]; then
185 192 _hg_tags
186 193 return 0
187 194 else
188 195 return 1
189 196 fi
190 197 fi
191 198
192 199 case "$cmd" in
193 200 help)
194 201 _hg_commands
195 202 ;;
196 203 export)
197 204 if _hg_ext_mq_patchlist qapplied && [ "${COMPREPLY[*]}" ]; then
198 205 return 0
199 206 fi
200 207 _hg_tags
201 208 ;;
202 209 manifest|update)
203 210 _hg_tags
204 211 ;;
205 212 pull|push|outgoing|incoming)
206 213 _hg_paths
207 214 _hg_repos
208 215 ;;
209 216 paths)
210 217 _hg_paths
211 218 ;;
212 219 add)
213 220 _hg_status "u"
214 221 ;;
215 222 commit)
216 223 _hg_status "mar"
217 224 ;;
218 225 remove)
219 226 _hg_status "d"
220 227 ;;
221 228 forget)
222 229 _hg_status "a"
223 230 ;;
224 231 diff)
225 232 _hg_status "mar"
226 233 ;;
227 234 revert)
228 235 _hg_status "mard"
229 236 ;;
230 237 clone)
231 238 local count=$(_hg_count_non_option)
232 239 if [ $count = 1 ]; then
233 240 _hg_paths
234 241 fi
235 242 _hg_repos
236 243 ;;
237 244 debugindex|debugindexdot)
238 245 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -f -X "!*.i" -- "$cur"))
239 246 ;;
240 247 debugdata)
241 248 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -f -X "!*.d" -- "$cur"))
242 249 ;;
243 250 *)
244 251 return 1
245 252 ;;
246 253 esac
247 254
248 255 return 0
249 256 }
250 257
251 258 complete -o bashdefault -o default -F _hg hg 2>/dev/null \
252 259 || complete -o default -F _hg hg
253 260
254 261
255 262 # Completion for commands provided by extensions
256 263
257 264 # mq
258 265 _hg_ext_mq_patchlist()
259 266 {
260 267 local patches
261 268 patches=$("$hg" $1 2>/dev/null)
262 269 if [ $? -eq 0 ] && [ "$patches" ]; then
263 270 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$patches' -- "$cur"))
264 271 return 0
265 272 fi
266 273 return 1
267 274 }
268 275
269 276 _hg_ext_mq_queues()
270 277 {
271 278 local root=$("$hg" root 2>/dev/null)
272 279 local n
273 280 for n in $(cd "$root"/.hg && compgen -d -- "$cur"); do
274 281 # I think we're usually not interested in the regular "patches" queue
275 282 # so just filter it.
276 283 if [ "$n" != patches ] && [ -e "$root/.hg/$n/series" ]; then
277 284 COMPREPLY=(${COMPREPLY[@]:-} "$n")
278 285 fi
279 286 done
280 287 }
281 288
282 289 _hg_cmd_qpop()
283 290 {
284 291 if [[ "$prev" = @(-n|--name) ]]; then
285 292 _hg_ext_mq_queues
286 293 return
287 294 fi
288 295 _hg_ext_mq_patchlist qapplied
289 296 }
290 297
291 298 _hg_cmd_qpush()
292 299 {
293 300 if [[ "$prev" = @(-n|--name) ]]; then
294 301 _hg_ext_mq_queues
295 302 return
296 303 fi
297 304 _hg_ext_mq_patchlist qunapplied
298 305 }
299 306
300 307 _hg_cmd_qdelete()
301 308 {
302 309 local qcmd=qunapplied
303 310 if [[ "$prev" = @(-r|--rev) ]]; then
304 311 qcmd=qapplied
305 312 fi
306 313 _hg_ext_mq_patchlist $qcmd
307 314 }
308 315
309 316 _hg_cmd_qsave()
310 317 {
311 318 if [[ "$prev" = @(-n|--name) ]]; then
312 319 _hg_ext_mq_queues
313 320 return
314 321 fi
315 322 }
316 323
317 324 _hg_cmd_strip()
318 325 {
319 326 _hg_tags
320 327 }
321 328
322 329 _hg_cmd_qcommit()
323 330 {
324 331 local root=$("$hg" root 2>/dev/null)
325 332 # this is run in a sub-shell, so we can't use _hg_status
326 333 local files=$(cd "$root/.hg/patches" 2>/dev/null &&
327 334 "$hg" status -nmar 2>/dev/null)
328 335 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
329 336 }
330 337
331 338 _hg_cmd_qfold()
332 339 {
333 340 _hg_ext_mq_patchlist qunapplied
334 341 }
335 342
336 343 _hg_cmd_qrename()
337 344 {
338 345 _hg_ext_mq_patchlist qseries
339 346 }
340 347
341 348 _hg_cmd_qheader()
342 349 {
343 350 _hg_ext_mq_patchlist qseries
344 351 }
345 352
346 353 _hg_cmd_qclone()
347 354 {
348 355 local count=$(_hg_count_non_option)
349 356 if [ $count = 1 ]; then
350 357 _hg_paths
351 358 fi
352 359 _hg_repos
353 360 }
354 361
355 362 _hg_ext_mq_guards()
356 363 {
357 364 "$hg" qselect --series 2>/dev/null | sed -e 's/^.//'
358 365 }
359 366
360 367 _hg_cmd_qselect()
361 368 {
362 369 local guards=$(_hg_ext_mq_guards)
363 370 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$guards' -- "$cur"))
364 371 }
365 372
366 373
367 374 # hbisect
368 375 _hg_cmd_bisect()
369 376 {
370 377 local i subcmd
371 378
372 379 # find the sub-command
373 380 for ((i=cmd_index+1; i<=COMP_CWORD; i++)); do
374 381 if [[ ${COMP_WORDS[i]} != -* ]]; then
375 382 if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
376 383 subcmd="${COMP_WORDS[i]}"
377 384 break
378 385 fi
379 386 fi
380 387 done
381 388
382 389 if [ -z "$subcmd" ] || [ $COMP_CWORD -eq $i ] || [ "$subcmd" = help ]; then
383 390 COMPREPLY=(${COMPREPLY[@]:-}
384 391 $(compgen -W 'bad good help init next reset' -- "$cur"))
385 392 return
386 393 fi
387 394
388 395 case "$subcmd" in
389 396 good|bad)
390 397 _hg_tags
391 398 ;;
392 399 esac
393 400
394 401 return
395 402 }
396 403
397 404
398 405 # patchbomb
399 406 _hg_cmd_email()
400 407 {
401 408 case "$prev" in
402 409 -c|--cc|-t|--to|-f|--from|--bcc)
403 410 # we need an e-mail address. let the user provide a function
404 411 # to get them
405 412 if [ "$(type -t _hg_emails)" = function ]; then
406 413 local arg=to
407 414 if [[ "$prev" == @(-f|--from) ]]; then
408 415 arg=from
409 416 fi
410 417 local addresses=$(_hg_emails $arg)
411 418 COMPREPLY=(${COMPREPLY[@]:-}
412 419 $(compgen -W '$addresses' -- "$cur"))
413 420 fi
414 421 return
415 422 ;;
416 423 -m|--mbox)
417 424 # fallback to standard filename completion
418 425 return
419 426 ;;
420 427 -s|--subject)
421 428 # free form string
422 429 return
423 430 ;;
424 431 esac
425 432
426 433 _hg_tags
427 434 return
428 435 }
429 436
430 437
431 438 # gpg
432 439 _hg_cmd_sign()
433 440 {
434 441 _hg_tags
435 442 }
General Comments 0
You need to be logged in to leave comments. Login now