Patch-ID: bash40-021
[bash.git] / examples / complete / complete.ianmac
blob2af9fc74761088bb1702bf5be8edbfe951b62cae
1 #####
2 #To: chet@po.cwru.edu, sarahmckenna@lucent.com
3 #Message-Id: <slrn8mqioc.msb.ian@lovelorn.linuxcare.com>
4 #Posted-To: comp.unix.shell, gnu.bash.bug
5 #Subject: bash 2.04 programmable completion examples
6 #Reply-To: ian@linuxcare.com, ian@caliban.org
7 #Summary: examples of programmable completion for bash 2.04
8 #Date: Thu, 13 Jul 2000 00:52:33 -0400 (EDT)
9 #From: ianmacd@linuxcare.com (Ian Macdonald)
10 #####
12 #########################################################################
13 # Turn on extended globbing
14 shopt -s extglob
16 # A lot of the following one-liners were taken directly from the
17 # completion examples provided with the bash 2.04 source distribution
19 # Make directory commands see only directories
20 complete -d cd mkdir rmdir pushd
22 # Make file commands see only files
23 complete -f cat less more chown ln strip
24 complete -f -X '*.gz' gzip
25 complete -f -X '*.Z' compress
26 complete -f -X '!*.+(Z|gz|tgz|Gz)' gunzip zcat zmore
27 complete -f -X '!*.Z' uncompress zmore zcat
28 complete -f -X '!*.+(gif|jpg|jpeg|GIF|JPG|bmp)' ee xv
29 complete -f -X '!*.+(ps|PS|ps.gz)' gv
30 complete -f -X '!*.+(dvi|DVI)' dvips xdvi dviselect dvitype
31 complete -f -X '!*.+(pdf|PDF)' acroread xpdf
32 complete -f -X '!*.texi*' makeinfo texi2dvi texi2html
33 complete -f -X '!*.+(tex|TEX)' tex latex slitex
34 complete -f -X '!*.+(mp3|MP3)' mpg123
36 # kill sees only signals
37 complete -A signal kill -P '%'
39 # user commands see only users
40 complete -u finger su usermod userdel passwd
42 # bg completes with stopped jobs
43 complete -A stopped -P '%' bg
45 # other job commands
46 complete -j -P '%' fg jobs disown
48 # network commands complete with hostname
49 complete -A hostname ssh rsh telnet rlogin ftp ping fping host traceroute \
50             nslookup
52 # export and others complete with shell variables
53 complete -v export local readonly unset
55 # set completes with set options
56 complete -A setopt set
58 # shopt completes with shopt options
59 complete -A shopt shopt
61 # helptopics
62 complete -A helptopic help
64 # unalias completes with aliases
65 complete -a unalias
67 # various commands complete with commands
68 complete -c command type nohup exec nice eval strace gdb
70 # bind completes with readline bindings (make this more intelligent)
71 complete -A binding bind
73 # Now we get to the meat of the file, the functions themselves. Some
74 # of these are works in progress. Most assume GNU versions of the
75 # tools in question and may require modifications for use on vanilla
76 # UNIX systems.
78 # A couple of functions may have non-portable, Linux specific code in
79 # them, but this will be noted where applicable
82 # GNU chown(1) completion. This should be expanded to allow the use of
83 # ':' as well as '.' as the user.group separator.
85 _chown ()
87         local cur prev user group
89         COMPREPLY=()
90         cur=${COMP_WORDS[COMP_CWORD]}
91         prev=${COMP_WORDS[COMP_CWORD-1]}
93         # do not attempt completion if we're specifying an option
94         if [ "${cur:0:1}" = "-" ]; then return 0; fi
96         # first parameter on line or first since an option?
97         if [ $COMP_CWORD -eq 1 ] || [ "${prev:0:1}" = "-" ]; then
98                 case "$cur" in
99                 [a-zA-Z]*.*)
100                         user=${cur%.*}
101                         group=${cur#*.}
102                         COMPREPLY=( $( awk 'BEGIN {FS=":"} \
103                                         {if ($1 ~ /^'$group'/) print $1}' \
104                                         /etc/group ) )
105                         for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
106                                 COMPREPLY[i]=$user.${COMPREPLY[i]}
107                         done
108                         return 0
109                         ;;
110                 *)
111                         COMPREPLY=( $( compgen -u $cur -S '.' ) )
112                         return 0
113                         ;;
114                 esac
115         else
116                 COMPREPLY=( $( compgen -f $cur ) )
117         fi
119         return 0
121 complete -F _chown chown
123 # umount(8) completion. This relies on the mount point being the third
124 # space-delimited field in the output of mount(8)
126 _umount ()
128         local cur
130         COMPREPLY=()
131         cur=${COMP_WORDS[COMP_CWORD]}
133         # could rewrite the cut | grep to be a sed command, but this is
134         # clearer and doesn't result in much overhead
135         COMPREPLY=( $( mount | cut -d' ' -f 3 | grep ^$cur) )
136         return 0
138 complete -F _umount umount
140 # GID completion. This will get a list of all valid group names from
141 # /etc/group and should work anywhere.
143 _gid_func ()
145         local cur
147         COMPREPLY=()
148         cur=${COMP_WORDS[COMP_CWORD]}
149         COMPREPLY=( $( awk 'BEGIN {FS=":"} {if ($1 ~ /^'$cur'/) print $1}' \
150                            /etc/group ) )
151         return 0
153 complete -F _gid_func groupdel groupmod
155 # mount(8) completion. This will pull a list of possible mounts out of
156 # /etc/fstab, unless the word being completed contains a ':', which
157 # would indicate the specification of an NFS server. In that case, we
158 # query the server for a list of all available exports and complete on
159 # that instead.
161 _mount ()
163 {       local cur
165         COMPREPLY=()
166         cur=${COMP_WORDS[COMP_CWORD]}
168         case "$cur" in
169         *:*)
170               COMPREPLY=( $( /usr/sbin/showmount -e --no-headers ${cur%%:*} |\
171                                grep ^${cur#*:} | awk '{print $1}'))
172                 return 0
173                 ;;
174         *)
175                 COMPREPLY=( $( awk '{if ($2 ~ /\//) print $2}' /etc/fstab | \
176                                grep ^$cur ))
177                 return 0
178                 ;;
179         esac
181 complete -F _mount mount
183 # Linux rmmod(1) completion. This completes on a list of all currently
184 # installed kernel modules.
186 _rmmod ()
188         local cur
190         COMPREPLY=()
191         cur=${COMP_WORDS[COMP_CWORD]}
193         COMPREPLY=($( lsmod | awk '{if (NR != 1 && $1 ~ /^'$cur'/) print $1}'))
194         return 0
196 complete -F _rmmod rmmod
198 # Linux insmod(1) completion. This completes on a list of all
199 # available modules for the version of the kernel currently running.
201 _insmod ()
203         local cur modpath
205         COMPREPLY=()
206         cur=${COMP_WORDS[COMP_CWORD]}
207         modpath=/lib/modules/`uname -r`
209         COMPREPLY=($( ls -R $modpath | sed -ne 's/^\('$cur'.*\)\.o$/\1/p'))
210         return 0
212 complete -F _insmod insmod depmod modprobe
214 # man(1) completion. This relies on the security enhanced version of
215 # GNU locate(1). UNIX variants having non-numeric man page sections
216 # other than l, m and n should add the appropriate sections to the
217 # first clause of the case statement.
219 # This is Linux specific, in that 'man <section> <page>' is the
220 # expected syntax. This allows one to do something like
221 # 'man 3 str<tab>' to obtain a list of all string handling syscalls on
222 # the system.
224 _man ()
226         local cur prev
228         COMPREPLY=()
229         cur=${COMP_WORDS[COMP_CWORD]}
230         prev=${COMP_WORDS[COMP_CWORD-1]}
232         case "$prev" in
233         [0-9lmn])
234                 COMPREPLY=($( slocate -ql 0 -r '/man/man'$prev'/'$cur | \
235                       sed -ne 's/^.*\/\('$cur'[^.\/]*\)\..*$/\1/p' ))
236                 return 0
237                 ;;
238         *)
239                 COMPREPLY=($( slocate -ql 0 -r '/man/man./'$cur | \
240                       sed -ne 's/^.*\/\('$cur'[^.\/]*\)\..*$/\1/p' ))
241                 return 0
242                 ;;
243         esac
245 complete -F _man man
247 # Linux killall(1) completion. This wouldn't be much use on, say,
248 # Solaris, where killall does exactly that: kills ALL processes.
250 # This could be improved. For example, it currently doesn't take
251 # command line options into account
253 _killall ()
255         local cur prev
257         COMPREPLY=()
258         cur=${COMP_WORDS[COMP_CWORD]}
259         prev=${COMP_WORDS[COMP_CWORD-1]}
261         case "$prev" in
262         -[A-Z0-9]*)
263                 # get a list of processes (the first sed evaluation
264                 # takes care of swapped out processes, the second
265                 # takes care of getting the basename of the process)
266                COMPREPLY=( $( ps ahx | awk '{if ($5 ~ /^'$cur'/) print $5}' | \
267                                sed -e 's#[]\[]##g' -e 's#^.*/##' ))
268                 return 0
269                 ;;
270         esac
272         # first parameter can be either a signal or a process
273         if [ $COMP_CWORD -eq 1 ]; then
274                 # standard signal completion is rather braindead, so we need
275                 # to hack around to get what we want here, which is to
276                 # complete on a dash, followed by the signal name minus
277                 # the SIG prefix
278                 COMPREPLY=( $( compgen -A signal SIG${cur#-} ))
279                 for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
280                         COMPREPLY[i]=-${COMPREPLY[i]#SIG}
281                 done
282         fi
284         # get processes, adding to signals if applicable
285         COMPREPLY=( ${COMPREPLY[*]} $( ps ahx | \
286                                        awk '{if ($5 ~ /^'$cur'/) print $5}' | \
287                                        sed -e 's#[]\[]##g' -e 's#^.*/##' ))
288         return 0
290 complete -F _killall killall
292 # GNU find(1) completion. This makes heavy use of ksh style extended
293 # globs and contains Linux specific code for completing the parameter
294 # to the -fstype option.
296 _find ()
298         local cur prev
300         COMPREPLY=()
301         cur=${COMP_WORDS[COMP_CWORD]#-}
302         prev=${COMP_WORDS[COMP_CWORD-1]}
304         case "$prev" in
305         -@(max|min)depth)
306                 COMPREPLY=( $( compgen -W '0 1 2 3 4 5 6 7 8 9' ) )
307                 return 0
308                 ;;
309         -?(a)newer|-fls|-fprint?(0|f))
310                 COMPREPLY=( $( compgen -f $cur ) )
311                 return 0
312                 ;;
313         -fstype)
314                 # this is highly non-portable (the option to -d is a tab)
315                 COMPREPLY=( $( cut -d'  ' -f 2 /proc/filesystems | grep ^$cur ) )
316                 return 0
317                 ;;
318         -gid)
319                 COMPREPLY=( $( awk 'BEGIN {FS=":"} \
320                                 {if ($3 ~ /^'$cur'/) print $3}' /etc/group ) )
321                 return 0
322                 ;;
323         -group)
324                 COMPREPLY=( $( awk 'BEGIN {FS=":"} \
325                                 {if ($1 ~ /^'$cur'/) print $1}' /etc/group ) )
326                 return 0
327                 ;;
328         -?(x)type)
329                 COMPREPLY=( $( compgen -W 'b c d p f l s' $cur ) )
330                 return 0
331                 ;;
332         -uid)
333                 COMPREPLY=( $( awk 'BEGIN {FS=":"} \
334                                 {if ($3 ~ /^'$cur'/) print $3}' /etc/passwd ) )
335                 return 0
336                 ;;
337         -user)
338                 COMPREPLY=( $( compgen -u $cur ) )
339                 return 0
340                 ;;
341         -[acm]min|-[acm]time|-?(i)?(l)name|-inum|-?(i)path|-?(i)regex| \
342         -links|-perm|-size|-used|-exec|-ok|-printf)
343                 # do nothing, just wait for a parameter to be given
344                 return 0
345                 ;;
346         esac
348         # complete using basic options ($cur has had its dash removed here,
349         # as otherwise compgen will bomb out with an error, since it thinks
350         # the dash is an option to itself)
351         COMPREPLY=( $( compgen -W 'daystart depth follow help maxdepth \
352                         mindepth mount noleaf version xdev amin anewer atime \
353                         cmin cnewer ctime empty false fstype gid group ilname \
354                         iname inum ipath iregex links lname mmin mtime name \
355                         newer nouser nogroup perm regex size true type uid \
356                         used user xtype exec fls fprint fprint0 fprintf ok \
357                         print print0 printf prune ls' $cur ) )
359         # this removes any options from the list of completions that have
360         # already been specified somewhere on the command line.
361         COMPREPLY=( $( echo "${COMP_WORDS[@]}-" | \
362                        (while read -d '-' i; do
363                             [ "$i" == "" ] && continue
364                             # flatten array with spaces on either side,
365                             # otherwise we cannot grep on word boundaries of
366                             # first and last word
367                             COMPREPLY=" ${COMPREPLY[@]} "
368                             # remove word from list of completions
369                             COMPREPLY=( ${COMPREPLY/ ${i%% *} / } )
370                         done
371                         echo ${COMPREPLY[@]})
372                   ) )
373         
374         # put dashes back
375         for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
376                 COMPREPLY[i]=-${COMPREPLY[i]}
377         done
378                 
379         return 0
381 complete -F _find find
383 # Linux ifconfig(8) completion
385 _ifconfig ()
387         local cur
389         COMPREPLY=()
390         cur=${COMP_WORDS[COMP_CWORD]}
392         case "${COMP_WORDS[1]}" in
393         -|*[0-9]*)
394                 COMPREPLY=( $( compgen -W '-a up down arp promisc allmulti \
395                                            metric mtu dstaddr netmask add del \
396                                            tunnel irq io_addr mem_start media \
397                                            broadcast pointopoint hw multicast \
398                                            address txqueuelen' $cur ))
399                 COMPREPLY=( $( echo " ${COMP_WORDS[@]}" | \
400                                (while read -d ' ' i; do
401                                    [ "$i" == "" ] && continue
402                                    # flatten array with spaces on either side,
403                                    # otherwise we cannot grep on word
404                                    # boundaries of first and last word
405                                    COMPREPLY=" ${COMPREPLY[@]} "
406                                    # remove word from list of completions
407                                    COMPREPLY=( ${COMPREPLY/ $i / } )
408                                 done
409                                 echo ${COMPREPLY[@]})
410                           ) )
411                 return 0
412                 ;;
413         esac
415         COMPREPLY=( $( ifconfig -a | sed -ne 's/^\('$cur'[^ ]*\).*$/\1/p' ))
417 complete -F _ifconfig ifconfig
419 # Linux ipsec(8) completion (for FreeS/WAN). Very basic.
421 _ipsec ()
423         local cur
425         COMPREPLY=()
426         cur=${COMP_WORDS[COMP_CWORD]}
428         COMPREPLY=( $( compgen -W 'auto barf eroute klipsdebug look manual \
429                                    pluto ranbits rsasigkey setup showdefaults \
430                                    showhostkey spi spigrp tncfg whack' $cur ))
432 complete -F _ipsec ipsec
433 #########################################################################