# bash_completion - some programmable completion functions for bash 2.05a # # $Id: bash_completion,v 1.221 2002/03/26 16:55:10 ianmacd Exp $ # # Copyright (C) Ian Macdonald # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # RELEASE: 20020326 [ -n "$DEBUG" ] && set -v || set +v # Alter the following to reflect the location of this file # [ -z "$BASH_COMPLETION" ] && declare -r BASH_COMPLETION=/etc/bash_completion [ -z "$BASH_COMPLETION_DIR" ] && \ declare -r BASH_COMPLETION_DIR=/etc/bash_completion.d # Set a couple of useful vars # OS=$( uname -s ) RELEASE=$( uname -r ) # Turn on extended globbing and programmable completion shopt -s extglob progcomp # A lot of the following one-liners were taken directly from the # completion examples provided with the bash 2.04 source distribution # Make directory commands see only directories complete -d pushd # The following section lists completions that are redefined later # Do NOT break these over multiple lines. # # START exclude -- do NOT remove this line complete -f -X '!*.bz2' bunzip2 bzcat bzcmp bzdiff bzegrep bzfgrep bzgrep complete -f -X '!*.@(zip|ZIP|jar|JAR|exe|EXE|pk3)' unzip complete -f -X '*.Z' compress znew complete -f -X '!*.@(Z|gz|tgz|Gz)' gunzip zcmp zdiff zcat zegrep zfgrep zgrep zless zmore complete -f -X '!*.Z' uncompress complete -f -X '!*.@(gif|jp?(e)g|tif?(f)|png|p[bgp]m|bmp|xpm|ico|GIF|JPG|JP?(E)G|TIF?(F)|PNG|P[BGP]M|BMP|XPM|ICO)' ee display complete -f -X '!*.@(gif|jp?(e)g|tif?(f)|png|p[bgp]m|bmp|xpm|GIF|JPG|JP?(E)G|TIF?(F)|PNG|P[BGP]M|BMP|XPM)' xv qiv complete -f -X '!*.@(?(e)ps?(.gz)|?(E)PS?(.GZ)|pdf?(.gz)|PDF?(.GZ))' gv ggv complete -f -X '!*.@(dvi|DVI)?(.@(gz|Z|bz2))' xdvi complete -f -X '!*.@(dvi|DVI)' dvips dviselect dvitype complete -f -X '!*.@(pdf|PDF)' acroread xpdf complete -f -X '!*.texi*' makeinfo texi2dvi texi2html complete -f -X '!*.@(tex|TEX)' tex latex slitex jadetex pdfjadetex pdftex pdflatex complete -f -X '!*.@(mp3|MP3)' mpg123 complete -f -X '!*.@(mpg|mpeg|avi|asf|vob|bin|vcd|ps|pes|fli|viv|rm|ram|yuv|mov|wmv)' mplayer complete -f -X '!*.@(avi|asf)' aviplay complete -f -X '!*.@(rm|ram|smi?(l))' realplay complete -f -X '!*.@(mpg|mpeg|avi|mov)' xanim complete -f -X '!*.@(ogg|OGG)' ogg123 complete -f -X '!*.@(mp3|MP3|ogg|OGG|pls)' xmms gqmpeg freeamp complete -f -X '!*.fig' xfig complete -f -X '!*.@(mid?(i))' timidity playmidi complete -f -X '*.@(o|so|so.*|a|tar|?(t)gz|?(t)bz2|rpm|zip|ZIP|gif|GIF|jp?(e)g|JP?(E)G|mp3|MP3|mpg|MPG|avi|AVI|asf|ASF' vi vim emacs complete -f -X '!*.@(exe|EXE|com|COM)' wine # FINISH exclude -- do not remove this line # start of section containing compspecs that can be handled within bash # user commands see only users complete -u finger su usermod userdel passwd chage write talk chfn # group commands see only groups complete -g groupmod groupdel # bg completes with stopped jobs complete -A stopped -P '%' bg # other job commands complete -j -P '%' fg jobs disown # export and others complete with shell variables complete -v readonly unset # set completes with set options complete -A setopt set # shopt completes with shopt options complete -A shopt shopt # helptopics complete -A helptopic help # unalias completes with aliases complete -a unalias # bind completes with readline bindings (make this more intelligent) complete -A binding bind # type completes with commands complete -c command type # start of section containing completion functions called by other functions # This function checks whether we have a given programs on the system. # No need for bulky functions in memory if we don't. # have() { unset -v have type $1 &> /dev/null [ $? -eq 0 ] && have="yes" } # This function performs file and directory completion. It's better than # simply using 'compgen -f', because it honours spaces in filenames # _filedir() { local IFS=$'\t\n' _expand || return 0 if [ "$1" = -d ]; then COMPREPLY=( ${COMPREPLY[@]} $( compgen -d -- $cur ) ) return 0 fi COMPREPLY=( ${COMPREPLY[@]} $( eval compgen -f -- \"$cur\" ) ) } # This function completes on signal names # _signals() { local i # standard signal completion is rather braindead, so we need # to hack around to get what we want here, which is to # complete on a dash, followed by the signal name minus # the SIG prefix COMPREPLY=( $( compgen -A signal SIG${cur#-} )) for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do COMPREPLY[i]=-${COMPREPLY[i]#SIG} done } # This function expands tildes in pathnames # _expand() { [ "$cur" != "${cur%\\}" ] && cur="$cur"'\' # expand ~username type directory specifications if [[ "$cur" == \~*/* ]]; then eval cur=$cur elif [[ "$cur" == \~* ]]; then cur=${cur#\~} COMPREPLY=( $( compgen -P '~' -u $cur ) ) return ${#COMPREPLY[@]} fi } # start of section containing completion functions for bash built-ins # bash alias completion # _alias() { local cur COMPREPLY=() cur=${COMP_WORDS[$COMP_CWORD]}; case "$COMP_LINE" in *[^=]) COMPREPLY=( $( compgen -A alias -S '=' -- $cur ) ) ;; *=) COMPREPLY=( "$( alias ${cur%=} 2>/dev/null | \ sed -e 's|^alias '$cur'\(.*\)$|\1|' )" ) ;; esac } complete -F _alias alias # bash export completion # _export() { local cur COMPREPLY=() cur=${COMP_WORDS[$COMP_CWORD]}; case "$COMP_LINE" in *[^=]) COMPREPLY=( $( compgen -v -S '=' -- $cur ) ) ;; *=) COMPREPLY=( $( eval echo $`echo ${cur%=}` ) ) ;; esac } complete -F _export -o default export # bash shell function completion # _function() { local cur prev COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} if [[ $1 == @(declare|typeset) ]]; then if [ "$prev" = -f ]; then COMPREPLY=( $( compgen -A function -- $cur ) ) elif [[ "$cur" == -* ]]; then COMPREPLY=( $( compgen -W '-a -f -F -i -r -x -p' -- \ $cur ) ) fi elif [ $COMP_CWORD -eq 1 ]; then COMPREPLY=( $( compgen -A function -- $cur ) ) else COMPREPLY=( "() $( type -- ${COMP_WORDS[1]} | sed -e 1,2d )" ) fi } complete -F _function function declare typeset # start of section containing completion functions for external programs # chown(1) completion # _chown() { local cur prev user group i COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} # do not attempt completion if we're specifying an option [[ "$cur" == -* ]] && return 0 # first parameter on line or first since an option? if [ $COMP_CWORD -eq 1 ] || [[ "$prev" == -* ]]; then if [[ "$cur" == [a-zA-Z]*[.:]* ]]; then user=${cur%%?(\\)[.:]*} group=${cur#*[.:]} COMPREPLY=( $( compgen -P $user'\:' -g -- $group ) ) else COMPREPLY=( $( compgen -S '\:' -u $cur ) ) fi fi return 0 } complete -F _chown -o default chown # chgrp(1) completion # _chgrp() { local cur prev COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} # do not attempt completion if we're specifying an option [[ "$cur" == -* ]] && return 0 # first parameter on line or first since an option? if [ $COMP_CWORD -eq 1 ] || [[ "$prev" == -* ]]; then _expand || return 0 COMPREPLY=( $( compgen -g $cur ) ) fi return 0 } complete -F _chgrp -o default chgrp # umount(8) completion. This relies on the mount point being the third # space-delimited field in the output of mount(8) # _umount() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} COMPREPLY=( $( mount | cut -d' ' -f 3 | grep ^$cur ) ) return 0 } complete -F _umount -o filenames umount # mount(8) completion. This will pull a list of possible mounts out of # /etc/fstab, unless the word being completed contains a ':', which # would indicate the specification of an NFS server. In that case, we # query the server for a list of all available exports and complete on # that instead. # _mount() { local cur i sm COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} for i in {,/usr}/{,s}bin/showmount; do [ -x $i ] && sm=$i && break; done if [ -n "$sm" ] && [[ "$cur" == *:* ]]; then COMPREPLY=( $( $sm -e ${cur%%:*} | sed 1d | \ grep ^${cur#*:} | awk '{print $1}' ) ) else COMPREPLY=( $( awk '{if ($2 ~ /\//) print $2}' /etc/fstab | \ grep ^$cur ) ) fi return 0 } complete -F _mount -o default mount # Linux rmmod(1) completion. This completes on a list of all currently # installed kernel modules. # [ $OS = Linux ] && _rmmod() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} COMPREPLY=( $( /sbin/lsmod | \ awk '{if (NR != 1 && $1 ~ /^'$cur'/) print $1}' ) ) return 0 } [ $OS = Linux ] && complete -F _rmmod rmmod # Linux insmod(8) & modprobe(8) completion. This completes on a list of all # available modules for the version of the kernel currently running. # [ $OS = Linux ] && _insmod() { local cur prev modpath COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} modpath=/lib/modules/`uname -r` # behave like lsmod for modprobe -r if [ $1 = "modprobe" ] && [ "${COMP_WORDS[1]}" = "-r" ]; then COMPREPLY=( $( /sbin/lsmod | \ awk '{if (NR != 1 && $1 ~ /^'$cur'/) print $1}' ) ) return 0 fi # do filename completion if we're giving a path to a module if [[ "$cur" == /* ]]; then _filedir return 0 fi if [ $COMP_CWORD -gt 1 ]; then # do module parameter completion COMPREPLY=( $( /sbin/modinfo -p ${COMP_WORDS[1]} 2>/dev/null | \ awk '{if ($1 ~ /^parm:/ && $2 ~ /^'$cur'/) { print $2 } \ else if ($1 !~ /:/ && $1 ~ /^'$cur'/) { print $1 }}' ) ) elif [ -r $modpath -a -x $modpath ]; then # do module name completion COMPREPLY=( $( \ls -R $modpath | \ sed -ne 's|^\('$cur'.*\)\.o$|\1|p') ) else _filedir fi return 0 } [ $OS = Linux ] && complete -F _insmod -o filenames insmod modprobe # man(1) completion. This is Linux and Darwin specific, in that # 'man
' is the expected syntax. # [ $OS = Linux -o $OS = Darwin ] && _man() { local cur prev sect manpath OS COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} _expand || return 0 # default completion if parameter contains / if [[ "$cur" == */* ]]; then _filedir return 0 fi OS=$( uname -s ) if [ $OS = Linux ]; then manpath=$( manpath 2>/dev/null || man --path ) else manpath=$MANPATH fi if [ -z "$manpath" ]; then COMPREPLY=( $( compgen -c -- $cur ) ) return 0 fi # determine manual section to search [[ "$prev" == [0-9ln] ]] && sect=$prev || sect='?' manpath=$manpath: if [ -n "$cur" ]; then manpath="${manpath//://man$sect/$cur* }" else manpath="${manpath//://man$sect/ }" fi # redirect stderr for when path doesn't exist COMPREPLY=( $( eval \\ls "$manpath" 2>/dev/null ) ) # weed out directory path names and paths to man pages COMPREPLY=( ${COMPREPLY[@]##*/?(:)} ) # strip suffix from man pages COMPREPLY=( ${COMPREPLY[@]%.@(gz|bz2)} ) COMPREPLY=( ${COMPREPLY[@]%.*} ) if [[ "$prev" != [0-9ln] ]]; then COMPREPLY=( ${COMPREPLY[@]} $( compgen -d -- $cur ) \ $( compgen -f -X '!*.[0-9ln]' -- $cur ) ) fi return 0 } [ $OS = Linux -o $OS = Darwin ] && complete -F _man -o filenames man # kill(1) completion # _kill() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} if [ $COMP_CWORD -eq 1 ] && [[ "$cur" == -* ]]; then # return list of available signals _signals else # return list of available PIDs COMPREPLY=( $( \ls /proc | grep '^[0-9]\+'| grep ^$cur ) ) fi } complete -F _kill kill # Linux and FreeBSD killall(1) completion. # [ $OS = Linux -o $OS = FreeBSD ] && _killall() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} if [ $COMP_CWORD -eq 1 ] && [[ "$cur" == -* ]]; then _signals else COMPREPLY=( $( compgen -W '$( ps axo ucomm | sed 1d )' \ -- $cur ) ) fi return 0 } [ $OS = Linux -o $OS = FreeBSD ] && complete -F _killall killall # GNU find(1) completion. This makes heavy use of ksh style extended # globs and contains Linux specific code for completing the parameter # to the -fstype option. # _find() { local cur prev COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} case "$prev" in -@(max|min)depth) COMPREPLY=( $( compgen -W '0 1 2 3 4 5 6 7 8 9' -- $cur ) ) return 0 ;; -?(a)newer|-fls|-fprint?(0|f)|-?(i)?(l)name) _filedir return 0 ;; -fstype) # this is highly non-portable COMPREPLY=( $( cut -d$'\t' -f 2 /proc/filesystems | grep ^$cur)) return 0 ;; -gid) COMPREPLY=( $( awk 'BEGIN {FS=":"} \ {if ($3 ~ /^'$ncur'/) print $3}' /etc/group ) ) return 0 ;; -group) COMPREPLY=( $( compgen -g -- $cur ) ) return 0 ;; -?(x)type) COMPREPLY=( $( compgen -W 'b c d p f l s' -- $cur ) ) return 0 ;; -uid) COMPREPLY=( $( awk 'BEGIN {FS=":"} \ {if ($3 ~ /^'$ncur'/) print $3}' /etc/passwd ) ) return 0 ;; -user) COMPREPLY=( $( compgen -u -- $cur ) ) return 0 ;; -[acm]min|-[acm]time|-?(i)?(l)name|-inum|-?(i)path|-?(i)regex| \ -links|-perm|-size|-used|-exec|-ok|-printf) # do nothing, just wait for a parameter to be given return 0 ;; esac _expand || return 0 # handle case where first parameter is not a dash option if [ $COMP_CWORD -eq 1 ] && [[ "$cur" != -* ]]; then _filedir -d return 0 fi # complete using basic options COMPREPLY=( $( compgen -W '-daystart -depth -follow -help -maxdepth \ -mindepth -mount -noleaf -version -xdev -amin -anewer \ -atime -cmin -cnewer -ctime -empty -false -fstype \ -gid -group -ilname -iname -inum -ipath -iregex \ -links -lname -mmin -mtime -name -newer -nouser \ -nogroup -perm -regex -size -true -type -uid -used \ -user -xtype -exec -fls -fprint -fprint0 -fprintf -ok \ -print -print0 -printf -prune -ls' -- $cur ) ) # this removes any options from the list of completions that have # already been specified somewhere on the command line. COMPREPLY=( $( echo "${COMP_WORDS[@]}" | \ (while read -d ' ' i; do [ "$i" == "" ] && continue # flatten array with spaces on either side, # otherwise we cannot grep on word boundaries of # first and last word COMPREPLY=" ${COMPREPLY[@]} " # remove word from list of completions COMPREPLY=( ${COMPREPLY/ ${i%% *} / } ) done echo ${COMPREPLY[@]}) ) ) return 0 } complete -F _find -o filenames find # Linux ifconfig(8) completion # [ $OS = Linux ] && _ifconfig() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} case "${COMP_WORDS[1]}" in -|*[0-9]*) COMPREPLY=( $( compgen -W '-a up down arp promisc allmulti \ metric mtu dstaddr netmask add del \ tunnel irq io_addr mem_start media \ broadcast pointopoint hw multicast \ address txqueuelen' $cur )) COMPREPLY=( $( echo " ${COMP_WORDS[@]}" | \ (while read -d ' ' i; do [ "$i" == "" ] && continue # flatten array with spaces on either side, # otherwise we cannot grep on word # boundaries of first and last word COMPREPLY=" ${COMPREPLY[@]} " # remove word from list of completions COMPREPLY=( ${COMPREPLY/ $i / } ) done echo ${COMPREPLY[@]}) ) ) return 0 ;; esac COMPREPLY=( $( /sbin/ifconfig -a | \ sed -ne 's|^\('$cur'[^ ]*\).*$|\1|p' )) } [ $OS = Linux ] && complete -F _ifconfig ifconfig # RedHat & Debian Linux if{up,down} completion # [ $OS = Linux ] && ( have ifup || have ifdown ) && _ifupdown() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} if [ $COMP_CWORD -eq 1 ]; then if [ -f /etc/debian_version ]; then # Debian system COMPREPLY=( $( sed -ne 's|^iface \([^ ]\+\).*$|\1|p' /etc/network/interfaces ) ) else # Assume Red Hat COMPREPLY=( $( \ls /etc/sysconfig/network-scripts/ifcfg-* | sed -ne 's|.*ifcfg-\('$cur'.*\)|\1|p' ) ) fi fi return 0 } [ $OS = Linux ] && have ifup && complete -F _ifupdown ifup ifdown # Linux ipsec(8) completion (for FreeS/WAN). Basic. # [ $OS = Linux ] && have ipsec && _ipsec() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} if [ $COMP_CWORD -eq 1 ]; then COMPREPLY=( $( compgen -W 'auto barf eroute klipsdebug look \ manual pluto ranbits rsasigkey \ setup showdefaults showhostkey spi \ spigrp tncfg whack' $cur ) ) return 0 fi case ${COMP_WORDS[1]} in auto) COMPREPLY=( $( compgen -W '--asynchronous --up --add --delete \ --replace --down --route --unroute \ --ready --status --rereadsecrets' \ $cur ) ) ;; manual) COMPREPLY=( $( compgen -W '--up --down --route --unroute \ --union' $cur ) ) ;; ranbits) COMPREPLY=( $( compgen -W '--quick --continuous --bytes' $cur ) ) ;; setup) COMPREPLY=( $( compgen -W '--start --stop --restart' $cur ) ) ;; *) ;; esac return 0 } [ $OS = Linux ] && [ "$have" ] && complete -F _ipsec ipsec # cvs(1) completion # have cvs && _cvs() { set_prefix() { [ -z "$prefix" ] || prefix=${cur%/*}/ [ -r ${prefix}CVS/Entries ] || prefix="" } get_entries() { entries=( $( cut -d/ -f2 -s ${prefix}CVS/Entries | \ grep "^$cur" ) ) } get_modules() { if [ -n "$prefix" ]; then COMPREPLY=( $( \ls -d ${cvsroot}/${prefix}/!(CVSROOT) )) else COMPREPLY=( $( \ls -d ${cvsroot}/!(CVSROOT) ) ) fi } local cur count mode i cvsroot pwd local -a flags miss files entries changed newremoved COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} count=1 for i in ${COMP_WORDS[@]}; do [ $count -eq $COMP_CWORD ] && break if [ -z "$mode" ]; then case $i in -d) cvsroot=${COMP_WORDS[((++count))]} ;; @(add|new)) mode=add ;; @(admin|rcs)) mode=admin ;; @(checkout|co|get)) mode=checkout ;; @(commit|ci)) mode=commit ;; @(diff|@(ex|im)port|history|release|status|update)) mode=$i ;; ?(r)log) mode=log ;; @(rdiff|patch)) mode=rdiff ;; @(remove|rm|delete)) mode=remove ;; @(rtag|rfreeze)) mode=rtag ;; @(tag|freeze)) mode=tag ;; *) ;; esac continue elif [[ "$i" = -* ]]; then flags=( ${flags[@]} $i ) fi count=$((++count)) done case "$mode" in add) if [[ "$cur" != -* ]]; then set_prefix if [ $COMP_CWORD -gt 1 -a -r ${prefix}CVS/Entries ]; then get_entries [ -z "$cur" ] && \ files=$( \ls -A | grep -v '^CVS$' ) || \ files=$( \ls -d ${cur}* ) for i in ${entries[@]}; do files=( ${files[@]%$i} ) done COMPREPLY=( $( compgen -W '${files[@]}' -- \ $cur ) ) fi else COMPREPLY=( $( compgen -W '-k -m' -- $cur ) ) fi ;; admin) if [[ "$cur" = -* ]]; then COMPREPLY=( $( compgen -W '-i -a -A -e -b -c -k -l -u \ -L -U -m -M -n -N -o -q -I \ -s -t -t- -T -V -x -z' -- \ $cur ) ) fi ;; checkout) if [[ "$cur" != -* ]]; then # can only do for local repositories [ -z "$cvsroot" ] && cvsroot=$CVSROOT prefix=${cur%/*} [ -r ${cvsroot}/${prefix} ] || prefix="" if [ -r ${cvsroot}/${prefix} ]; then get_modules COMPREPLY=( ${COMPREPLY[@]#$cvsroot} ) COMPREPLY=( ${COMPREPLY[@]#/} ) COMPREPLY=( $( compgen -W \ '${COMPREPLY[@]}' -- $cur ) ) fi else COMPREPLY=( $( compgen -W '-A -N -P -R -c -f -l -n -p \ -s -r -D -d -k -j' -- $cur ) ) fi ;; commit) set_prefix if [[ "$cur" != -* ]] && [ -r ${prefix}CVS/Entries ]; then # this is the least computationally intensive way # found so far, but other changes (something other than # changed/removed/new) may be missing changed=( $( cvs diff --brief 2>&1 | \ sed -ne 's/^Files [^ ]* and \([^ ]*\) differ$/\1/p' ) ) newremoved=( $( cvs diff --brief 2>&1 | \ sed -ne 's/^cvs diff: \([^ ]*\) .*, no comparison available$/\1/p' ) ) COMPREPLY=( $( compgen -W '${changed[@]} \ ${newremoved[@]}' -- $cur ) ) else COMPREPLY=( $( compgen -W '-n -R -l -f -F -m -r' -- \ $cur ) ) fi ;; remove) if [[ "$cur" != -* ]]; then set_prefix if [ $COMP_CWORD -gt 1 -a -r ${prefix}CVS/Entries ]; then get_entries # find out what files are missing for i in ${entries[@]}; do [ ! -r "$i" ] && miss=( ${miss[@]} $i ) done COMPREPLY=( $(compgen -W '${miss[@]}' -- $cur) ) fi else COMPREPLY=( $( compgen -W '-f -l -R' -- $cur ) ) fi ;; import) if [[ "$cur" != -* ]]; then # starts with same algorithm as checkout [ -z "$cvsroot" ] && cvsroot=$CVSROOT prefix=${cur%/*} if [ -r ${cvsroot}/${prefix} ]; then get_modules COMPREPLY=( ${COMPREPLY[@]#$cvsroot} ) COMPREPLY=( ${COMPREPLY[@]#\/} ) fi pwd=$( pwd ) pwd=${pwd##*/} COMPREPLY=( $( compgen -W '${COMPREPLY[@]} $pwd' -- \ $cur ) ) else COMPREPLY=( $( compgen -W '-d -k -I -b -m -W' -- $cur )) fi ;; "") COMPREPLY=( $( compgen -W 'add admin checkout ci co commit \ diff delete export freeze get \ history import log new patch rcs \ rdiff release remove rfreeze rlog \ rm rtag status tag update -H -Q -q \ -b -d -e -f -l -n -t -r -v -w -x \ -z --help --version' -- $cur ) ) ;; *) ;; esac return 0 } [ "$have" ] && complete -F _cvs -o default cvs # rpm(8) completion # have rpm && _rpm() { add_package_list() { if [ -r /var/log/rpmpkgs -a \ /var/log/rpmpkgs -nt /var/lib/rpm/Packages ]; then # using RHL 7.2 - this is quicker than querying the DB COMPREPLY=( ${COMPREPLY[@]} \ $( sed -ne 's|^\('$cur'.*\)-[0-9a-zA-Z._]\+-[0-9a-z.]\+.*\.rpm$|\1|p' /var/log/rpmpkgs ) ) else COMPREPLY=( ${COMPREPLY[@]} $( rpm -qa | \ sed -ne 's|^\('$cur'.*\)-[0-9a-zA-Z._]\+-[0-9a-z.]\+$|\1|p' ) ) fi } file_glob() { _expand || return 0 COMPREPLY=( ${COMPREPLY[@]} $( compgen -f -X "!*.$1" -- $cur ) ) COMPREPLY=( ${COMPREPLY[@]} $( compgen -d -- $cur ) ) } uninstalled_packages() { COMPREPLY=( $( compgen -W '--scripts --root --rcfile \ --whatprovides --whatrequires --requires --triggeredby \ --ftpport --ftpproxy --httpproxy --httpport --provides \ --triggers --dump --changelog --dbpath --filesbypkg --define \ --eval --pipe --showrc --info --list --state --docfiles \ --configfiles --queryformat --conflicts --obsoletes' -- $cur ) ) # return if $cur is an option [[ "$cur" == -* ]] && return 0 # add a list of RPMS to possible completions file_glob rpm } local cur prev COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} if [ $COMP_CWORD -eq 1 ]; then # first parameter on line case "$cur" in -b*) COMPREPLY=( $( compgen -W '-ba -bb -bc -bi -bl -bp -bs'\ -- $cur ) ) ;; -t*) COMPREPLY=( $( compgen -W '-ta -tb -tc -ti -tl -tp -ts'\ -- $cur ) ) ;; --*) COMPREPLY=( $( compgen -W '--help --version --initdb \ --checksig --recompile --rebuild --resign --addsign \ --rebuilddb --showrc --setperms --setugids --tarbuild \ --eval --install --upgrade --query --freshen --erase \ --verify --querytags --rmsource --rmspec --clean' -- \ $cur ) ) ;; *) COMPREPLY=( $( compgen -W '-b -e -F -i -q -t -U -V' \ -- $cur ) ) ;; esac return 0 fi case "$prev" in --@(@(db|exclude)path|prefix|relocate|root)) _filedir -d return 0 ;; --eval) # get a list of macros COMPREPLY=( $( sed -ne 's|^\(%'${cur#\%}'[^ '$'\t'']*\).*$|\1|p' \ /usr/lib/rpm/macros ) ) return 0 ;; --pipe) COMPREPLY=( $( compgen -c -- $cur ) ) return 0 ;; --rcfile) _filedir return 0 ;; --specfile) # complete on .spec files file_glob spec return 0 ;; --whatprovides) if [[ "$cur" == */* ]]; then _filedir else # complete on capabilities COMPREPLY=( $( rpm -qa --queryformat '%{providename}\n' | grep ^$cur ) ) fi return 0 ;; --whatrequires) # complete on capabilities COMPREPLY=( $( rpm -qa --queryformat '%{requirename}\n' | grep ^$cur ) ) return 0 ;; esac case "${COMP_WORDS[1]}" in -@([iFU]*|-install|-freshen|-upgrade)) COMPREPLY=( $( compgen -W '--percent --force --test \ --replacepkgs --replacefiles --root --excludedocs \ --includedocs --noscripts --rcfile --ignorearch --dbpath \ --prefix --ignoreos --nodeps --allfiles --ftpproxy --ftpport \ --justdb --httpproxy --httpport --noorder --relocate \ --badreloc --notriggers --excludepath --ignoresize \ --oldpackage --define --eval --pipe --queryformat \ --repackage' -- $cur ) ) # return if $cur is an option [[ "$cur" == -* ]] && return 0 # add a list of RPMS to possible completions file_glob rpm ;; -q*p*) uninstalled_packages ;; -*f) # standard filename completion _filedir ;; -@(e|-erase)) COMPREPLY=( $( compgen -W '--allmatches --noscripts \ --notriggers --nodeps --test --repackage' -- $cur ) ) # return if $cur is an option [[ "$cur" == -* ]] && return 0 add_package_list ;; -q*) # check whether we're querying installed or uninstalled if [ "${COMP_LINE#*-*([^ ])p}" != "$COMP_LINE" ]; then # there's a -p on the line uninstalled_packages return 0 else COMPREPLY=( $( compgen -W '--scripts --root --rcfile \ --whatprovides --whatrequires --requires --triggeredby \ --ftpport --ftpproxy --httpproxy --httpport --provides \ --triggers --dump --changelog --dbpath --specfile \ --querybynumber --last --filesbypkg --define --eval \ --pipe --showrc --info --list --state --docfiles \ --configfiles --queryformat --conflicts --obsoletes \ --pkgid --hdrid --fileid --tid' -- $cur ) ) fi # return if $cur is an option [[ "$cur" == -* ]] && return 0 # don't complete on packages if we are querying all packages [[ ${COMP_WORDS[1]} == -qa* ]] && return 0 add_package_list ;; -@(K|-checksig)) COMPREPLY=( $( compgen -W '--nopgp --nogpg --nomd5' -- $cur ) ) # return if $cur is an option [[ "$cur" == -* ]] && return 0 # add a list of RPMS to possible completions file_glob rpm ;; -@([Vy]*|-verify)) COMPREPLY=( $( compgen -W '--root --rcfile --dbpath --nodeps \ --nofiles --noscripts --nomd5 --querytags --specfile \ --whatrequires --whatprovides' -- $cur ) ) # return if $cur is an option [[ "$cur" == -* ]] && return 0 if [ "${COMP_LINE#*-*([^ ])p}" != "$COMP_LINE" ]; then file_glob rpm else add_package_list fi ;; -[bt]*) COMPREPLY=( $( compgen -W '--short-circuit --timecheck \ --clean --rmsource --rmspec --test --sign --buildroot \ --targetbuildarch --buildos --nobuild --nodeps --nodirtokens' \ -- $cur ) ) # return if $cur is an option [[ "$cur" == -* ]] && return 0 if [[ ${COMP_WORDS[1]} == -b* ]]; then # complete on .spec files file_glob spec else _expand || return 0 # complete on .tar files file_glob '@(tgz|tar.@(gz|bz2))' fi ;; --re@(build|compile)) _expand || return 0 COMPREPLY=( $( compgen -W '--nodeps --rmsource --rmspec \ --sign --nodirtokens' -- $cur ) ) # return if $cur is an option [[ "$cur" == -* ]] && return 0 # complete on source RPMs COMPREPLY=( ${COMPREPLY[@]} $( compgen -f -X '!*.src.rpm' -- \ $cur ) ) COMPREPLY=( ${COMPREPLY[@]} $( compgen -d -- $cur ) ) ;; --tarbuild) _expand || return 0 # complete on tarred sources file_glob '@(tgz|tar.@(gz|bz2))' ;; --@(re|add)sign) # complete on RPMs file_glob rpm ;; --set@(perms|gids)) add_package_list ;; --@(clean|rms@(ource|pec))) COMPREPLY=( $( compgen -W '--clean --rmsource --rmspec' -- \ $cur ) ) # return if $cur is an option [[ "$cur" == -* ]] && return 0 file_glob spec ;; -*g) # package group completion local IFS=$'\t' # remove trailing backslash, or grep will complain cur=${cur%'\'} COMPREPLY=( $( rpm -qa --queryformat '%{group}\n' | \ grep ^$cur ) ) # backslash escape spaces and translate newlines to tabs COMPREPLY=( $( echo ${COMPREPLY[@]} | sed 's/ /\\ /g' | \ tr '\n' '\t' ) ) ;; esac return 0 } [ "$have" ] && complete -F _rpm -o filenames rpm # Debian Linux apt-get(8) completion. # have apt-get && _apt_get() { local cur prev special i COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} for (( i=0; i < ${#COMP_WORDS}-1; i++ )); do if [[ ${COMP_WORDS[i]} == @(install|remove|source) ]]; then special=${COMP_WORDS[i]} fi done if [ -n "$special" ]; then case $special in @(install|remove|source)) COMPREPLY=( $( apt-cache pkgnames $cur ) ) return 0 ;; esac fi if [[ "$prev" == -*c ]] || [ "$prev" = --config-file ]; then _filedir else COMPREPLY=( $( compgen -W 'update upgrade dselect-upgrade \ dist-upgrade install remove source check \ clean autoclean -d -f -h -v -m -q -s -y -u \ -b -c -o --download-only --fix-broken --help \ --version --ignore-missing --fix-missing \ --no-download --quiet --simulate \ --just-print --dry-run --recon --no-act \ --yes --assume-yes --show-upgraded \ --compile --build --ignore-hold \ --no-upgrade --force-yes --print-uris \ --purge --reinstall --list-cleanup \ --trivial-only --no-remove --diff-only \ --tar-only --config-file --option' -- $cur ) ) fi return 0 } [ "$have" ] && complete -F _apt_get -o filenames apt-get # Debian Linux apt-cache(8) completion. # have apt-cache && _apt_cache() { local cur prev special i COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} for (( i=0; i < ${#COMP_WORDS}-1; i++ )); do if [[ ${COMP_WORDS[i]} == @(add|show?(pkg)|depends|dotty) ]]; then special=${COMP_WORDS[i]} fi done if [ -n "$special" ]; then case $special in add) _filedir return 0 ;; show?(pkg)|depends|dotty) COMPREPLY=( $( apt-cache pkgnames $cur ) ) return 0 ;; esac fi if [[ "$prev" == -*c ]] || [ "$prev" = --config-file ]; then _filedir else COMPREPLY=( $( compgen -W 'add gencaches showpkg stats dump \ dumpavail unmet check search show dotty \ depends pkgnames -h -v -p -s -q -i -f -a -g -c \ -o --help --version --pkg-cache --src-cache \ --quiet --important --full --all-versions \ --no-generate --names-only --all-names \ --config-file --option' -- $cur ) ) fi return 0 } [ "$have" ] && complete -F _apt-cache -o filenames apt-cache complete -F _apt_cache -o filenames apt-cache # chsh(1) completion # _chsh() { local cur prev COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} if [ "$prev" = "-s" ]; then COMPREPLY=( $( chsh -l | grep ^$cur ) ) else COMPREPLY=( $( compgen -u -- $cur ) ) fi return 0 } complete -F _chsh chsh # chkconfig(8) completion # have chkconfig && _chkconfig() { local cur prev COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} if [ $COMP_CWORD -eq 1 ]; then COMPREPLY=( $( compgen -W '--list --add --del --level' -- \ $cur ) ) return 0 fi if [ $COMP_CWORD -eq 4 ]; then COMPREPLY=( $( compgen -W 'on off reset' -- $cur ) ) return 0 fi case "$prev" in @([1-6]|--@(list|add|del))) COMPREPLY=( $( compgen -W "`(cd /etc/rc.d/init.d; echo *)`" \ -- $cur) ) return 0 ;; --level) COMPREPLY=( $( compgen -W '1 2 3 4 5 6' -- $cur ) ) return 0 ;; esac return 0 } [ "$have" ] && complete -F _chkconfig chkconfig # This function performs host completion based on ssh's known_hosts files, # defaulting to standard host completion if they don't exist. # _known_hosts() { local cur user suffix local -a kh COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} [ "$1" = -c ] && suffix=':' [[ $cur == *@* ]] && user=${cur%@*}@ && cur=${cur#*@} kh=() [ -r /etc/known_hosts ] && kh[0]=/etc/known_hosts [ -r /etc/known_hosts2 ] && kh[1]=/etc/known_hosts2 [ -r ~/.ssh/known_hosts ] && kh[2]=~/.ssh/known_hosts [ -r ~/.ssh/known_hosts2 ] && kh[3]=~/.ssh/known_hosts2 # If we have known_hosts files to use if [ ${#kh[@]} -gt 0 ]; then # Escape slashes and dots in paths for awk cur=${cur//\//\\\/} cur=${cur//\./\\\.} if [[ "$cur" == [0-9]*.* ]]; then # Digits followed by a dot - just search for that cur="^$cur.*" elif [[ "$cur" == [0-9]* ]]; then # Digits followed by no dot - search for digits followed # by a dot cur="^$cur.*\." elif [ -z "$cur" ]; then # A blank - search for a dot or an alpha character cur="[a-z.]" else cur="^$cur" fi # FS needs to look for a comma separated list COMPREPLY=( $( awk 'BEGIN {FS=","} {for (i=1; i<=2; ++i) { \ gsub(" .*$", "", $i); \ if ($i ~ /'$cur'/) {print $i} \ }}' ${kh[@]} ) ) for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do COMPREPLY[i]=$user${COMPREPLY[i]}$suffix done else # Just do normal hostname completion COMPREPLY=( $( compgen -A hostname -S "$suffix" -- $cur ) ) fi return 0 } complete -F _known_hosts traceroute ping fping telnet host nslookup rsh \ rlogin ftp # ssh(1) completion # have ssh && _ssh() { local cur prev COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} case "$prev" in -*c) COMPREPLY=( $( compgen -W 'blowfish 3des 3des-cbc blowfish-cbc \ arcfour cast128-cbc' -- $cur ) ) ;; -*l) COMPREPLY=( $( compgen -u -- $cur ) ) ;; *) _known_hosts [ $COMP_CWORD -eq 1 ] || \ COMPREPLY=( ${COMPREPLY[@]} $( compgen -c -- $cur ) ) esac return 0 } [ "$have" ] && shopt -u hostcomplete && complete -F _ssh ssh slogin sftp # scp(1) completion # have scp && _scp() { local cur userhost path COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} _expand || return 0 if [[ "$cur" == *:* ]]; then # remove backslash escape from : cur=${cur/\\:/:} userhost=${cur%%?(\\):*} path=${cur#*:} if [ -z "$path" ]; then # default to home dir of specified user on remote host path=$( ssh -o 'Batchmode yes' $userhost pwd ) fi COMPREPLY=( $( compgen -P "$userhost:" \ -W "`echo $( ssh -o 'Batchmode yes' $userhost \ compgen -f -- $path )`" ) ) return 0 fi [[ "$cur" == */* ]] || _known_hosts -c _filedir return 0 } [ "$have" ] && complete -o filenames -F _scp scp # Linux route(8) completion # [ $OS = Linux ] && _route() { local cur prev COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} if [ "$prev" = dev ]; then COMPREPLY=( $( ifconfig -a | sed -ne 's|^\('$cur'[^ ]*\).*$|\1|p' )) return 0 fi COMPREPLY=( $( compgen -W 'add del -host -net netmask metric mss \ window irtt reject mod dyn reinstate dev' \ -- $cur ) ) COMPREPLY=( $( echo " ${COMP_WORDS[@]}" | \ (while read -d ' ' i; do [ "$i" == "" ] && continue # flatten array with spaces on either side, # otherwise we cannot grep on word # boundaries of first and last word COMPREPLY=" ${COMPREPLY[@]} " # remove word from list of completions COMPREPLY=( ${COMPREPLY/ $i / } ) done echo ${COMPREPLY[@]}) ) ) return 0 } [ $OS = Linux ] && complete -F _route route # GNU make(1) completion (adapted from the example supplied with the bash 2.04 # source code) # have make && _make() { local mdef makef gcmd cur prev i COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} # if prev argument is -f, return possible filename completions. # we could be a little smarter here and return matches against # `makefile Makefile *.mk', whatever exists if [[ "$prev" == -*f ]]; then _filedir return 0 fi # check for a long option if [[ "$cur" == --* ]]; then _longopt $1 return 0 fi # if we want an option, return the possible posix options if [[ "$cur" == -* ]]; then COMPREPLY=( $( compgen -W '-e -f -i -k -n -p -q -r -S -s -t' \ -- $cur ) ) return 0 fi # make reads `makefile' before `Makefile' if [ -f makefile ]; then mdef=makefile elif [ -f Makefile ]; then mdef=Makefile else mdef=*.mk # local convention fi # before we scan for targets, see if a makefile name was specified # with -f for (( i=0; i < ${#COMP_WORDS[@]}; i++ )); do if [[ ${COMP_WORDS[i]} == -*f ]]; then eval makef=${COMP_WORDS[i+1]} # eval for tilde expansion break fi done [ -z "$makef" ] && makef=$mdef # if we have a partial word to complete, restrict completions to # matches of that word [ -n "$2" ] && gcmd='grep "^$2"' || gcmd=cat # if we don't want to use *.mk, we can take out the cat and use # test -f $makef and input redirection COMPREPLY=( $( cat $makef 2>/dev/null | \ awk 'BEGIN {FS=":"} /^[^.# ][^=]*:/ {print $1}' | \ eval $gcmd ) ) # default to filename completion if all else failed [ ${#COMPREPLY[@]} -eq 0 ] && _filedir return 0 } [ "$have" ] && complete -F _make -X '+($*|*.[cho])' -o filenames make gmake pmake # Red Hat Linux service completion. This completes on a list of all available # service scripts in the SysV init.d directory, followed by that script's # available commands # have service && _service() { local cur sysvdir COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} [ -d /etc/rc.d/init.d ] && sysvdir=/etc/rc.d/init.d \ || sysvdir=/etc/init.d #[[ "$cur" == -* ]] && return 0 if [ $COMP_CWORD -eq 1 ]; then COMPREPLY=( $( compgen -W '`echo $sysvdir/!(*.rpmsave|*.rpmorig)`' ) ) COMPREPLY=( $( compgen -W '${COMPREPLY[@]#$sysvdir/}' -- \ $cur ) ) else COMPREPLY=( $( compgen -W '`sed -ne "y/|/ /; \ s/^.*Usage.*{\(.*\)}.*$/\1/p" \ $sysvdir/${COMP_WORDS[1]}`' -- \ $cur ) ) fi return 0 } [ "$have" ] && complete -F _service service # GNU tar(1) completion # _tar() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} if [ $COMP_CWORD = 1 ]; then COMPREPLY=( $( compgen -W 'c t x u r d A' -- $cur ) ) return 0 fi case "${COMP_WORDS[1]}" in c*f) _filedir ;; +([^Izjy])f) COMPREPLY=( $( compgen -d -- $cur ) \ $( compgen -f -X '!*.tar' -- $cur ) ) ;; *z*f) COMPREPLY=( $( compgen -d -- $cur ) \ $( compgen -f -X '!*.t?(ar.)gz' -- $cur ) ) ;; *[Ijy]*f) COMPREPLY=( $( compgen -d -- $cur ) \ $( compgen -f -X '!*.tar.bz2' -- $cur ) ) ;; *) _filedir ;; esac return 0 } complete -F _tar -o filenames tar # jar(1) completion # have jar && _jar() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} if [ $COMP_CWORD = 1 ]; then COMPREPLY=( $( compgen -W 'c t x u' -- $cur ) ) return 0 fi case "${COMP_WORDS[1]}" in c*f) _filedir ;; *f) COMPREPLY=( $( compgen -d -- $cur ) \ $( compgen -f -X '!*.jar' -- $cur ) ) ;; *) _filedir ;; esac } [ "$have" ] && complete -F _jar -o filenames jar # Linux iptables(8) completion # have iptables && _iptables() { local cur prev table chain COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} chain='s/^Chain \([^ ]\+\).*$/\1/p' if [[ $COMP_LINE == *-t\ *filter* ]]; then table="-t filter" elif [[ $COMP_LINE == *-t\ *nat* ]]; then table="-t nat" elif [[ $COMP_LINE == *-t\ *mangle* ]]; then table="-t mangle" fi case "$prev" in -*[AIDPFXL]) COMPREPLY=( $( compgen -W '`iptables $table -nL | \ sed -ne "s/^Chain \([^ ]\+\).*$/\1/p"`' -- $cur ) ) ;; -*t) COMPREPLY=( $( compgen -W 'nat filter mangle' -- $cur ) ) ;; -j) if [ "$table" = "-t filter" -o "$table" = "" ]; then COMPREPLY=( $( compgen -W 'ACCEPT DROP LOG ULOG REJECT \ `iptables $table -nL | sed -ne "$chain" \ -e "s/INPUT|OUTPUT|FORWARD|PREROUTING|POSTROUTING//"`' -- \ $cur ) ) elif [ "$table" = "-t nat" ]; then COMPREPLY=( $( compgen -W 'ACCEPT DROP LOG ULOG REJECT \ MIRROR SNAT DNAT MASQUERADE `iptables $table -nL | \ sed -ne "$chain" -e "s/OUTPUT|PREROUTING|POSTROUTING//"`' \ -- $cur ) ) elif [ "$table" = "-t mangle" ]; then COMPREPLY=( $( compgen -W 'ACCEPT DROP LOG ULOG REJECT \ MARK TOS `iptables $table -nL | sed -ne "$chain" \ -e "s/INPUT|OUTPUT|FORWARD|PREROUTING|POSTROUTING//"`' -- \ $cur ) ) fi ;; *) ;; esac } [ "$have" ] && complete -F _iptables iptables # tcpdump(8) completion # have tcpdump && _tcpdump() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} COMPREPLY=( $( compgen -W 'host net port src dst ether gateway \ less greater' -- $cur ) ) } [ "$have" ] && complete -F _tcpdump tcpdump # This meta-cd function observes the CDPATH variable, so that cd additionally # completes on directories under those specified in CDPATH. # _cd() { local IFS=$'\t\n' cur=${COMP_WORDS[COMP_CWORD]} dirs=() i _expand || return 0 # standard dir completion if parameter starts with /, ./ or ../ if [[ "$cur" == ?(.)?(.)/* ]]; then _filedir -d return 0 fi if [ -n "$CDPATH" ]; then IFS=$'\t' # we have a CDPATH, so loop on its contents for i in ${CDPATH//:/$'\t'}; do # create an array of matched subdirs dirs=( $( compgen -d $i/$cur ) ) # add subdirs to list of completions as necessary [ ${#dirs[@]} ] && COMPREPLY=( ${COMPREPLY[@]} ${dirs[@]#$i/}) done fi IFS=$' \t\n' _filedir -d # remove leading ./ from completions for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do COMPREPLY[i]=${COMPREPLY[i]#.\/} done return 0 } complete -F _cd -o filenames cd # A meta-command completion function for commands like sudo(8), which need to # first complete on a command, then complete according to that command's own # completion definition - currently not quite foolproof (e.g. mount and umount # don't work properly), but still quite useful # _command() { local cur func cline cspec COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} if [ $COMP_CWORD -eq 1 ]; then COMPREPLY=( $( compgen -c -- $cur ) ) elif complete -p ${COMP_WORDS[1]} &>/dev/null; then cspec=$( complete -p ${COMP_WORDS[1]} ) if [ "${cspec#*-F }" != "$cspec" ]; then # complete -F # # COMP_CWORD and COMP_WORDS() are not read-only, # so we can set them before handing off to regular # completion routine # set current token number to 1 less than now COMP_CWORD=$(( $COMP_CWORD - 1 )) # get function name func=${cspec#*-F } func=${func%% *} # get current command line minus initial command cline="${COMP_LINE#$1 }" # split current command line tokens into array COMP_WORDS=( $cline ) $func $cline elif [ "${cspec#*-[abcdefgjkvu]}" != "$cspec" ]; then # complete -[abcdefgjkvu] func=$( echo $cspec | \ sed -e 's/^.*\(-[abcdefgjkvu]\).*$/\1/' ) COMPREPLY=( $( compgen $func -- $cur ) ) elif [ "${cspec#*-A}" != "$cspec" ]; then # complete -A func=${cspec#*-A } func=${func%% *} COMPREPLY=( $( compgen -A $func -- $cur ) ) fi fi [ ${#COMPREPLY[@]} -eq 0 ] && _filedir } complete -F _command -o filenames nohup exec nice eval strace time _root_command() { PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin _command $1 } complete -F _root_command -o filenames sudo # ant(1) completion # have ant && _ant() { local cur prev buildfile i COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} case "$prev" in -buildfile) COMPREPLY=( $( compgen -f -X '!*.xml' -- $cur ) \ $( compgen -d -- $cur ) ) return 0 ;; -logfile) _filedir return 0 ;; esac if [[ "$cur" == -* ]]; then # relevant options completion COMPREPLY=( $( compgen -W 'help projecthelp version quiet \ verbose debug emacs logfile logger listener \ buildfile D find' -P '-' -- $cur ) ) else # available targets completion # find wich buildfile to use buildfile=build.xml for (( i=1; i < COMP_CWORD; i++ )); do if [[ "${COMP_WORDS[i]}" == -buildfile ]]; then buildfile=${COMP_WORDS[i+1]} break fi done [ ! -f $buildfile ] && return 0 # parse buildfile for targets COMPREPLY=( $( awk 'BEGIN {FS="\""} //dev/null | grep "^ $cur" ) ) [ ${#COMPREPLY[@]} -eq 0 ] && \ COMPREPLY=( $( compgen -u -- $cur ) ) return 0 ;; *) COMPREPLY=( $( psql -l | sed -ne 's|^ \('$cur'[^ ]*\).*$|\1|p' ) ) return 0 ;; esac } [ "$have" ] && complete -F _psql -o default psql _longopt() { local cur opt cur=${COMP_WORDS[COMP_CWORD]} _expand || return 0 if [[ "$cur" == --*=* ]]; then opt=${cur%%=*} # cut backlash that gets inserted before '=' sign opt=${opt%\\*} cur=${cur#*=} _filedir COMPREPLY=( $( compgen -P "$opt=" -W '${COMPREPLY[@]}' -- $cur)) return 0 fi if [[ "$cur" == -* ]]; then COMPREPLY=( $( $1 --help | sed -e '/--/!d' \ -e 's/.*\(--[-A-Za-z0-9]\+=\?\).*/\1/' | \ grep ^$cur | sort -u ) ) elif [[ "$1" == @(mk|rm)dir ]]; then _filedir -d else _filedir fi } # makeinfo and texi2dvi are defined elsewhere for i in a2ps autoconf automake bc gprof ld nm objcopy objdump readelf strip \ bison cpio diff patch enscript cp df dir du ln ls mkfifo mknod mv rm \ touch vdir xargs awk gperf grep gpg grub indent less m4 sed shar date \ env seq su tee uname who texindex cat csplit cut expand fmt fold head \ md5sum nl od paste pr ptx sha1sum sort split tac tail tr unexpand \ uniq wc units wget rsync ldd bash id info irb mkdir rmdir; do have $i && complete -F _longopt -o filenames $i done unset i # gcc(1) completion # # The only unusual feature is that we don't parse "gcc --help -v" output # directly, because that would include the options of all the other backend # tools (linker, assembler, preprocessor, etc) without any indication that # you cannot feed such options to the gcc driver directly. (For example, the # linker takes a -z option, but you must type -Wl,-z for gcc.) Instead, we # ask the driver ("g++") for the name of the compiler ("cc1"), and parse the # --help output of the compiler. # have gcc && _gcc() { local cur cc backend COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} _expand || return 0 case "$1" in gcj) backend=jc1 ;; gpc) backend=gpc1 ;; *77) backend=f771 ;; *) backend=cc1 # (near-)universal backend ;; esac if [[ "$cur" == -* ]]; then cc=$( $1 -print-prog-name=$backend ) # sink stderr: # for C/C++/ObjectiveC it's useless # for FORTRAN/Java it's an error COMPREPLY=( $( $cc --help 2>/dev/null | tr '\t' ' ' | \ sed -e '/^ *-/!d' -e 's/ *-\([^ ]*\).*/-\1/' | \ grep ^$cur | sort -u ) ) else _filedir fi } [ "$have" ] && complete -o filenames -F _gcc gcc g++ c++ g77 gcj gpc [ $OS = Linux ] && complete -o filenames -F _gcc cc # Linux cardctl(8) completion # have cardctl && _cardctl() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} if [ $COMP_CWORD -eq 1 ]; then COMPREPLY=( $( compgen -W 'status config ident suspend \ resume reset eject insert scheme' \ -- $cur ) ) fi } [ "$have" ] && complete -F _cardctl cardctl # This function is required by _dpkg() and _dpkg-reconfigure() have dpkg && _comp-dpkg-installed-packages() { grep-dctrl -r -F package -s package,status "^$1" /var/lib/dpkg/status \ | grep-dctrl -n -F status -s package installed } # Debian Linux dpkg(8) completion # have dpkg && _dpkg() { local cur prev COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} case "$prev" in -i|--install|--unpack|-A|--record-avail|-c|--contents|-I|--info| \ --fsys-tarfile|-f|--field|-e|--control|-X|--extract) COMPREPLY=( $( compgen -f -X '!*.deb' -- $cur ) \ $( compgen -d -- $cur ) ) return 0 ;; -b|--build) COMPREPLY=( $( compgen -d -- $cur ) ) return 0 ;; -s|--status|-p|--print-avail|-L|--listfiles) COMPREPLY=( $( apt-cache pkgnames $cur ) ) return 0 ;; -S|--search) _filedir return 0 ;; -r|--remove|--purge) COMPREPLY=( $( _comp-dpkg-installed-packages $cur ) ) return 0 ;; *) ;; esac COMPREPLY=( $( compgen -W '-i --install --unpack -A --record-avail \ --configure -r --remove --purge --get-selections \ --set-selections --update-avail --merge-avail \ --clear-avail --command-fd --forget-old-unavail -s \ --status -p --print-avail -L --listfiles -l --list \ -S --search -C --audit --print-architecture \ --print-gnu-build-architecture \ --print-installation-architecture \ --compare-versions --help --version --force-help -Dh \ --debug=help --licence --admindir= --root= --instdir= \ -O --selected-only -E --skip-same-version \ -G --refuse-downgrade -B --auto-deconfigure \ --no-debsig --no-act -D --debug= --status-fd \ -b --build -I --info -f --field -c --contents \ -x --extract -X --vextract --fsys-tarfile -e --control \ --ignore-depends= --abort-after' -- $cur ) ) } [ "$have" ] && complete -F _dpkg -o filenames dpkg dpkg-deb # Debian Linux dpkg-reconfigure(8) completion # have dpkg-reconfigure && _dpkg-reconfigure() { local cur prev COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} COMPREPLY=( $( compgen -W '--frontent= --priority --all \ --unseen-only --help' -- $cur ) \ $( _comp-dpkg-installed-packages $cur ) ) } [ "$have" ] && complete -F _dpkg-reconfigure -o filenames dpkg-reconfigure have java && _java() { local cur prev classpath i COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} case $prev in -@(cp|classpath)) _filedir return 0 ;; esac if [[ "$cur" == -* ]]; then # relevant options completion COMPREPLY=( $( compgen -W 'client hotspot server classic cp \ classpath D verbose version showversion ? help \ X' -P '-' -- $cur ) ) else # available classes completion # find wich classpath to use if [ -n "$CLASSPATH" ]; then classpath=$CLASSPATH else classpath=. fi for (( i=1; i < COMP_CWORD; i++ )); do if [[ "${COMP_WORDS[i]}" == -classpath ]] || \ [[ "${COMP_WORDS[i]}" == -cp ]]; then classpath=${COMP_WORDS[i+1]} break fi done # parse each classpath element for classes for i in ${classpath//:/ }; do if [ -f $i ] && [[ "$i" == *.@(jar|zip) ]]; then COMPREPLY=( ${COMPREPLY[@]} $( jar tf $i | \ grep .class | sed -e 's|\.class||g' \ -e 's|/|.|g' | grep ^$cur ) ) elif [ -d $i ]; then COMPREPLY=( ${COMPREPLY[@]} $( find $i -type f \ -name *.class | grep .class | \ sed -e 's|^'$i'/||' \ -e 's|\.class$||' \ -e 's|/|.|g' | grep ^$cur ) ) fi done fi } [ "$have" ] && complete -F _java java _configure_func() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} [[ "$cur" != -* ]] && return 0 COMPREPLY=( $( $1 --help | sed -ne 's|^ *\('$cur'[^ '$'\t'',[]\+\).*$|\1|p' ) ) } complete -F _configure_func -o default configure # urpmi media function required by other urpmi functions # have urpmi && _urpmi.media() { # return list of available urpmi media COMPREPLY=( $( awk '/{/ {print $1}' /etc/urpmi/urpmi.cfg | grep ^$cur )) } # Mandrake urpmi completion # have urpmi && _urpmi() { local cur prev COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} case $prev in --media) _urpmi.media return 0;; esac if [[ "$cur" == -* ]]; then # return list of available options COMPREPLY=( $( compgen -W 'a p P y s q v -help -update \ -media -auto -auto-select -fuzzy -src -noclean \ -complete -force -wget -curl -X -best-output' \ -P '-' -- $cur ) ) else # return list of available packages COMPREPLY=( $( gzip -dc /var/lib/urpmi/synthesis.hdlist.* | \ awk 'BEGIN {FS="@"} /info/ {print $1}' | \ grep ^$cur ) ) fi } [ "$have" ] && complete -F _urpmi urpmi # Mandrake urpmi.update completion # have urpmi.update && _urpmi.update() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} if [[ "$cur" == -* ]]; then # return list of available options COMPREPLY=( $( compgen -W 'a c d f -curl -wget' -P '-' -- $cur)) else # return list of available media _urpmi.media fi } [ "$have" ] && complete -F _urpmi.update urpmi.update # Mandrake urpmi.addmedia completion # have urpmi.addmedia && _urpmi.addmedia() { local cur i args COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} if [[ "$cur" == -* ]]; then # return list of available options COMPREPLY=( $( compgen -W 'c h f -wget -curl -update -distrib' \ -P '-' -- $cur ) ) else # count number of mandatory args given sofar args=$COMP_CWORD for (( i=1; i < COMP_CWORD; i++ )); do if [[ "${COMP_WORDS[i]}" == -* ]]; then args=$(($args-1)) fi done case $args in 1) # return list of available media _urpmi.media ;; 2) # return list of available protocols COMPREPLY=( $( compgen -W 'file:// http:// \ ftp:// removable://' -- $cur ) ) ;; 3) # return word "with" COMPREPLY=( 'with' ) ;; esac fi } [ "$have" ] && complete -F _urpmi.addmedia urpmi.addmedia # Mandrake urpmi.removemedia completion # _urpmi.removemedia() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} if [[ "$cur" == -* ]]; then # if word begins with a dash, return list of available options COMPREPLY=( $( compgen -W 'a c' -P '-' -- $cur ) ) else # elsewhere, return list of available media _urpmi.media fi } [ "$have" ] && complete -F _urpmi.removemedia urpmi.removemedia # Debian Linux reportbug(1) completion # have reportbug && _reportbug() { local cur prev COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} case "$prev" in -f|--filename|-i|--include|--mta|-o|--output) _filedir return 0 ;; -B|--bts) COMPREPLY=( $( compgen -W "debian guug kde mandrake help" -- \ $cur )) return 0 ;; -e|--editor|--mua) COMP_WORDS=(COMP_WORDS[0] $cur) COMP_CWORD=1 _command return 0 ;; --mode) COMPREPLY=( $( compgen -W "novice standard expert" -- $cur ) ) return 0 ;; -S|--severity) COMPREPLY=( $( compgen -W "grave serious important normal \ minor wishlist" -- $cur ) ) return 0; ;; -u|--ui--interface) COMPREPLY=( $( compgen -W "newt text gnome" -- $cur ) ) return 0 ;; -t|--type) COMPREPLY=( $( compgen -W "gnats debbugs" -- $cur ) ) return 0; ;; -T|--tags) COMPREPLY=( $( compgen -W "none patch security upstream sid \ woody potato sarge fixed" -- $cur ) ) return 0; ;; *) ;; esac COMPREPLY=($( compgen -W '-h --help -v --version -a --af -b \ --no-query-bts --query-bts -B --bts -c --configure \ --no-config-files --check-available -d --debug \ --no-check-available -e --editor --email -f \ --filename -g --gnupg -H --header -i --include -j \ --justification -l --ldap --no-ldap -L --list-cc -m \ --maintonly --mode --mua --mta --mutt -n --mh --nmh \ -o --output -p --print -P --pgp --proxy --http_proxy\ -q --quiet -Q --query-only --realname --report-quiet \ --reply-to --replyto -s --subject -S --severity \ --smtphost -t --type -T --tags --template -V -x \ --no-cc --package-version -z --no-compress \ --ui --interface -u \ wnpp boot-floppies kernel-image' -- $cur ) \ $( apt-cache pkgnames -- $cur ) ) _filedir return 0 } [ "$have" ] && complete -F _reportbug -o filenames reportbug # Debian Linux querybts(1) completion # have querybts && _querybts() { local cur prev COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} case "$prev" in -B|--bts) COMPREPLY=( $( compgen -W "debian guug kde mandrake help" -- \ $cur )) return 0 ;; -u|--ui--interface) COMPREPLY=($( compgen -W "newt text gnome" -- $cur )) return 0 ;; *) ;; esac COMPREPLY=($( compgen -W '-h --help -v --version -A --archive \ -B --bts -l --ldap --no-ldap --proxy= --http_proxy= \ -s --source -w --web -u --ui --interface wnpp boot-floppies' -- $cur ) \ $( apt-cache pkgnames -- $cur ) ) } [ "$have" ] && complete -F _querybts -o filenames querybts _filedir_xspec() { local IFS cur xspec IFS=$'\t\n' COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} _expand || return 0 # get first exclusion compspec that matches this command xspec=$( sed -ne '/ '${1##*/}'/{p;q;}' $BASH_COMPLETION ) # prune to leave nothing but the -X spec xspec=${xspec#*-X } xspec=${xspec%% *} COMPREPLY=( $( eval compgen -f -X "$xspec" -- \"$cur\" ) \ $( compgen -d -- $cur ) ) } list=( $( sed -ne '/^# START exclude/,/^# FINISH exclude/p' \ $BASH_COMPLETION | \ # read exclusion compspecs ( while read line do # ignore compspecs that are commented out if [ "${line#\#}" != "$line" ]; then continue; fi line=${line%# START exclude*} line=${line%# FINISH exclude*} line=${line##*\'} list=( ${list[@]} $line ) done echo ${list[@]} ) ) ) # remove previous compspecs if [ ${#list[@]} -gt 0 ]; then eval complete -r ${list[@]} # install new compspecs eval complete -F _filedir_xspec -o filenames ${list[@]} fi unset list[@] # source completion directory definitions if [ -d $BASH_COMPLETION_DIR -a -r $BASH_COMPLETION_DIR -a \ -x $BASH_COMPLETION_DIR ]; then for i in $BASH_COMPLETION_DIR/*; do [ -r $i ] && . $i done fi # source user completion file [ $BASH_COMPLETION != ~/.bash_completion -a -r ~/.bash_completion ] \ && . ~/.bash_completion unset -f have unset OS RELEASE have i