blob: 8a0746d535a7daa9432514bc64db160f98e60a78 [file] [log] [blame]
Jari Aaltobb706242000-03-17 21:46:59 +00001#
2# Completion examples
3#
Chet Rameyac50fba2014-02-26 09:36:43 -05004# Chet Ramey <chet.ramey@case.edu>
5#
6# Copyright 2002 Chester Ramey
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2, or (at your option)
11# any later version.
12#
13# TThis program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software Foundation,
20# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Jari Aaltobb706242000-03-17 21:46:59 +000021
22#
23# This encapsulates the default bash completion code
24# call with the word to be completed as $1
25#
26# Since programmable completion does not use the bash default completions
27# or the readline default of filename completion when the compspec does
28# not generate any matches, this may be used as a `last resort' in a
29# completion function to mimic the default bash completion behavior.
30#
31_bash_def_completion ()
32{
33 local h t
34 COMPREPLY=()
35
36 # command substitution
37 if [[ "$1" == \$\(* ]]; then
38 t=${1#??}
39 COMPREPLY=( $(compgen -c -P '$(' $t) )
40 fi
41 # variables with a leading `${'
42 if [ ${#COMPREPLY[@]} -eq 0 ] && [[ "$1" == \$\{* ]]; then
43 t=${1#??}
44 COMPREPLY=( $(compgen -v -P '${' -S '}' $t) )
45 fi
46 # variables with a leading `$'
47 if [ ${#COMPREPLY[@]} -eq 0 ] && [[ "$1" == \$* ]]; then
48 t=${1#?}
49 COMPREPLY=( $(compgen -v -P '$' $t ) )
50 fi
51 # username expansion
52 if [ ${#COMPREPLY[@]} -eq 0 ] && [[ "$1" == ~* ]] && [[ "$1" != */* ]]; then
53 t=${1#?}
54 COMPREPLY=( $( compgen -u -P '~' $t ) )
55 fi
56 # hostname
57 if [ ${#COMPREPLY[@]} -eq 0 ] && [[ "$1" == *@* ]]; then
58 h=${1%%@*}
59 t=${1#*@}
60 COMPREPLY=( $( compgen -A hostname -P "${h}@" $t ) )
61 fi
62 # glob pattern
63 if [ ${#COMPREPLY[@]} -eq 0 ]; then
64 # sh-style glob pattern
65 if [[ $1 == *[*?[]* ]]; then
66 COMPREPLY=( $( compgen -G "$1" ) )
67 # ksh-style extended glob pattern - must be complete
68 elif shopt -q extglob && [[ $1 == *[?*+\!@]\(*\)* ]]; then
69 COMPREPLY=( $( compgen -G "$1" ) )
70 fi
71 fi
72
73 # final default is filename completion
74 if [ ${#COMPREPLY[@]} -eq 0 ]; then
75 COMPREPLY=( $(compgen -f "$1" ) )
76 fi
77}
78
79#
80# Return 1 if $1 appears to contain a redirection operator. Handles backslash
81# quoting (barely).
82#
83_redir_op()
84{
85 case "$1" in
86 *\\'[\<\>]'*) return 1;;
87 *[\<\>]*) return 0;;
88 *) return 1;;
89 esac
90}
91
92
93# _redir_test tests the current word ($1) and the previous word ($2) for
94# redirection operators and does filename completion on the current word
95# if either one contains a redirection operator
96_redir_test()
97{
98 if _redir_op "$1" ; then
99 COMPREPLY=( $( compgen -f "$1" ) )
100 return 0
101 elif _redir_op "$2" ; then
102 COMPREPLY=( $( compgen -f "$1" ) )
103 return 0
104 fi
105 return 1
106}
107
108# optional, but without this you can't use extended glob patterns
109shopt -s extglob
110
111#
112# Easy ones for the shell builtins
113#
114# nothing for: alias, break, continue, dirs, echo, eval, exit, getopts,
115# let, logout, popd, printf, pwd, return, shift, suspend, test, times,
116# umask
117#
118
119complete -f -- . source
120complete -A enabled builtin
121complete -d cd
122
123# this isn't exactly right yet -- needs to skip shell functions and
124# do $PATH lookup (or do compgen -c and filter out matches that also
125# appear in compgen -A function)
126complete -c command
127
128# could add -S '=', but that currently screws up because readline appends
129# a space unconditionally
130
131complete -v export local readonly
132complete -A helptopic help # currently same as builtins
133
134complete -d pushd
135
136complete -A shopt shopt
137
138complete -c type
139
140complete -a unalias
141complete -v unset
142
143#
144# Job control builtins: fg, bg, disown, kill, wait
145# kill not done yet
146#
147
148complete -A stopped -P '%' bg
149complete -j -P '%' fg jobs disown
150
151# this is not quite right at this point
152
153_wait_func ()
154{
155 local cur
156 cur=${COMP_WORDS[COMP_CWORD]}
157
158 case "$cur" in
159 %*) COMPREPLY=( $(compgen -A running -P '%' ${cur#?} ) ) ;;
160 [0-9]*) COMPREPLY=( $(jobs -p | grep ^${cur}) ) ;;
161 *) COMPREPLY=( $(compgen -A running -P '%') $(jobs -p) )
162 ;;
163 esac
164}
165complete -F _wait_func wait
166
167#
168# more complicated things, several as yet unimplemented
169#
170
171#complete -F _bind_func bind
172
173_declare_func()
174{
175 local cur prev nflag opts
176
177 cur=${COMP_WORDS[COMP_CWORD]}
178 prev=${COMP_WORDS[COMP_CWORD-1]}
179
180 COMPREPLY=()
181 if (( $COMP_CWORD <= 1 )) || [[ $cur == '-' ]]; then
Jari Aalto7117c2d2002-07-17 14:10:11 +0000182 COMPREPLY=(-a -f -F -i -p -r -t -x)
Jari Aaltobb706242000-03-17 21:46:59 +0000183 return 0;
184 fi
185 if [[ $cur == '+' ]]; then
Jari Aalto7117c2d2002-07-17 14:10:11 +0000186 COMPREPLY=(+i +t +x)
Jari Aaltobb706242000-03-17 21:46:59 +0000187 return 0;
188 fi
189 if [[ $prev == '-p' ]]; then
190 COMPREPLY=( $(compgen -v $cur) )
191 return 0;
192 fi
193 return 1
194}
195complete -F _declare_func declare typeset
196
197_enable_func()
198{
199 local cur prev nflag opts
200
201 cur=${COMP_WORDS[COMP_CWORD]}
202 prev=${COMP_WORDS[COMP_CWORD-1]}
203
204 COMPREPLY=()
205 if (( $COMP_CWORD <= 1 )) || [[ $cur == '-' ]]; then
206 COMPREPLY=(-a -d -f -n -p -s)
207 return 0;
208 fi
209 if [[ $prev == '-f' ]]; then
210 COMPREPLY=( $( compgen -f $cur ) )
211 return 0;
212 fi
213 for opts in "${COMP_WORDS[@]}" ; do
214 if [[ $opts == -*n* ]]; then nflag=1; fi
215 done
216
217 if [ -z "$nflag" ] ; then
218 COMPREPLY=( $( compgen -A enabled $cur ) )
219 else
220 COMPREPLY=( $( compgen -A disabled $cur ) )
221 fi
222 return 0;
223}
224complete -F _enable_func enable
225
226_exec_func()
227{
228 local cur prev
229
230 cur=${COMP_WORDS[COMP_CWORD]}
231 prev=${COMP_WORDS[COMP_CWORD-1]}
232
233 if (( $COMP_CWORD <= 1 )) || [[ $cur == '-' ]]; then
234 COMPREPLY=(-a -c -l)
235 return 0;
236 fi
237 if [[ $prev != -*a* ]]; then
238 COMPREPLY=( $( compgen -c $cur ) )
239 return 0
240 fi
241 return 1;
242}
243complete -F _exec_func exec
244
245_fc_func()
246{
247 local cur prev
248
249 cur=${COMP_WORDS[COMP_CWORD]}
250 prev=${COMP_WORDS[COMP_CWORD-1]}
251
252 if (( $COMP_CWORD <= 1 )) || [[ $cur == '-' ]]; then
253 COMPREPLY=(-e -n -l -r -s)
254 return 0;
255 fi
256 if [[ $prev == -*e ]]; then
257 COMPREPLY=( $(compgen -c $cur) )
258 return 0
259 fi
260 return 1
261}
262complete -F _fc_func fc
263
264_hash_func()
265{
266 local cur prev
267
268 cur=${COMP_WORDS[COMP_CWORD]}
269 prev=${COMP_WORDS[COMP_CWORD-1]}
270
271 if (( $COMP_CWORD <= 1 )) || [[ $cur == '-' ]]; then
Jari Aalto7117c2d2002-07-17 14:10:11 +0000272 COMPREPLY=(-p -r -t)
Jari Aaltobb706242000-03-17 21:46:59 +0000273 return 0;
274 fi
275
276 if [[ $prev == '-p' ]]; then
277 COMPREPLY=( $( compgen -f $cur ) )
278 return 0;
279 fi
280 COMPREPLY=( $( compgen -c $cur ) )
281 return 0
282}
283complete -F _hash_func hash
284
285_history_func()
286{
287 local cur prev
288
289 cur=${COMP_WORDS[COMP_CWORD]}
290 prev=${COMP_WORDS[COMP_CWORD-1]}
291
292 COMPREPLY=()
293 if (( $COMP_CWORD <= 1 )) || [[ $cur == '-' ]]; then
294 COMPREPLY=(-a -c -d -n -r -w -p -s)
295 return 0;
296 fi
297 if [[ $prev == -[anrw] ]]; then
298 COMPREPLY=( $( compgen -f $cur ) )
299 fi
300 return 0
301}
302complete -F _history_func history
303
304#complete -F _read_func read
305
306_set_func ()
307{
308 local cur prev
309
310 cur=${COMP_WORDS[COMP_CWORD]}
311 prev=${COMP_WORDS[COMP_CWORD-1]}
312
313 COMPREPLY=()
314
315 _redir_test "$cur" "$prev" && return 0;
316
317 if (( $COMP_CWORD <= 1 )) || [[ $cur == '-' ]]; then
318 COMPREPLY=(-a -b -e -f -k -m -n -o -p -t -u -v -x -B -C -H -P --)
319 return 0;
320 fi
321 if [[ $cur == '+' ]]; then
322 COMPREPLY=(+a +b +e +f +k +m +n +o +p +t +u +v +x +B +C +H +P)
323 return 0;
324 fi
325 if [[ $prev == [+-]o ]]; then
326 COMPREPLY=( $(compgen -A setopt $cur) )
327 return 0;
328 fi
329 return 1;
330}
331complete -F _set_func set
332
333_trap_func ()
334{
335 local cur
336 cur=${COMP_WORDS[COMP_CWORD]}
337
338 if (( $COMP_CWORD <= 1 )) || [[ $cur == '-' ]]; then
339 COMPREPLY=(-l -p)
340 return 0;
341 fi
342 COMPREPLY=( $( compgen -A signal ${cur}) )
343 return 0
344}
345complete -F _trap_func trap
346
347#
348# meta-completion (completion for complete/compgen)
349#
350_complete_meta_func()
351{
352 local cur prev cmd
353 COMPREPLY=()
354
355 cmd=$1
356
357 cur=${COMP_WORDS[COMP_CWORD]}
358 prev=${COMP_WORDS[COMP_CWORD-1]}
359
360 _redir_test "$cur" "$prev" && return 0;
361
362 if (( $COMP_CWORD <= 1 )) || [[ "$cur" == '-' ]]; then
363 case "$cmd" in
Jari Aalto7117c2d2002-07-17 14:10:11 +0000364 complete) COMPREPLY=(-a -b -c -d -e -f -j -k -s -v -u -r -p -A -G -W -P -S -X -F -C);;
365 compgen) COMPREPLY=(-a -b -c -d -e -f -j -k -s -v -u -A -G -W -P -S -X -F -C);;
Jari Aaltobb706242000-03-17 21:46:59 +0000366 esac
367 return 0
368 fi
369
370 if [[ $prev == -A ]]; then
371 COMPREPLY=(alias arrayvar binding builtin command directory \
Jari Aalto28ef6c32001-04-06 19:14:31 +0000372disabled enabled export file 'function' helptopic hostname job keyword \
Jari Aalto7117c2d2002-07-17 14:10:11 +0000373running service setopt shopt signal stopped variable)
Jari Aaltobb706242000-03-17 21:46:59 +0000374 return 0
375 elif [[ $prev == -F ]]; then
376 COMPREPLY=( $( compgen -A function $cur ) )
377 elif [[ $prev == -C ]]; then
378 COMPREPLY=( $( compgen -c $cur ) )
379 else
380 COMPREPLY=( $( compgen -c $cur ) )
381 fi
382 return 0
383}
384complete -F _complete_meta_func complete compgen
385
386#
387# some completions for shell reserved words
388#
389#complete -c -k time do if then else elif '{'
390
391#
392# external commands
393#
394
395complete -e printenv
396
397complete -c nohup exec nice eval trace truss strace sotruss gdb
398
399_make_targets ()
400{
401 local mdef makef gcmd cur prev i
402
403 COMPREPLY=()
404 cur=${COMP_WORDS[COMP_CWORD]}
405 prev=${COMP_WORDS[COMP_CWORD-1]}
406
407 # if prev argument is -f, return possible filename completions.
408 # we could be a little smarter here and return matches against
409 # `makefile Makefile *.mk', whatever exists
410 case "$prev" in
411 -*f) COMPREPLY=( $(compgen -f $cur ) ); return 0;;
412 esac
413
414 # if we want an option, return the possible posix options
415 case "$cur" in
416 -) COMPREPLY=(-e -f -i -k -n -p -q -r -S -s -t); return 0;;
417 esac
418
419 # make reads `makefile' before `Makefile'
Jari Aalto28ef6c32001-04-06 19:14:31 +0000420 # GNU make reads `GNUmakefile' before all other makefiles, but we
421 # check that we're completing `gmake' before checking for it
422 if [ -f GNUmakefile ] && [ ${COMP_WORDS[0]} == gmake ]; then
423 mdef=GNUmakefile
424 elif [ -f makefile ]; then
Jari Aaltobb706242000-03-17 21:46:59 +0000425 mdef=makefile
426 elif [ -f Makefile ]; then
427 mdef=Makefile
428 else
429 mdef=*.mk # local convention
430 fi
431
432 # before we scan for targets, see if a makefile name was specified
433 # with -f
434 for (( i=0; i < ${#COMP_WORDS[@]}; i++ )); do
435 if [[ ${COMP_WORDS[i]} == -*f ]]; then
436 eval makef=${COMP_WORDS[i+1]} # eval for tilde expansion
437 break
438 fi
439 done
440
441 [ -z "$makef" ] && makef=$mdef
442
443 # if we have a partial word to complete, restrict completions to
444 # matches of that word
445 if [ -n "$2" ]; then gcmd='grep "^$2"' ; else gcmd=cat ; fi
446
447 # if we don't want to use *.mk, we can take out the cat and use
448 # test -f $makef and input redirection
449 COMPREPLY=( $(cat $makef 2>/dev/null | awk 'BEGIN {FS=":"} /^[^.# ][^=]*:/ {print $1}' | tr -s ' ' '\012' | sort -u | eval $gcmd ) )
450}
451complete -F _make_targets -X '+($*|*.[cho])' make gmake pmake
452
453_umount_func ()
454{
455 COMPREPLY=( $(mount | awk '{print $1}') )
456}
457complete -F _umount_func umount
458
459_configure_func ()
460{
461 case "$2" in
462 -*) ;;
463 *) return ;;
464 esac
465
466 case "$1" in
467 \~*) eval cmd=$1 ;;
468 *) cmd="$1" ;;
469 esac
470
471 COMPREPLY=( $("$cmd" --help | awk '{if ($1 ~ /--.*/) print $1}' | grep ^"$2" | sort -u) )
472}
473complete -F _configure_func configure
474
475complete -W '"${GROUPS[@]}"' newgrp
476
477complete -f chown ln more cat
478complete -d mkdir rmdir
479complete -f strip
480
481complete -f -X '*.gz' gzip
Jari Aalto28ef6c32001-04-06 19:14:31 +0000482complete -f -X '*.bz2' bzip2
Jari Aaltobb706242000-03-17 21:46:59 +0000483complete -f -X '*.Z' compress
484complete -f -X '!*.+(gz|tgz|Gz)' gunzip gzcat zcat zmore
485complete -f -X '!*.Z' uncompress zmore zcat
Jari Aalto7117c2d2002-07-17 14:10:11 +0000486complete -f -X '!*.bz2' bunzip2 bzcat
Jari Aalto28ef6c32001-04-06 19:14:31 +0000487complete -f -X '!*.zip' unzip
488complete -f -X '!*.+(gif|jpg|jpeg|GIF|JPG|JPEG|bmp)' xv
Jari Aaltobb706242000-03-17 21:46:59 +0000489
490complete -f -X '!*.pl' perl perl5
491
492complete -A hostname rsh telnet rlogin ftp ping xping host traceroute nslookup
493complete -A hostname rxterm rxterm3 rxvt2
494
495complete -u su
Jari Aaltof73dda02001-11-13 17:56:06 +0000496complete -g newgrp groupdel groupmod
Jari Aaltobb706242000-03-17 21:46:59 +0000497
498complete -f -X '!*.+(ps|PS)' gs gv ghostview psselect pswrap
Jari Aalto28ef6c32001-04-06 19:14:31 +0000499complete -f -X '!*.+(dvi|DVI)' dvips xdvi dviselect dvitype catdvi
500complete -f -X '!*.+(pdf|PDF)' acroread4
Jari Aaltobb706242000-03-17 21:46:59 +0000501complete -f -X '!*.texi*' makeinfo texi2dvi texi2html
502complete -f -X '!*.+(tex|TEX)' tex latex slitex
503
Jari Aalto28ef6c32001-04-06 19:14:31 +0000504complete -f -X '!*.+(mp3|MP3)' mpg123
505complete -f -X '!*.+(htm|html)' links w3m lynx
506
Jari Aaltobb706242000-03-17 21:46:59 +0000507#
508# other possibilities, left as exercises
509#
510#complete -F _find_func find
511#complete -F _man_func man
512#complete -F _stty_func stty