#   bash_completion - some programmable completion functions for bash 2.05a
#
#   $Id: bash_completion,v 1.264 2002/04/08 16:30:59 ianmacd Exp $
#
#   Copyright (C) Ian Macdonald <ian@caliban.org>
#
#   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: 20020408

[ -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 )
if [ ${BASH_VERSINFO[1]} '>' 04 ]; then
	default="-o default"
	dirnames="-o dirnames"
	filenames="-o filenames"
fi
[ ${BASH_VERSINFO[1]} = "05b" ] && nospace="-o nospace"

# 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|?(E)PS|pdf|PDF)?(.gz|.GZ|.Z))' 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|m3u)' 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
[ ${BASH_VERSINFO[1]} '>' 04 ] && complete -g groupmod groupdel

# bg completes with stopped jobs
complete -A stopped -P '%' bg

# other job commands
complete -j -P '%' fg jobs disown

# readonly and unset 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 and which complete on commands
complete -c command type which

# 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
}

# This function completes on process IDs
#
_pids()
{
	COMPREPLY=( $( compgen -W '$( ps axo pid | sed 1d )' -- $cur ) )
}

# This function completes on process group IDs
#
_pgids()
{
	COMPREPLY=( $( compgen -W '$( ps axo pgid | sed 1d )' -- $cur ) )
}

# 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 $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]*[.:]* ]] && \
		   [ ${BASH_VERSINFO[1]} '>' 04 ]; then
			user=${cur%%?(\\)[.:]*}
			group=${cur#*[.:]}
			COMPREPLY=( $( compgen -P $user'\:' -g -- $group ) )
		else
			COMPREPLY=( $( compgen -S '\:' -u $cur ) )
		fi
	fi

	return 0
}
complete -F _chown $default chown

# chgrp(1) completion
#
_chgrp()
{
	local cur prev

	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]}
	prev=${COMP_WORDS[COMP_CWORD-1]}

	# first parameter on line or first since an option?
	if [ $COMP_CWORD -eq 1 ] && [[ "$cur" != -* ]] || \
	   [[ "$prev" == -* ]]; then
		[ ${BASH_VERSINFO[1]} '>' 04 ] && \
			COMPREPLY=( $( compgen -g $cur ) )
	else
		_expand || return 0
	fi

	return 0
}
complete -F _chgrp $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=( $( compgen -W '$( mount | cut -d" " -f 3 )' -- $cur ) )

	return 0
}
complete -F _umount $dirnames 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 $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\(\|.gz\)$/\1/p') )
	else 
		_filedir
	fi

	return 0
}
[ $OS = Linux ] && complete -F _insmod $filenames insmod modprobe

# man(1) completion. This is Linux and Darwin specific, in that
# 'man <section> <page>' 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 $filenames man

# renice(8) completion
#
_renice()
{
	local command cur curopt i

	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]}
	command=$1

	i=0
	# walk back throuh command line and find last option
	while [ $i -le $COMP_CWORD -a ${#COMPREPLY[@]} -eq 0 ]; do
		curopt=${COMP_WORDS[COMP_CWORD-$i]}
		case "$curopt" in
		-u)
			COMPREPLY=( $( compgen -u -- $cur ) )
			;;
		-g)
			_pgids
			;;
		-p|$command)
			_pids
			;;
		esac
		i=$(( ++i ))
	done
}
complete -F _renice renice

# 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
		_pids
	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)
		[ ${BASH_VERSINFO[1]} '>' 04 ] && \
			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 $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
			# if $COMP_CVS_REMOTE is not null, 'cvs commit' will
			# complete on remotely checked-out files (requires
			# passwordless access to the remote repository
			if [ -n "$COMP_CVS_REMOTE" ]; 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 -f -- $cur ) )
			fi
		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 $default cvs

have rpm &&
# helper functions for rpm completion
#
rpm_installed_packages()
{
	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=( $( sed -ne \
		's|^\('$cur'.*\)-[0-9a-zA-Z._]\+-[0-9a-z.]\+.*\.rpm$|\1|p' \
				/var/log/rpmpkgs ) )
	else
		COMPREPLY=( $( rpm -qa | sed -ne \
		's|^\('$cur'.*\)-[0-9a-zA-Z._]\+-[0-9a-z.]\+$|\1|p' ) )
	fi
}

