# bash_completion - some programmable completion functions for bash 2.05a # # $Id: bash_completion,v 1.149 2002/02/27 00:13:04 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: 20020225 [ -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 # 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 # 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|GIF|JPG|JP?(E)G|TIF?(F)|PNG|P[BGP]M|BMP|XPM)' ee xv qiv display complete -f -X '!*.@(?(e)ps|?(E)PS|?(e)ps.gz|pdf|PDF)' 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)' 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 # FINISH exclude -- do not remove this line # user commands see only users complete -u finger su usermod userdel passwd # 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 # Now we get to the meat of the file, the functions themselves. Some # of these are works in progress. Most assume GNU versions of the # tools in question and may require modifications for use on vanilla # UNIX systems. # # A couple of functions may have non-portable, Linux specific code in # them, but this will be noted where applicable # This function is handy for checking whether we have certain 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" } # GNU 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 -g -- $group ) ) for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do COMPREPLY[i]=$user.${COMPREPLY[i]} done 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]} # could rewrite the cut | grep to be a sed command, but this is # clearer and doesn't result in much overhead 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}/sbin/showmount; do [ -x $i ] && sm=$i && break; done if [ -n "$sm" ] && [[ "$cur" == *:* ]]; then COMPREPLY=( $( $sm -e --no-headers ${cur%%:*} | \ 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 COMPREPLY=( $( compgen -f $cur ) ) 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 ~ /^'$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 COMPREPLY=( $( compgen -f $cur ) ) fi return 0 } [ $OS = Linux ] && complete -F _insmod -o filenames insmod modprobe # man(1) completion. This is Linux specific, in that 'man
' # is the expected syntax. This allows one to do something like # 'man 3 str' to obtain a list of all string handling syscalls on # the system. # [ $OS = Linux ] && _man() { local cur prev sect i manpath 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 manpath=$( man --path ) 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 ] && complete -F _man -o filenames man _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 } # 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=( $( ps ahx | awk '{print $1}' | grep ^$cur ) ) fi } complete -F _kill kill # Linux killall(1) completion. This wouldn't be much use on, say, # Solaris, where killall does exactly that: kills ALL processes. # # This could be improved. For example, it currently doesn't take # command line options into account # [ $OS = Linux ] && _killall() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} if [ $COMP_CWORD -eq 1 ] && [[ "$cur" == -* ]]; then _signals else # get a list of processes (the sub() in the awk takes care # of getting the basename of the process, the first sed # evaluation takes care of swapped out processes, and the # second takes care of getting the basename of the process) COMPREPLY=( $( ps ahx | sed -e 's#[]\[()]##g' | \ awk '{p=$5;sub("^.*/","",p);if (p ~ /^'$cur'/) print $5}' | \ sed -e 's#^.*/##' ) ) fi return 0 } [ $OS = Linux ] && 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 ncur prev i COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]#} ncur=${cur#-} 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' ) ) return 0 ;; -?(a)newer|-fls|-fprint?(0|f)|-?(i)?(l)name) COMPREPLY=( $( compgen -f $ncur ) ) return 0 ;; -fstype) # this is highly non-portable COMPREPLY=( $( cut -d$'\t' -f 2 /proc/filesystems | grep ^$ncur ) ) return 0 ;; -gid) COMPREPLY=( $( awk 'BEGIN {FS=":"} \ {if ($3 ~ /^'$ncur'/) print $3}' /etc/group ) ) return 0 ;; -group) COMPREPLY=( $( compgen -g $ncur ) ) return 0 ;; -?(x)type) COMPREPLY=( $( compgen -W 'b c d p f l s' $ncur ) ) return 0 ;; -uid) COMPREPLY=( $( awk 'BEGIN {FS=":"} \ {if ($3 ~ /^'$ncur'/) print $3}' /etc/passwd ) ) return 0 ;; -user) COMPREPLY=( $( compgen -u $ncur ) ) 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 -a "$cur" = "$ncur" ]; then COMPREPLY=( $( compgen -d $cur ) ) return 0 fi # complete using basic options ($ncur has had its dash removed here, # as otherwise compgen will bomb out with an error, since it thinks # the dash is an option to itself) 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' $ncur ) ) # 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[@]}) ) ) # put dashes back for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do COMPREPLY[i]=-${COMPREPLY[i]} done 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 ) ) return 0 ;; manual) COMPREPLY=( $( compgen -W '--up --down --route --unroute \ --union' $cur ) ) return 0 ;; ranbits) COMPREPLY=( $( compgen -W '--quick --continuous --bytes' $cur ) ) return 0 ;; setup) COMPREPLY=( $( compgen -W '--start --stop --restart' $cur ) ) return 0 ;; *) return 0 ;; esac return 0 } [ $OS = Linux ] && [ "$have" ] && complete -F _ipsec ipsec # cvs(1) completion # have cvs && _cvs() { local cur prev COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} if [ $COMP_CWORD -eq 1 ] || [[ "$prev" == -* ]]; then COMPREPLY=( $( compgen -W 'add admin checkout commit diff \ export history import log rdiff release remove rtag status \ tag update' $cur )) fi return 0 } [ "$have" ] && complete -F _cvs -o default cvs # rpm(8) completion. This is quite comprehensive now and covers rpm 4.x # have rpm && _rpm() { dashify() { local i for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do if [ ${#COMPREPLY[i]} -le 2 ]; then COMPREPLY[i]=-${COMPREPLY[i]} else COMPREPLY[i]=--${COMPREPLY[i]} fi done } 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 ) ) } local cur cur_nodash prev COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} cur_nodash=${cur#-} 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_nodash ) ) dashify return 0 ;; -t*) COMPREPLY=( $( compgen -W 'ta tb tc ti tl tp ts' \ $cur_nodash ) ) dashify return 0 ;; --*) 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_nodash#-} ) ) dashify return 0 ;; *) COMPREPLY=( $( compgen -W 'b e F i q t U V' \ $cur_nodash ) ) dashify return 0 ;; esac fi case "$prev" in --@(db|exclude)path|prefix|relocate|root) COMPREPLY=( $( compgen -d $cur ) ) 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) COMPREPLY=( $( compgen -f $cur ) ) return 0 ;; --specfile) # complete on .spec files file_glob spec return 0 ;; --whatprovides) # complete on capabilities COMPREPLY=( $( rpm -qa --queryformat '%{providename}\n' | grep ^$cur ) ) 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)) # complete on list of relevant options 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_nodash#-} )) dashify # return if $cur is an option [[ "$cur" == -* ]] && return 0 # add a list of RPMS to possible completions file_glob rpm return 0 ;; -q*p*) # complete on list of relevant options 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_nodash#-} ) ) dashify # return if $cur is an option [[ "$cur" == -* ]] && return 0 # add a list of RPMS to possible completions file_glob rpm return 0 ;; -*f) # standard filename completion COMPREPLY=( $( compgen -f $cur ) ) return 0 ;; -@(e|-erase)) # complete on list of relevant options COMPREPLY=( $( compgen -W 'allmatches noscripts notriggers \ nodeps test repackage' ${cur_nodash#-} ) ) dashify # return if $cur is an option [[ "$cur" == -* ]] && return 0 add_package_list return 0 ;; -q*) # complete on list of relevant options 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_nodash#-} ) ) dashify # 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 return 0 ;; -@(K|-checksig)) # complete on list of relevant options COMPREPLY=( $( compgen -W 'nopgp nogpg nomd5' \ ${cur_nodash#-} ) ) dashify # return if $cur is an option [[ "$cur" == -* ]] && return 0 # add a list of RPMS to possible completions file_glob rpm return 0 ;; -@([Vy]*|-verify)) # complete on list of relevant options COMPREPLY=( $( compgen -W 'root rcfile dbpath nodeps nofiles \ noscripts nomd5' ${cur_nodash#-} ) ) dashify # return if $cur is an option [[ "$cur" == -* ]] && return 0 add_package_list return 0 ;; -[bt]*) # complete on list of relevant options COMPREPLY=( $( compgen -W 'short-circuit timecheck clean \ rmsource rmspec test sign buildroot target buildarch buildos \ nobuild nodeps nodirtokens' ${cur_nodash#-} ) ) dashify # 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 return 0 ;; --re@(build|compile)) _expand || return 0 COMPREPLY=( $( compgen -W 'nodeps rmsource rmspec sign \ nodirtokens' ${cur_nodash#-} ) ) dashify # 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 ) ) return 0 ;; --tarbuild) _expand || return 0 # complete on tarred sources file_glob '@(tgz|tar.@(gz|bz2))' return 0 ;; --@(re|add)sign) # complete on RPMs file_glob rpm return 0 ;; --set@(perms|gids)) add_package_list return 0 ;; --@(clean|rms@(ource|pec))) COMPREPLY=( $( compgen -W 'clean rmsource rmspec' \ ${cur_nodash#-} ) ) dashify # return if $cur is an option [[ "$cur" == -* ]] && return 0 file_glob spec return 0 ;; -*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' ) ) return 0 ;; 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 COMPREPLY=( $( compgen -f $cur ) ) 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 ' | \ grep ^$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) COMPREPLY=( $( compgen -f $cur ) ) return 0 ;; show?(pkg)|depends|dotty) COMPREPLY=( $( apt-cache pkgnames $cur ) ) return 0 ;; esac fi if [[ "$prev" == -*c ]] || [ "$prev" = --config-file ]; then COMPREPLY=( $( compgen -f $cur ) ) 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' | grep ^$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 i COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} cur_nodash=${cur#--} prev=${COMP_WORDS[COMP_CWORD-1]} if [ $COMP_CWORD -eq 1 ]; then COMPREPLY=( $( compgen -W 'list add del level' $cur_nodash ) ) for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do COMPREPLY[i]=--${COMPREPLY[i]} done 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 kh user suffix 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. Should be able to improve this with user@host notation, # but the '@' seems to trigger some kind of bug in bash's 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 have scp && _scp() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} _expand || return 0 [[ "$cur" == */* ]] || _known_hosts -c _filedir return 0 } [ "$have" ] && complete -o filenames -F _scp scp # Linux route(8) completion. This could be improved by adding address family # completion for -A, etc. # [ $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 # Must use grep here, otherwise $cur will cause compgen to barf, if # it begins with a hyphen COMPREPLY=( $( compgen -W 'add del -host -net netmask metric mss \ window irtt reject mod dyn reinstate dev' | \ grep ^$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 COMPREPLY=( $( compgen -f $cur ) ) 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' | grep ^$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 if [ ${#COMPREPLY[@]} -eq 0 ]; then COMPREPLY=( $( compgen -f $cur ) ) fi 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 # The beginnings of a completion function for GNU tar(1) # _tar() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} [ $COMP_CWORD -eq 1 ] && return 0 case "${COMP_WORDS[1]}" in c*f) _filedir ;; +([^zj])f) COMPREPLY=( $( compgen -d $cur ) \ $( compgen -f -X '!*.tar' $cur ) ) ;; *z*f) COMPREPLY=( $( compgen -d $cur ) \ $( compgen -f -X '!*.t?(ar.)gz' $cur ) ) ;; *j*f) COMPREPLY=( $( compgen -d $cur ) \ $( compgen -f -X '!*.tar.bz2' $cur ) ) ;; *) _filedir ;; esac return 0 } complete -F _tar -o filenames tar # 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 COMPREPLY=( $( compgen -d $cur ) ) return 0 fi if [ -n "$CDPATH" ]; then # 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' COMPREPLY=( ${COMPREPLY[@]} $( compgen -d $cur ) ) 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 else COMPREPLY=( $( compgen -f $cur ) ) fi } complete -F _command -o filenames nohup exec nice eval strace sudo _root_command() { local OLDPATH=$PATH PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin _command PATH=$OLDPATH } complete -F _command -o filenames sudo # Basic Perforce completion by Frank Cusack (frank@google.com) # have p4 && _p4() { local cur prev prev2 p4commands p4filetypes COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} # rename isn't really a command p4commands="add admin branch branches change changes client \ clients counter counters delete depot depots describe \ diff diff2 dirs edit filelog files fix fixes flush \ fstat group groups have help info integrate integrated \ job jobs jobspec label labels labelsync lock obliterate \ opened passwd print protect rename reopen resolve \ resolved revert review reviews set submit sync triggers \ typemap unlock user users verify where" p4filetypes="ctext cxtext ktext kxtext ltext tempobj ubinary \ uresource uxbinary xbinary xltext xtempobj xtext \ text binary resource" if [ $COMP_CWORD -eq 1 ]; then COMPREPLY=( $( compgen -W "$p4commands" $cur ) ) elif [ $COMP_CWORD -eq 2 ]; then case "$prev" in help) COMPREPLY=( $( compgen -W "simple commands \ environment filetypes jobview revisions \ usage views $p4commands" $cur ) ) ;; admin) COMPREPLY=( $( compgen -W "checkpoint stop" $cur ) ) ;; *) ;; esac elif [ $COMP_CWORD -gt 2 ]; then prev2=${COMP_WORDS[COMP_CWORD-2]} case "$prev" in -t) case "$prev2" in add|edit|reopen) COMPREPLY=( $(compgen -W "$p4filetypes" $cur) ) ;; *) ;; esac ;; *) ;; esac fi return 0 } [ "$have" ] && complete -F _p4 -o default p4 g4 # ant completion is modified from the original submitted by # Claus-Peter Klas # have ant && _ant_targets() { COMPREPLY=() local gcmd # if we have a partial word to complete, restrict completions to # matches of that word [ ! -f build.xml ] && return 0 [ -n "$2" ] && gcmd='grep "^$2"' || gcmd=cat 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 psql _longopt() { local cur cur=${COMP_WORDS[COMP_CWORD]} _expand || return 0 [ "$4" = no_completion ] && return 0 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, originally by Phil Edwards # # 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]} _longopt "$1" "$cur" "" no_completion # return if _expand returned anything [ ${#COMPREPLY[@]} -gt 0 ] && 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 # 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%=} | \ 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 export # bash shell function completion # _function() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} if [ $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 _expand() { # expand ~username type directory specifications if [[ "$cur" == \~*/* ]]; then eval cur=$cur elif [[ "$cur" == \~* ]]; then cur=${cur#\~} COMPREPLY=( $( compgen -P '~' -u $cur ) ) return ${#COMPREPLY[@]} fi } _configure_func() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} [[ "$cur" != -* ]] && return 0 _longopt "$1" "$cur" "" no_completion COMPREPLY=( $( $1 --help | sed -ne 's/^ *\('$cur'[^ '$'\t'',[]\+\).*$/\1/p' ) ) } complete -F _configure_func configure _filedir() { local IFS cur IFS=$'\t\n' cur=${COMP_WORDS[COMP_CWORD]} _expand || return 0 if [ "$1" = -d ]; then COMPREPLY=( ${COMPREPLY[@]} $( compgen -d $cur ) ) return 0 fi COMPREPLY=( ${COMPREPLY[@]} $( eval compgen -f \"$cur\" ) ) } _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 user completion file [ -f ~/.bash_completion ] && . ~/.bash_completion unset -f have unset OS RELEASE have