file_glob()
{
	_expand || return 0
	COMPREPLY=( $( compgen -f -X "!*.$1" -- $cur ) \
		    $( compgen -d -- $cur ) )
}

# rpm(8) completion
# 
_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))
		if [[ "$cur" == -* ]]; then
			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 ) )
		else
			file_glob rpm
		fi
		;;
	-*f)
		_filedir
		;;
	-@(e|-erase))
		if [[ "$cur" == -* ]]; then
			COMPREPLY=( $( compgen -W '--allmatches --noscripts \
			--notriggers --nodeps --test --repackage' -- $cur ) )
		else
			rpm_installed_packages
		fi
		;;
	-@(q*|-query))
		# check whether we're doing package group completion
		if [ "${COMP_LINE#* -*([^ -])g}" != "$COMP_LINE" ]; then
			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' ) )
		elif [ "${COMP_LINE#* -*([^ -])p}" != "$COMP_LINE" ]; then
			# uninstalled package completion
			if [[ "$cur" == -* ]]; then
				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 ) )
			else
				file_glob rpm
			fi
		else
			# installed package completion
			if [[ "$cur" == -* ]]; then
				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 ) )
			elif [ "${COMP_LINE#* -*([^ -])a}" == "$COMP_LINE" ]; then
				rpm_installed_packages
			fi
		fi
		;;
	-@(K|-checksig))
		if [[ "$cur" == -* ]]; then
			COMPREPLY=( $( compgen -W '--nopgp --nogpg --nomd5' \
					-- $cur ) )
		else
			file_glob rpm
		fi
		;;
	-@([Vy]*|-verify))
		if [[ "$cur" == -* ]]; then
			COMPREPLY=( $( compgen -W '--root --rcfile --dbpath \
			--nodeps --nofiles --noscripts --nomd5 --querytags \
			--specfile --whatrequires --whatprovides' -- $cur ) )
		elif [ "${COMP_LINE#* -*([^ -])p}" != "$COMP_LINE" ]; then
			file_glob rpm
		else
			rpm_installed_packages
		fi
		;;
	-[bt]*)
		if [[ "$cur" == -* ]]; then
			COMPREPLY=( $( compgen -W '--short-circuit --timecheck \
			--clean --rmsource --rmspec --test --sign --buildroot \
			--targetbuildarch --buildos --nobuild --nodeps \
			--nodirtokens' -- $cur ) )
		elif [[ ${COMP_WORDS[1]} == -b* ]]; then
			file_glob spec
		else
			file_glob '@(tgz|tar.@(gz|bz2))'
		fi
		;;
	--re@(build|compile))
		if [[ "$cur" == -* ]]; then
			COMPREPLY=( $( compgen -W '--nodeps --rmsource \
				--rmspec --sign --nodirtokens' -- $cur ) )
		else
			file_glob src.rpm
		fi
		;;
	--tarbuild)
		file_glob '@(tgz|tar.@(gz|bz2))'
		;;
	--@(re|add)sign)
		file_glob rpm
		;;
	--set@(perms|gids))
		rpm_installed_packages
		;;
	--@(clean|rms@(ource|pec)))
		if [[ "$cur" == -* ]]; then
			COMPREPLY=( $( compgen -W '--clean --rmsource \
					--rmspec' -- $cur ) )
		else
			file_glob spec
		fi
		;;
	esac

	return 0
}
[ "$have" ] && complete -F _rpm $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|build-dep) ]]; then
			special=${COMP_WORDS[i]}
		fi
	done
	if [ -n "$special" ]; then
		case $special in
		@(install|source|build-dep))
			COMPREPLY=( $( apt-cache pkgnames $cur ) )
			return 0
			;;
		remove)
			if [ -f /etc/debian_version ]; then
				# Debian system
				COMPREPLY=( $( _comp-dpkg-installed-packages \
						$cur ) )
			else
				# assume RPM based
				rpm_installed_packages
			fi
			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 \
				  build-dep 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 $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 $filenames apt-cache
complete -F _apt_cache $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 2>/dev/null)`"))
		return 0
	fi

	[[ "$cur" == */* ]] || _known_hosts -c
	_filedir

	return 0
}
[ "$have" ] && complete $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 \
				   default gw' -- $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])' $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 $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 $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

# autorpm(8) completion
#
have autorpm &&
_autorpm()
{
	local cur

	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]}

	COMPREPLY=( $( compgen -W '--notty --debug --help --version \
				   auto add fullinfo info help install list \
				   remove set' -- $cur ) )

}
[ "$have" ] && complete -F _autorpm autorpm

# 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

	# Use standard dir completion if no CDPATH or parameter starts with /,
	# ./ or ../
	if [ -z "$CDPATH" ] || [[ "$cur" == ?(.)?(.)/* ]]; then
		_filedir -d
		return 0
	fi
	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
	_filedir -d
	IFS=$' \t\n'
	if [ -n "$CDPATH" ]; then
		for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
			# remove leading ./ from completions
			COMPREPLY[i]=${COMPREPLY[i]#.\/}
			# turn relative paths from current dir into
			# absolute ones
			[ -d ./"${COMPREPLY[i]}" ] && \
				COMPREPLY[i]=$PWD/${COMPREPLY[i]}
		done
	fi

	return 0
}
complete -F _cd $nospace $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 <function>
			#
			# COMP_CWORD and COMP_WORDS() are not read-only,
			# so we can set them before handing off to regular
			# completion routine

			# 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 )
			# set current token number to 1 less than expanded line
			COMP_CWORD=$(( ${#COMP_WORDS[@]} - 1 ))
			cur=${COMP_WORDS[COMP_CWORD]}
			$func $cline
			# remove any \: generated by a command that doesn't
			# default to filenames or dirnames (e.g. sudo chown)
			if [ "${cspec#*-o }" != "$cspec" ]; then
				cspec=${cspec#*-o }
				cspec=${cspec%% *}
				if [[ "$cspec" != @(dir|file)names ]]; then
					COMPREPLY=( "${COMPREPLY[@]//\\\\:/:}" )
				fi
			fi
		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 <type>
			func=${cspec#*-A }
			func=${func%% *}
			COMPREPLY=( $( compgen -A $func -- $cur ) )
		fi
	fi

	[ ${#COMPREPLY[@]} -eq 0 ] && _filedir
}
complete -F _command $filenames nohup exec nice eval strace time

_root_command()
{
	PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin _command $1
}
complete -F _root_command $filenames sudo fakeroot

# 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' -- $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 -F'"' '/<target name="/ {print $2}' \
				$buildfile | grep "^$cur" ) )
	fi
}
[ "$have" ] && complete -F _ant $filenames ant

have nslookup &&
_nslookup()
{
	local cur

	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]#-}

	COMPREPLY=( $( compgen -P '-' -W 'all class= debug d2 domain= \
			       srchlist= defname search port= querytype= \
			       type= recurse retry root timeout vc \
			       ignoretc' -- $cur ) )
}
[ "$have" ] && complete -F _nslookup nslookup

# mysqladmin(1) completion
#
have mysqladmin &&
_mysqladmin()
{
	local cur prev

	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]} 
	prev=${COMP_WORDS[COMP_CWORD-1]}

	case "$prev" in
	-u)
		COMPREPLY=( $( compgen -u -- $cur ) )
		return 0
		;;
	*)
		;;
	esac

	COMPREPLY=( $( compgen -W '-# -f -? -C -h -p -P -i -r -E -s -S -t -u \
					      -v -V -w' -- $cur ) )

	COMPREPLY=( ${COMPREPLY[@]} \
		    $( compgen -W 'create drop extended-status flush-hosts \
				   flush-logs flush-status flush-tables \
				   flush-threads flush-privileges kill \
				   password ping processlist reload refresh \
				   shutdown status variables version' \
		       -- $cur ) )
}
[ "$have" ] && complete -F _mysqladmin mysqladmin

# gzip(1) and bzip2(1) completion
#
have gzip &&
_zip()
{
	local IFS cur prev xspec

	IFS=$'\t\n'
	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]}
	prev=${COMP_WORDS[COMP_CWORD-1]}

	[ ${COMP_WORDS[0]} = "gzip" ] && xspec="*.gz"
	[ ${COMP_WORDS[0]} = "bzip2" ] && xspec="*.bz2"
	[[ "$prev" == -*d* ]] && xspec="!"$xspec

	_expand || return 0

	COMPREPLY=( $( compgen -f -X "$xspec" -- $cur ) \
		    $( compgen -d -- $cur ) )
}
[ "$have" ] && complete -F _zip $filenames gzip bzip2

# openssl(1) completion
#
have openssl &&
_openssl()
{
	local cur

	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]}

	if [ $COMP_CWORD -eq 1 ]; then
		COMPREPLY=( $( compgen -W 'asn1parse ca ciphers crl crl2pkcs7 \
			dgst dh dhparam dsa dsaparam enc errstr gendh gendsa \
			genrsa nseq passwd pkcs12 pkcs7 pkcs8 rand req rsa \
			rsautl s_client s_server s_time sess_id smime speed \
			spkac verify version x509 md2 md4 md5 mdc2 rmd160 sha \
			sha1 base64 bf bf-cbc bf-cfb bf-ecb bf-ofb cast \
			cast-cbc cast5-cbc cast5-cfb cast5-ecb cast5-ofb des \
			des-cbc des-cfb des-ecb des-ede des-ede-cbc \
			des-ede-cfb des-ede-ofb des-ede3 des-ede3-cbc \
			des-ede3-cfb des-ede3-ofb des-ofb des3 desx rc2 \
			rc2-40-cbc rc2-64-cbc rc2-cbc rc2-cfb rc2-ecb rc2-ofb \
			rc4 rc4-40' -- $cur ) )
	fi

	return 0
}
[ $have ] && complete -F _openssl $default openssl

# screen(1) completion
#
have screen &&
_screen()
{
	local cur prev

	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]}
	prev=${COMP_WORDS[COMP_CWORD-1]}

	case "$prev" in
	-[rR])
		# list detached
		COMPREPLY=( $( \screen -ls | sed -ne 's|^['$'\t'']\+\('$cur'[^'$'\t'']\+\).*Detached.*$|\1|p' ) )
		;;
	-[dDx])
		# list attached
		COMPREPLY=( $( \screen -ls | sed -ne 's|^['$'\t'']\+\('$cur'[^'$'\t'']\+\).*Attached.*$|\1|p' ) )
		;;
	-s)
		# shells
		COMPREPLY=( $( grep ^${cur:-[^#]} /etc/shells ) )
		;;
	*)
		;;
	esac

	return 0
}
[ $have ] && complete -F _screen $default screen

# lftp(1) bookmark completion
#
have lftp &&
_lftp()
{
	local cur

	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]}

	if [ $COMP_CWORD -eq 1 ] && [ -f ~/.lftp/bookmarks ]; then
	    COMPREPLY=( $( compgen -W '$( sed -ne "s/^\(.*\)'$'\t''.*$/\1/p" \
			   ~/.lftp/bookmarks )' -- $cur ) )
	fi

	return 0
}
[ $have ] && complete -F _lftp $default lftp

# ncftp(1) bookmark completion
#
have ncftp &&
_ncftp()
{
	local cur

	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]}

	if [ $COMP_CWORD -eq 1 ] && [ -f ~/.ncftp/bookmarks ]; then
	    COMPREPLY=( $( compgen -W '$( sed -ne "s/^\([^,]\{1,\}\),.*$/\1/p" \
			   ~/.ncftp/bookmarks )' -- $cur ) )
	fi

	return 0
}
[ $have ] && complete -F _ncftp $default ncftp

# gdb(1) completion
#
have gdb &&
_gdb()
{
	local cur prev

	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]}
	prev=${COMP_WORDS[COMP_CWORD-1]}

	if [ $COMP_CWORD -eq 1 ]; then
		COMPREPLY=( $( compgen -c -- $cur ) )
	elif [ $COMP_CWORD -eq 2 ]; then
		# escaoe slashes for awk
		prev=${prev//\//\\\/}
		COMPREPLY=( ${COMPREPLY[@]} $( ps ahx | sed -e 's#[]\[()]##g' |\
					awk '{p=$5;sub("^.*/","",p); \
					if (p ~ /^'$prev'/) print $1}' | \
					sed -e 's#^.*/##' ))
	fi
}
[ $have ] && complete -F _gdb $default gdb

# psql(1) completion
#
have psql &&
_psql() 
{
	local cur prev

	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]}
	prev=${COMP_WORDS[COMP_CWORD-1]}

	case "$prev" in
	-h) 
		_known_hosts
		return 0
		;;
	-U)
		COMPREPLY=( $( psql -qtc 'select usename from pg_user' \
			       2>/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 $default psql

_longopt()
{
	local cur opt

	cur=${COMP_WORDS[COMP_CWORD]}

	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 2>&1 | 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 netstat; do
    have $i && complete -F _longopt $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 $filenames -F _gcc gcc g++ c++ g77 gcj gpc
[ $OS = Linux ] && complete $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]}

	# find the last option flag
	if [[ $cur != -* ]]; then
		while [[ $prev != -* && $COMP_CWORD != 1 ]]; do
		      COMP_CWORD=$((COMP_CWORD-1))
		      prev=${COMP_WORDS[COMP_CWORD-1]}
		done
	fi

	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|--list)
		COMPREPLY=( $( apt-cache pkgnames $cur ) )
		return 0
		;;
	-S|--search)
		_filedir
		return 0
		;;
	-r|--remove|--purge|-L|--listfiles)
		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 \
			--force-all --force-auto-select --force-downgrade \
			--force-configure-any --force-hold --force-bad-path \
			--force-not-root --force-overwrite \
			--force-overwrite-diverted --force-bad-verify \
		        --force-depends-version --force-depends \
			--force-confnew --force-confold --force-confdef \
			--force-miss --force-conflicts --force-architecture \
			--force-overwrite-dir --force-remove-reinstreq \
			--force-remove-essential -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 $filenames dpkg dpkg-deb

# Debian Linux dpkg-reconfigure(8) completion
#
have dpkg-reconfigure &&
_dpkg-reconfigure()
{
	local cur prev opt

	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]}
	prev=${COMP_WORDS[COMP_CWORD-1]}


	case "$prev" in
	    -@(f|-frontend))
		opt=( $( echo /usr/share/perl5/Debconf/FrontEnd/* ) )
		opt=( ${opt[@]##*/} )
		opt=( ${opt[@]%.pm} )
	        COMPREPLY=( $( compgen -W '${opt[@]}' -- $cur ) )
	        return 0
		;;
	    -@(p|-priority))
  	        COMPREPLY=( $( compgen -W 'low medium high critical' -- $cur ) )
	        return 0
		;;
	esac

	if [[ "$cur" == -* ]]; then
	    COMPREPLY=( $( compgen -W '-f --frontend -p --priority -a --all \
				       -u --unseen-only -h --help -s --showold \
				       --force --terse' -- $cur ) )
	else
	    COMPREPLY=( $( _comp-dpkg-installed-packages $cur ) )
	fi
}
[ "$have" ] && complete -F _dpkg-reconfigure $default 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' -- $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 | \
					    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]}

	# if $COMP_CONFIGURE_HINTS is not null, then completions of the form
	# --option=SETTING will include 'SETTING' as a contextual hint
	[[ "$cur" != -* ]] && return 0
	if [ -n "$COMP_CONFIGURE_HINTS" ]; then
		COMPREPLY=( $( $1 --help | sed -ne 's|^ *\('$cur'[^ '$'\t'',[]\+\).*$|\1|p' ) )
	else
		COMPREPLY=( $( $1 --help | sed -ne 's|^ *\('$cur'[^ '$'\t'',=[]\+=\?\).*$|\1|p' ) )
	fi
}
complete -F _configure_func $default configure

# urpmi media function required by other urpmi functions
#
have urpmi &&
_urpmi_media()
{
	# return list of available urpmi media
	COMPREPLY=( $( awk -F'{' '/{/ {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' -- $cur ) )
	else
		# return list of available packages
		COMPREPLY=( $( gzip -dc /var/lib/urpmi/synthesis.hdlist.* | \
			       awk -F'@' '/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' -- $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' -- $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
#
have urpmi.removemedia &&
_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' -- $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 $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 $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 $filenames ${list[@]}
fi
unset list[@]

# source Debian specific completion directory
for i in /usr/share/bash_completion/*; do
    [ -r $i ] && . $i
done

# 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
		# On Debian, don't include any filenames containing
		# `.dpkg', omitting foo.dpkg-old, foo.dpkg-new, etc.
		case "$(basename $i)" in
			*.dpkg*) ;;
			*) [ -r $i ] && . $i
		esac
	done
fi
unset i

# source user completion file
[ $BASH_COMPLETION != ~/.bash_completion -a -r ~/.bash_completion ] \
	&& . ~/.bash_completion
unset -f have
unset OS RELEASE have default dirnames filenames nospace

###  Local Variables:
###  mode: shell-script
###  End:
