# -*- mode: shell-script; sh-basic-offset: 8; indent-tabs-mode: t -*-
# ex: ts=8 sw=8 noet filetype=sh
#
#   bash_completion - programmable completion functions for bash 3.x
#		      (backwards compatible with bash 2.05b)
#
#   Copyright © 2006-2008, Ian Macdonald <ian@caliban.org>
#             © 2009, Bash Completion Maintainers
#                     <bash-completion-devel@lists.alioth.debian.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.
#
#   The latest version of this software can be obtained here:
#
#   http://bash-completion.alioth.debian.org/
#
#   RELEASE: 1.x

if [[ $- == *v* ]]; then
	BASH_COMPLETION_ORIGINAL_V_VALUE="-v"
else
	BASH_COMPLETION_ORIGINAL_V_VALUE="+v"
fi

if [[ -n $BASH_COMPLETION_DEBUG ]]; then
	set -v
else
	set +v
fi

# Alter the following to reflect the location of this file.
#
[ -n "$BASH_COMPLETION" ] || BASH_COMPLETION=/etc/bash_completion
[ -n "$BASH_COMPLETION_DIR" ] || BASH_COMPLETION_DIR=/etc/bash_completion.d
[ -n "$BASH_COMPLETION_COMPAT_DIR" ] || BASH_COMPLETION_COMPAT_DIR=/etc/bash_completion.d
readonly BASH_COMPLETION BASH_COMPLETION_DIR BASH_COMPLETION_COMPAT_DIR

# Set a couple of useful vars
#
UNAME=$( uname -s )
# strip OS type and version under Cygwin (e.g. CYGWIN_NT-5.1 => Cygwin)
UNAME=${UNAME/CYGWIN_*/Cygwin}

case ${UNAME} in
	Linux|GNU|GNU/*) USERLAND=GNU ;;
	*) USERLAND=${UNAME} ;;
esac

# features supported by bash 2.05 and higher
if [ ${BASH_VERSINFO[0]} -eq 2 ] && [[ ${BASH_VERSINFO[1]} > 04 ]] ||
   [ ${BASH_VERSINFO[0]} -gt 2 ]; then
	declare -r bash205=$BASH_VERSION 2>/dev/null || :
	default="-o default"
	dirnames="-o dirnames"
	filenames="-o filenames"
fi
# features supported by bash 2.05b and higher
if [ ${BASH_VERSINFO[0]} -eq 2 ] && [[ ${BASH_VERSINFO[1]} = "05b" ]] ||
   [ ${BASH_VERSINFO[0]} -gt 2 ]; then
	declare -r bash205b=$BASH_VERSION 2>/dev/null || :
	nospace="-o nospace"
fi
# features supported by bash 3.0 and higher
if [ ${BASH_VERSINFO[0]} -gt 2 ]; then
	declare -r bash3=$BASH_VERSION 2>/dev/null || :
	bashdefault="-o bashdefault"
	plusdirs="-o plusdirs"
fi
# features supported by bash 4.0 and higher
if [ ${BASH_VERSINFO[0]} -gt 3 ]; then
	declare -r bash4=$BASH_VERSION 2>/dev/null || :
fi

# 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 '!*.?(t)bz?(2)' bunzip2
# TODO: see #455510
#complete -f -X '!*.?(t)bz?(2)' bzcat bzcmp bzdiff bzegrep bzfgrep bzgrep
complete -f -X '!*.*' bzcat bzcmp bzdiff bzegrep bzfgrep bzgrep
complete -f -X '!*.@(zip|ZIP|jar|JAR|exe|EXE|pk3|war|wsz|ear|zargo|xpi|sxw|ott|od[fgpst]|epub)' unzip zipinfo
complete -f -X '*.Z' compress znew
complete -f -X '!*.@(Z|gz|tgz|Gz|dz)' gunzip
# TODO: see #455510
#complete -f -X '!*.@(Z|gz|tgz|Gz|dz)' zcmp zdiff zcat zegrep zfgrep zgrep zless zmore
complete -f -X '!*.*' zcmp zdiff zcat zegrep zfgrep zgrep zless zmore
complete -f -X '!*.Z' uncompress
complete -f -X '!*.lzma' lzcat unlzma
complete -f -X '!*.xz' unxz xzcat
complete -f -X '!*.@(gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx|GIF|JP?(E)G|MIFF|TIF?(F)|PN[GM]|P[BGP]M|BMP|XPM|ICO|XWD|TGA|PCX)' ee
complete -f -X '!*.@(gif|jp?(e)g|tif?(f)|png|p[bgp]m|bmp|x[bp]m|rle|rgb|pcx|fits|pm|GIF|JPG|JP?(E)G|TIF?(F)|PNG|P[BGP]M|BMP|X[BP]M|RLE|RGB|PCX|FITS|PM)' xv qiv
complete -f -X '!*.@(@(?(e)ps|?(E)PS|pdf|PDF)?(.gz|.GZ|.bz2|.BZ2|.Z))' gv ggv kghostview
complete -f -X '!*.@(dvi|DVI)?(.@(gz|Z|bz2))' xdvi
complete -f -X '!*.@(dvi|DVI)?(.@(gz|Z|bz2))' kdvi
complete -f -X '!*.@(dvi|DVI)' dvips dviselect dvitype dvipdf advi dvipdfm dvipdfmx
complete -f -X '!*.@(pdf|PDF)' acroread gpdf xpdf
complete -f -X '!*.@(?(e)ps|?(E)PS|pdf|PDF)' kpdf
complete -f -X '!*.@(@(?(e)ps|?(E)PS|pdf|PDF|dvi|DVI)?(.gz|.GZ|.bz2|.BZ2)|cb[rz]|CB[RZ]|djv?(u)|DJV?(U)|dvi|DVI|gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx|GIF|JP?(E)G|MIFF|TIF?(F)|PN[GM]|P[BGP]M|BMP|XPM|ICO|XWD|TGA|PCX)' evince okular
complete -f -X '!*.@(?(e)ps|?(E)PS|pdf|PDF)' ps2pdf ps2pdf12 ps2pdf13 ps2pdf14 ps2pdfwr
complete -f -X '!*.texi*' makeinfo texi2html
complete -f -X '!*.@(?(la)tex|?(LA)TEX|texi|TEXI|dtx|DTX|ins|INS)' tex latex slitex jadetex pdfjadetex pdftex pdflatex texi2dvi
complete -f -X '!*.@(mp3|MP3)' mpg123 mpg321 madplay
complete -f -X '!*@(.@(mp?(e)g|MP?(E)G|wma|avi|AVI|asf|vob|VOB|bin|dat|divx|DIVX|vcd|ps|pes|fli|flv|FLV|viv|rm|ram|yuv|mov|MOV|qt|QT|wmv|mp[234]|MP[234]|m4[pv]|M4[PV]|mkv|MKV|ogg|OGG|ogm|OGM|wav|WAV|asx|ASX|mng|MNG|srt|m[eo]d|M[EO]D|s[3t]m|S[3T]M|it|IT|xm|XM)|+([0-9]).@(vdr|VDR))' xine aaxine fbxine kaffeine
complete -f -X '!*.@(avi|asf|wmv)' aviplay
complete -f -X '!*.@(rm?(j)|ra?(m)|smi?(l))' realplay
complete -f -X '!*.@(mpg|mpeg|avi|mov|qt)' xanim
complete -f -X '!*.@(ogg|OGG|m3u|flac|spx)' ogg123
complete -f -X '!*.@(mp3|MP3|ogg|OGG|pls|m3u)' gqmpeg freeamp
complete -f -X '!*.fig' xfig
complete -f -X '!*.@(mid?(i)|MID?(I)|cmf|CMF)' playmidi
complete -f -X '!*.@(mid?(i)|MID?(I)|rmi|RMI|rcp|RCP|[gr]36|[GR]36|g18|G18|mod|MOD|xm|XM|it|IT|x3m|X3M|s[3t]m|S[3T]M|kar|KAR)' timidity
complete -f -X '!*.@(m[eo]d|M[EO]D|s[3t]m|S[3T]M|xm|XM|it|IT)' modplugplay
complete -f -X '*.@(o|so|so.!(conf)|a|rpm|gif|GIF|jp?(e)g|JP?(E)G|mp3|MP3|mp?(e)g|MPG|avi|AVI|asf|ASF|ogg|OGG|class|CLASS)' vi vim gvim rvim view rview rgvim rgview gview
complete -f -X '*.@(o|so|so.!(conf)|a|rpm|gif|GIF|jp?(e)g|JP?(E)G|mp3|MP3|mp?(e)g|MPG|avi|AVI|asf|ASF|ogg|OGG|class|CLASS)' emacs
complete -f -X '!*.@(exe|EXE|com|COM|scr|SCR|exe.so)' wine
complete -f -X '!*.@(zip|ZIP|z|Z|gz|GZ|tgz|TGZ)' bzme
complete -f -X '!*.@(?([xX]|[sS])[hH][tT][mM]?([lL]))' netscape mozilla lynx opera galeon curl dillo elinks amaya
complete -f -X '!*.@(sxw|stw|sxg|sgl|doc?([mx])|dot?([mx])|rtf|txt|htm|html|odt|ott|odm)' oowriter
complete -f -X '!*.@(sxi|sti|pps?(x)|ppt?([mx])|pot?([mx])|odp|otp)' ooimpress
complete -f -X '!*.@(sxc|stc|xls?([bmx])|xlw|xlt?([mx])|[ct]sv|ods|ots)' oocalc
complete -f -X '!*.@(sxd|std|sda|sdd|odg|otg)' oodraw
complete -f -X '!*.@(sxm|smf|mml|odf)' oomath
complete -f -X '!*.odb' oobase
complete -f -X '!*.rpm' rpm2cpio
complete -f -X '!*.sqlite' sqlite3
complete -f -X '!*.aux' bibtex
complete -f -X '!*.po' poedit gtranslator kbabel lokalize
# 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 su passwd write chfn groups slay w sux

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

# other job commands
complete -j -P '"%' -S '"' 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

# builtin completes on builtins
complete -b builtin

# start of section containing completion functions called by other functions

# This function checks whether we have a given program on the system.
# No need for bulky functions in memory if we don't.
#
have()
{
	unset -v have
	PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin type $1 &>/dev/null &&
		have="yes"
}

# use GNU sed if we have it, since its extensions are still used in our code
#
[ $USERLAND != GNU ] && have gsed && alias sed=gsed

# This function checks whether a given readline variable
# is `on'.
#
_rl_enabled()
{
    [[ "$( bind -v )" = *$1+([[:space:]])on* ]]
}

# This function shell-quotes the argument
quote()
{
	echo \'${1//\'/\'\\\'\'}\' #'# Help vim syntax highlighting
}

# This function quotes the argument in a way so that readline dequoting 
# results in the original argument
quote_readline()
{
	if [ -n "$bash4" ] ; then
		# This function isn't really necessary on bash 4
		# See: http://lists.gnu.org/archive/html/bug-bash/2009-03/msg00155.html
		echo "${1}"
		return
	fi
	local t="${1//\\/\\\\}"
	echo \'${t//\'/\'\\\'\'}\' #'# Help vim syntax highlighting
}

# This function shell-dequotes the argument
dequote()
{
	eval echo "$1"
}

# Get the word to complete
# This is nicer than ${COMP_WORDS[$COMP_CWORD]}, since it handles cases
# where the user is completing in the middle of a word.
# (For example, if the line is "ls foobar",
# and the cursor is here -------->   ^
# it will complete just "foo", not "foobar", which is what the user wants.)
#
#
# Accepts an optional parameter indicating which characters out of
# $COMP_WORDBREAKS should NOT be considered word breaks. This is useful
# for things like scp where we want to return host:path and not only path.
_get_cword()
{
	if [[ "${#COMP_WORDS[COMP_CWORD]}" -eq 0 ]] || [[ "$COMP_POINT" == "${#COMP_LINE}" ]]; then
		printf "%s" "${COMP_WORDS[COMP_CWORD]}"
	else
		local i
		local cur="$COMP_LINE"
		local index="$COMP_POINT"
		for (( i = 0; i <= COMP_CWORD; ++i )); do
			while [[ "${#cur}" -ge ${#COMP_WORDS[i]} ]] && [[ "${cur:0:${#COMP_WORDS[i]}}" != "${COMP_WORDS[i]}" ]]; do
				cur="${cur:1}"
				index="$(( index - 1 ))"
			done
			if [[ "$i" -lt "$COMP_CWORD" ]]; then
				local old_size="${#cur}"
				cur="${cur#${COMP_WORDS[i]}}"
				local new_size="${#cur}"
				index="$(( index - old_size + new_size ))"
			fi
		done
		
		if [[ "${COMP_WORDS[COMP_CWORD]:0:${#cur}}" != "$cur" ]]; then
			# We messed up! At least return the whole word so things 
			# keep working
			printf "%s" "${COMP_WORDS[COMP_CWORD]}"
		else
			printf "%s" "${cur:0:$index}"
		fi
	fi
}

# This function performs file and directory completion. It's better than
# simply using 'compgen -f', because it honours spaces in filenames.
# If passed -d, it completes only on directories. If passed anything else,
# it's assumed to be a file glob to complete on.
#
_filedir()
{
	local IFS=$'\t\n' xspec

	_expand || return 0

	local -a toks
	local tmp
	
	# TODO: I've removed a "[ -n $tmp ] &&" before `echo $tmp',
	#       and everything works again. If this bug
	#       suddenly appears again (i.e. "cd /b<TAB>"
	#       becomes "cd /"), remember to check for
	#       other similar conditionals (here and
	#       _filedir_xspec()). --David
	# NOTE: The comment above has been moved outside of the subshell below, 
	#       because quotes-in-comments-in-a-subshell cause errors on
	#       bash-3.1.  See also: 
	#       http://www.mail-archive.com/bug-bash@gnu.org/msg01667.html
	toks=( ${toks[@]-} $(
		compgen -d -- "$(quote_readline "$cur")" | {
			while read -r tmp; do
				echo $tmp
			done
		}
	))
	
	if [[ "$1" != -d ]]; then
		xspec=${1:+"!*.$1"}
		toks=( ${toks[@]-} $(
			compgen -f -X "$xspec" -- "$(quote_readline "$cur")" | {
				while read -r tmp; do
					[ -n $tmp ] && echo $tmp
				done
			}
		))
	fi

	COMPREPLY=( "${COMPREPLY[@]}" "${toks[@]}" )
}

# This function splits $cur=--foo=bar into $prev=--foo, $cur=bar, making it
# easier to support both "--foo bar" and "--foo=bar" style completions.
# Returns 0 if current option was split, 1 otherwise.
#
_split_longopt()
{
	if [[ "$cur" == --?*=* ]]; then
		# Cut also backslash before '=' in case it ended up there
		# for some reason.
		prev="${cur%%?(\\)=*}"
		cur="${cur#*=}"
		return 0
	fi

	return 1
}

# This function tries to parse the output of $command --help
#
_parse_help() {
	local cmd
	cmd=$1
	$cmd --help | \
		grep -- "^[[:space:]]*-" | \
		tr "," " " | \
		awk '{print $1; if ($2 ~ /-.*/) { print $2 } }' | \
		sed -e "s:=.*::g"
}

# 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 completes on configured network interfaces
#
_configured_interfaces()
{
	if [ -f /etc/debian_version ]; then
		# Debian system
		COMPREPLY=( $( sed -ne 's|^iface \([^ ]\+\).*$|\1|p' \
			       /etc/network/interfaces ) )
	elif [ -f /etc/SuSE-release ]; then
		# SuSE system
		COMPREPLY=( $( command ls \
			/etc/sysconfig/network/ifcfg-* | \
			sed -ne 's|.*ifcfg-\('$cur'.*\)|\1|p' ) )
	elif [ -f /etc/pld-release ]; then
		# PLD Linux
		COMPREPLY=( $( command ls -B \
			/etc/sysconfig/interfaces | \
			sed -ne 's|.*ifcfg-\('$cur'.*\)|\1|p' ) )
	else
		# Assume Red Hat
		COMPREPLY=( $( command ls \
			/etc/sysconfig/network-scripts/ifcfg-* | \
			sed -ne 's|.*ifcfg-\('$cur'.*\)|\1|p' ) )
	fi
}

# This function completes on available kernels
#
_kernel_versions()
{
	COMPREPLY=( $( compgen -W '$( command ls /lib/modules )' -- $cur ) )
}

# This function completes on all available network interfaces
# -a: restrict to active interfaces only
# -w: restrict to wireless interfaces only
#
_available_interfaces()
{
	local cmd

	if [ "${1:-}" = -w ]; then
		cmd="iwconfig"
	elif [ "${1:-}" = -a ]; then
		cmd="ifconfig"
	else
		cmd="ifconfig -a"
	fi

	COMPREPLY=( $( eval $cmd 2>/dev/null | \
		sed -ne 's|^\('$cur'[^[:space:][:punct:]]\{1,\}\).*$|\1|p') )
}

# This function expands tildes in pathnames
#
_expand()
{
	# FIXME: Why was this here?
	#[ "$cur" != "${cur%\\}" ] && cur="$cur\\"

	# Expand ~username type directory specifications.  We want to expand
	# ~foo/... to /home/foo/... to avoid problems when $cur starting with
	# a tilde is fed to commands and ending up quoted instead of expanded.

	if [[ "$cur" == \~*/* ]]; then
		eval cur=$cur
	elif [[ "$cur" == \~* ]]; then
		cur=${cur#\~}
		COMPREPLY=( $( compgen -P '~' -u $cur ) )
		[ ${#COMPREPLY[@]} -eq 1 ] && eval COMPREPLY[0]=${COMPREPLY[0]}
		return ${#COMPREPLY[@]}
	fi
}

# This function completes on process IDs.
# AIX and Solaris ps prefers X/Open syntax.
[ $UNAME = SunOS -o $UNAME = AIX ] &&
_pids()
{
	COMPREPLY=( $( compgen -W '$( command ps -efo pid | sed 1d )' -- $cur ))
} ||
_pids()
{
	COMPREPLY=( $( compgen -W '$( command ps axo pid= )' -- $cur ) )
}

# This function completes on process group IDs.
# AIX and SunOS prefer X/Open, all else should be BSD.
[ $UNAME = SunOS -o $UNAME = AIX ] &&
_pgids()
{
	COMPREPLY=( $( compgen -W '$( command ps -efo pgid | sed 1d )' -- $cur ))
} ||
_pgids()
{
	COMPREPLY=( $( compgen -W '$( command ps axo pgid= )' -- $cur ))
}

# This function completes on process names.
# AIX and SunOS prefer X/Open, all else should be BSD.
[ $UNAME = SunOS -o $UNAME = AIX ] &&
_pnames()
{
	COMPREPLY=( $( compgen -W '$( command ps -efo comm | \
			           sed -e 1d -e "s:.*/::" -e "s/^-//" \
				       -e "s/^<defunct>$//")' \
			           -- $cur ) )
} ||
_pnames()
{
	# FIXME: completes "[kblockd/0]" to "0". Previously it was completed
	# to "kblockd" which isn't correct either. "kblockd/0" would be
	# arguably most correct, but killall from psmisc 22 treats arguments
	# containing "/" specially unless -r is given so that wouldn't quite
	# work either. Perhaps it'd be best to not complete these to anything
	# for now.
	# Not using "ps axo comm" because under some Linux kernels, it
	# truncates command names (see e.g. http://bugs.debian.org/497540#19)
	COMPREPLY=( $( compgen -W '$( command ps axo command= | \
			           sed -e "s/ .*//; s:.*/::; s/:$//;" \
			               -e "s/^[[(-]//; s/[])]$//" \
				       -e "s/^<defunct>$//")' \
			           -- $cur ) )
}

# This function completes on user IDs
#
_uids()
{
	if type getent &>/dev/null; then
	    COMPREPLY=( $( compgen -W '$( getent passwd | cut -d: -f3 )' -- $cur ) )
	elif type perl &>/dev/null; then
	    COMPREPLY=( $( compgen -W '$( perl -e '"'"'while (($uid) = (getpwent)[2]) { print $uid . "\n" }'"'"' )' -- $cur ) )
	else
	    # make do with /etc/passwd
	    COMPREPLY=( $( compgen -W '$( cut -d: -f3 /etc/passwd )' -- $cur ) )
	fi
}

# This function completes on group IDs
#
_gids()
{
	if type getent &>/dev/null; then
	    COMPREPLY=( $( getent group | \
			    awk -F: '{if ($3 ~ /^'$cur'/) print $3}' ) )
	elif type perl &>/dev/null; then
	    COMPREPLY=( $( compgen -W '$( perl -e '"'"'while (($gid) = (getgrent)[2]) { print $gid . "\n" }'"'"' )' -- $cur ) )
	else
	    # make do with /etc/group
	    COMPREPLY=( $( awk 'BEGIN {FS=":"} {if ($3 ~ /^'$cur'/) print $3}'\
			    /etc/group ) )
	fi
}

# This function completes on services
#
_services()
{
	local sysvdir famdir
	[ -d /etc/rc.d/init.d ] && sysvdir=/etc/rc.d/init.d || sysvdir=/etc/init.d
	famdir=/etc/xinetd.d
	COMPREPLY=( $( builtin echo $sysvdir/!(*.rpm@(orig|new|save)|*~|functions)) )

	if [ -d $famdir ]; then
		COMPREPLY=( "${COMPREPLY[@]}" $( builtin echo $famdir/!(*.rpm@(orig|new|save)|*~)) )
	fi

	COMPREPLY=( $( compgen -W '${COMPREPLY[@]#@($sysvdir|$famdir)/}' -- $cur ) )
}

# This function completes on modules
#
_modules()
{
	local modpath
	modpath=/lib/modules/$1
	COMPREPLY=( $( command ls -R $modpath | \
			sed -ne 's/^\('$cur'.*\)\.k\?o\(\|.gz\)$/\1/p') )
}

# This function completes on installed modules
#
_installed_modules()
{
	COMPREPLY=( $( compgen -W "$( /sbin/lsmod | \
				  awk '{if (NR != 1) print $1}' )" -- $1 ) )
}

# This function completes on user:group format
#
_usergroup()
{
	local IFS=$'\n'
	cur=${cur//\\\\ / }
	if [[ $cur = *@(\\:|.)* ]] && [ -n "$bash205" ]; then
		user=${cur%%*([^:.])}
		COMPREPLY=( $(compgen -P ${user/\\\\} -g -- ${cur##*[.:]}) )
	elif [[ $cur = *:* ]] && [ -n "$bash205" ]; then
		COMPREPLY=( $( compgen -g -- ${cur##*[.:]} ) )
	else
		COMPREPLY=( $( compgen -S : -u -- $cur ) )
	fi
}

# This function completes on valid shells
#
_shells()
{
	COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W '$( grep "^[[:space:]]*/" \
			/etc/shells 2>/dev/null )' -- $cur ) )
}

# Get real command.
# - arg: $1  Command
# - stdout:  Filename of command in PATH with possible symbolic links resolved.
#            Empty string if command not found.
# - return:  True (0) if command found, False (> 0) if not.
_realcommand() {
	type -P "$1" > /dev/null && {
		if type -p realpath > /dev/null; then
			realpath "$(type -P "$1")"
		elif type -p readlink > /dev/null; then
			readlink -f "$(type -P "$1")"
		else
			type -P "$1"
		fi
	}
}


# this function count the number of mandatory args
#
_count_args()
{
	args=1
	for (( i=1; i < COMP_CWORD; i++ )); do
		if [[ "${COMP_WORDS[i]}" != -* ]]; then
			args=$(($args+1))
		fi
	done
}

# This function completes on PCI IDs
#
_pci_ids()
{
	COMPREPLY=( ${COMPREPLY[@]:-} \
		$( compgen -W "$( lspci -n | awk '{print $3}')" -- $cur ) )
}

# This function completes on USB IDs
#
_usb_ids()
{
	COMPREPLY=( ${COMPREPLY[@]:-} \
		$( compgen -W "$( lsusb | awk '{print $6}')" -- $cur ) )
}

# start of section containing completion functions for external programs

# a little help for FreeBSD ports users
[ $UNAME = FreeBSD ] && complete -W 'index search fetch fetch-list \
	extract patch configure build install reinstall \
	deinstall clean clean-depends kernel buildworld' make

# This completes on a list of all available service scripts for the
# 'service' command and/or the SysV init.d directory, followed by
# that script's available commands
#
{ have service || [ -d /etc/init.d/ ]; } &&
_service()
{
	local cur sysvdir

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

	# don't complete for things like killall, ssh and mysql if it's
	# the standalone command, rather than the init script
	[[ ${COMP_WORDS[0]} != @(*init.d/!(functions|~)|service) ]] && return 0

	# don't complete past 2nd token
	[ $COMP_CWORD -gt 2 ] && return 0

	[ -d /etc/rc.d/init.d ] && sysvdir=/etc/rc.d/init.d \
				|| sysvdir=/etc/init.d

	if [[ $COMP_CWORD -eq 1 ]] && [[ $prev == "service" ]]; then
		_services
	else
		COMPREPLY=( $( compgen -W '`sed -ne "y/|/ /; \
				s/^.*\(U\|msg_u\)sage.*{\(.*\)}.*$/\2/p" \
				$sysvdir/${prev##*/} 2>/dev/null`' -- $cur ) )
	fi

	return 0
} &&
complete -F _service service
[ -d /etc/init.d/ ] && complete -F _service $default \
	$(for i in /etc/init.d/*; do echo ${i##*/}; done)

# chown(1) completion
#
_chown()
{
	local cur prev split=false
	cur=`_get_cword`
	prev=${COMP_WORDS[COMP_CWORD-1]}

	_split_longopt && split=true

	case "$prev" in
		--from)
			_usergroup
			return 0
			;;
		--reference)
			_filedir
			return 0
			;;
	esac

	$split && return 0

	# options completion
	if [[ "$cur" == -* ]]; then
		COMPREPLY=( $( compgen -W '-c -h -f -R -v --changes \
		--dereference --no-dereference --from --silent --quiet \
		--reference --recursive --verbose --help --version' -- $cur ) )
	else
		_count_args

		case $args in
			1)
				_usergroup
				;;
			*)
				_filedir
				;;
		esac
	fi
}
complete -F _chown $filenames chown

# chgrp(1) completion
#
_chgrp()
{
	local cur prev split=false

	COMPREPLY=()
	cur=`_get_cword`
	cur=${cur//\\\\/}
	prev=${COMP_WORDS[COMP_CWORD-1]}

	_split_longopt && split=true

	if [[ "$prev" == --reference ]]; then
		_filedir
		return 0
	fi

	$split && return 0
		
	# options completion
	if [[ "$cur" == -* ]]; then
		COMPREPLY=( $( compgen -W '-c -h -f -R -v --changes \
		--dereference --no-dereference --silent --quiet \
		--reference --recursive --verbose --help --version' -- $cur ) )
		return 0
	fi

	# first parameter on line or first since an option?
	if [ $COMP_CWORD -eq 1 ] && [[ "$cur" != -* ]] || \
	   [[ "$prev" == -* ]] && [ -n "$bash205" ]; then
		local IFS=$'\n'
		COMPREPLY=( $( compgen -g $cur 2>/dev/null ) )
	else
		_filedir || return 0
	fi

	return 0
}
complete -F _chgrp $filenames 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 IFS=$'\n'

	COMPREPLY=()
	cur=`_get_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/{,v}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 host prev

	COMPREPLY=()
	cur=`_get_cword`
	[[ "$cur" == \\ ]] && cur="/"
	prev=${COMP_WORDS[COMP_CWORD-1]}

	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}' ) )
	elif [[ "$cur" == //* ]]; then
		host=${cur#//}
		host=${host%%/*}
		if [ -n "$host" ]; then
			COMPREPLY=( $( compgen -W "$( echo $( smbclient -d 0 -NL $host 2>/dev/null|
			sed -ne '/^['"$'\t '"']*Sharename/,/^$/p' |
			sed -ne '3,$s|^[^A-Za-z]*\([^'"$'\t '"']*\).*$|//'$host'/\1|p' ) )" -- "$cur" ) )
		fi
	elif [ -r /etc/vfstab ]; then
		# Solaris
		COMPREPLY=( $( compgen -W "$( awk '! /^[ \t]*#/ {if ($3 ~ /\//) print $3}' /etc/vfstab )" -- $cur ) )
	elif [ ! -e /etc/fstab ]; then
		# probably Cygwin
		COMPREPLY=( $( compgen -W "$( mount | awk '! /^[ \t]*#/ {if ($3 ~ /\//) print $3}' )" -- $cur ) )
	else
		# probably Linux
		if [ $prev = -L ]; then
			COMPREPLY=( $( compgen -W '$(sed -ne "s/^[[:space:]]*LABEL=\([^[:space:]]*\).*/\1/p" /etc/fstab )' -- $cur ) )
		elif [ $prev = -U ]; then
			COMPREPLY=( $( compgen -W '$(sed -ne "s/^[[:space:]]*UUID=\([^[:space:]]*\).*/\1/p" /etc/fstab )' -- $cur ) )
		else
			COMPREPLY=( $( compgen -W "$( awk '! /^[ \t]*#/ {if ($2 ~ /\//) print $2}' /etc/fstab )" -- $cur ) )
		fi
	fi

	return 0
}
complete -F _mount $default $dirnames mount

# Linux rmmod(8) completion. This completes on a list of all currently
# installed kernel modules.
#
have rmmod && {
_rmmod()
{
	local cur

	COMPREPLY=()
	cur=`_get_cword`

	_installed_modules "$cur"
	return 0
}
complete -F _rmmod rmmod

# Linux insmod(8), modprobe(8) and modinfo(8) completion. This completes on a
# list of all available modules for the version of the kernel currently
# running.
#
_insmod()
{
	local cur prev modpath

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

	# behave like lsmod for modprobe -r
	if [ $1 = "modprobe" ] &&
	   [ "${COMP_WORDS[1]}" = "-r" ]; then
		_installed_modules "$cur"
		return 0
	fi

	# do filename completion if we're giving a path to a module
	if [[ "$cur" == */* ]]; then
		_filedir '@(?(k)o?(.gz))'
		return 0
	fi

	if [ $COMP_CWORD -gt 1 ] &&
	   [[ "${COMP_WORDS[COMP_CWORD-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 }}' ) )
	else
		_modules $(uname -r)
	fi

	return 0
}
complete -F _insmod $filenames insmod modprobe modinfo
}

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

	COMPREPLY=()
	cur=`_get_cword`
	command=$1

	i=0
	# walk back through 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=`_get_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

# killall(1) (Linux and FreeBSD) and pkill(1) completion.
#
[ $UNAME = Linux -o $UNAME = FreeBSD ] || have pkill &&
_killall()
{
	local cur

	COMPREPLY=()
	cur=`_get_cword`

	if [ $COMP_CWORD -eq 1 ] && [[ "$cur" == -* ]]; then
		_signals
	else
		_pnames
	fi

	return 0
}
[ $UNAME = Linux -o $UNAME = FreeBSD ] && complete -F _killall killall
have pkill && complete -F _killall pkill

# pgrep(1) completion.
#
[ $UNAME = Linux ] || have pgrep &&
_pgrep()
{
	local cur

	COMPREPLY=()
	cur=`_get_cword`

	_pnames

	return 0
}
have pgrep && complete -F _pgrep pgrep

# Linux pidof(8) completion.
[ $UNAME = Linux ] && complete -F _pgrep pidof

# Red Hat & Debian GNU/Linux if{up,down} completion
#
[ $USERLAND = GNU ] && { have ifup || have ifdown; } &&
_ifupdown()
{
	local cur

	COMPREPLY=()
	cur=`_get_cword`

	if [ $COMP_CWORD -eq 1 ]; then
		_configured_interfaces
		COMPREPLY=( $(compgen -W '${COMPREPLY[@]}' -- "$cur") )
       fi

       return 0
} &&
complete -F _ifupdown ifup ifdown
[ $USERLAND = GNU ] && have ifstatus && complete -F _ifupdown ifstatus

# Linux ipsec(8) completion (for FreeS/WAN)
#
[ $UNAME = Linux ] && have ipsec &&
_ipsec()
{
	local cur

	COMPREPLY=()
	cur=`_get_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
} &&
complete -F _ipsec ipsec

# This function provides simple user@host completion
#
_user_at_host() {
	local cur

	COMPREPLY=()
	cur=`_get_cword`

	if [[ $cur == *@* ]]; then
		_known_hosts_real "$cur"
	else
		COMPREPLY=( $( compgen -u -- "$cur" ) )
	fi

	return 0
}
shopt -u hostcomplete && complete -F _user_at_host $nospace talk ytalk finger

# NOTE: Using this function as a helper function is deprecated.  Use 
#       `_known_hosts_real' instead.
_known_hosts()
{
	COMPREPLY=()

	# NOTE: Passing "$@" is deprecated.  See NOTE above.
	_known_hosts_real "$@" "$(_get_cword)"
}

# Helper function for completing _known_hosts.
# This function performs host completion based on ssh's known_hosts files,
# defaulting to standard host completion if they don't exist.
# Usage: _known_hosts_real [OPTIONS] CWORD
# Options:  -a             Use aliases
#           -c             Use `:' suffix
#           -F configfile  Use `configfile' for configuration settings
#           -p PREFIX      Use PREFIX
# Return: Completions, starting with CWORD, are added to COMPREPLY[]
_known_hosts_real()
{
	local configfile flag prefix
	local cur curd awkcur user suffix aliases global_kh user_kh hosts i host
	local -a kh khd config

	local OPTIND=1
	while getopts "acF:p:" flag "$@"; do
		case $flag in
			a) aliases='yes' ;;
			c) suffix=':' ;;
			F) configfile=$OPTARG ;;
			p) prefix=$OPTARG ;;
		esac
	done
	[ $# -lt $OPTIND ] && echo "error: $FUNCNAME: missing mandatory argument CWORD"
	cur=${!OPTIND}; let "OPTIND += 1"
	[ $# -ge $OPTIND ] && echo "error: $FUNCNAME("$@"): unprocessed arguments:"\
	    $(while [ $# -ge $OPTIND ]; do echo ${!OPTIND}; shift; done)

	[[ $cur == *@* ]] && user=${cur%@*}@ && cur=${cur#*@}
	kh=()

	# ssh config files
	if [ -n "$configfile" ]; then
		[ -r "$configfile" ] &&
		  config=( "${config[@]}" "$configfile" )
	else
		[ -r /etc/ssh/ssh_config ] &&
		  config=( "${config[@]}" "/etc/ssh/ssh_config" )
		[ -r "${HOME}/.ssh/config" ] &&
		  config=( "${config[@]}" "${HOME}/.ssh/config" )
		[ -r "${HOME}/.ssh2/config" ] &&
		  config=( "${config[@]}" "${HOME}/.ssh2/config" )
	fi

	if [ ${#config[@]} -gt 0 ]; then
		local OIFS=$IFS IFS=$'\n'
		# expand path (if present) to global known hosts file
		global_kh=($( sed -ne 's/^[ \t]*[Gg][Ll][Oo][Bb][Aa][Ll][Kk][Nn][Oo][Ww][Nn][Hh][Oo][Ss][Tt][Ss][Ff][Ii][Ll][Ee]['"$'\t '"']*\(.*\)$/\1/p' "${config[@]}" ))
		for (( i=0; i < ${#global_kh[@]}; i++ )); do
			global_kh[i]=$(echo "${global_kh[i]//\"/}")
		done
		# expand path (if present) to user known hosts file
		user_kh=($( sed -ne 's/^[ \t]*[Uu][Ss][Ee][Rr][Kk][Nn][Oo][Ww][Nn][Hh][Oo][Ss][Tt][Ss][Ff][Ii][Ll][Ee]['"$'\t '"']*\(.*\)$/\1/p' "${config[@]}" ))
		for (( i=0; i < ${#user_kh[@]}; i++ )); do
			user_kh[i]=$(echo "${user_kh[i]//\"/}")
		done
		IFS=$OIFS
	fi

	# Global known_hosts files
	[ -r "$global_kh" ] &&
		kh=( "${kh[@]}" "${global_kh[@]}" )
	if [ -z "$configfile" ]; then
		[ -r /etc/ssh/ssh_known_hosts ] &&
		  kh=( "${kh[@]}" /etc/ssh/ssh_known_hosts )
		[ -r /etc/ssh/ssh_known_hosts2 ] &&
		  kh=( "${kh[@]}" /etc/ssh/ssh_known_hosts2 )
		[ -r /etc/known_hosts ] &&
		  kh=( "${kh[@]}" /etc/known_hosts )
		[ -r /etc/known_hosts2 ] &&
		  kh=( "${kh[@]}" /etc/known_hosts2 )
		[ -d /etc/ssh2/knownhosts ] &&
		  khd=( "${khd[@]}" /etc/ssh2/knownhosts/*pub )
	fi

	# User known_hosts files
	[ -r "$user_kh" ] &&
		kh=( "${kh[@]}" "${user_kh[@]}" )
	if [ -z "$configfile" ]; then
		[ -r ~/.ssh/known_hosts ] &&
		  kh=( "${kh[@]}" ~/.ssh/known_hosts )
		[ -r ~/.ssh/known_hosts2 ] &&
		  kh=( "${kh[@]}" ~/.ssh/known_hosts2 )
		[ -d ~/.ssh2/hostkeys ] &&
		  khd=( "${khd[@]}" ~/.ssh2/hostkeys/*pub )
	fi

	# If we have known_hosts files to use
	if [ ${#kh[@]} -gt 0 -o ${#khd[@]} -gt 0 -o -n "$configfile" ]; then
	    # Escape slashes and dots in paths for awk
	    awkcur=${cur//\//\\\/}
	    awkcur=${awkcur//\./\\\.}
	    curd=$awkcur

	    if [[ "$awkcur" == [0-9]*.* ]]; then
		# Digits followed by a dot - just search for that
		awkcur="^$awkcur.*"
	    elif [[ "$awkcur" == [0-9]* ]]; then
		# Digits followed by no dot - search for digits followed
		# by a dot
		awkcur="^$awkcur.*\."
	    elif [ -z "$awkcur" ]; then
		# A blank - search for a dot or an alpha character
		awkcur="[a-z.]"
	    else
		awkcur="^$awkcur"
	    fi

	    if [ ${#kh[@]} -gt 0 ]; then

		# FS needs to look for a comma separated list
		COMPREPLY=( $( awk 'BEGIN {FS=","}
				/^\s*[^|\#]/ {for (i=1; i<=2; ++i) { \
				       gsub(" .*$", "", $i); \
				       if ($i ~ /'$awkcur'/) {print $i} \
				}}' "${kh[@]}" 2>/dev/null ) )
	    fi
	    if [ ${#khd[@]} -gt 0 ]; then
		# Needs to look for files called
		# .../.ssh2/key_22_<hostname>.pub
		# dont fork any processes, because in a cluster environment,
		# there can be hundreds of hostkeys
		for i in "${khd[@]}" ; do
		    if [[ "$i" == *key_22_$awkcurd*.pub ]] && [ -r "$i" ] ; then
			host=${i/#*key_22_/}
			host=${host/%.pub/}
			COMPREPLY=( "${COMPREPLY[@]}" $host )
		    fi
		done
	    fi
	    # append any available aliases from config files
	    if [ ${#config[@]} -gt 0 ] && [ -n "$aliases" ]; then
	    local host_aliases=$( sed -ne 's/^[ \t]*[Hh][Oo][Ss][Tt]\([Nn][Aa][Mm][Ee]\)\?['"$'\t '"']\+\([^#*?]*\)\(#.*\)\?$/\2/p' "${config[@]}" )
	    hosts=$( compgen -W "$host_aliases" -- $cur )
		COMPREPLY=( "${COMPREPLY[@]}" $hosts )
	    fi

        # Add hosts reported by avahi, if it's available
        # and if the daemon is started.
        # The original call to avahi-browse also had "-k", to avoid
        #  lookups into avahi's services DB. We don't need the name
        #  of the service, and if it contains ";", it may mistify
        #  the result. But on Gentoo (at least), -k isn't available
        #  (even if mentioned in the manpage), so...
        if type avahi-browse >&/dev/null; then
            if [ -n "$(pidof avahi-daemon)" ]; then
                COMPREPLY=( "${COMPREPLY[@]}" $(
                    compgen -W "$( avahi-browse -cpr _workstation._tcp | \
                                   grep ^= | cut -d\; -f7 | sort -u )" -- $cur ) )
            fi
        fi

	    # Now add results of normal hostname completion
	    COMPREPLY=( "${COMPREPLY[@]}" $( compgen -A hostname -- $cur ) )

	    # apply suffix and prefix
	    for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
		COMPREPLY[i]=$prefix$user${COMPREPLY[i]}$suffix
	    done
	elif [ -z "$configfile" ]; then
	    # Just do normal hostname completion
	    COMPREPLY=( $( compgen -A hostname -S "$suffix" -- $cur ) )
	fi

	return 0
}
complete -F _known_hosts traceroute traceroute6 tracepath tracepath6 \
	ping ping6 fping fping6 telnet host nslookup rsh rlogin ftp dig ssh-installkeys mtr

# 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=`_get_cword` i j k

	# try to allow variable completion
	if [[ "$cur" == ?(\\)\$* ]]; then
		COMPREPLY=( $( compgen -v -P '$' -- "${cur#?(\\)$}" ) )
		return 0
	fi

	# Enable -o filenames option, see Debian bug #272660
	compgen -f /non-existing-dir/ >/dev/null

	# Use standard dir completion if no CDPATH or parameter starts with /,
	# ./ or ../
	if [ -z "${CDPATH:-}" ] || [[ "$cur" == ?(.)?(.)/* ]]; then
		_filedir -d
		return 0
	fi

	local -r mark_dirs=$(_rl_enabled mark-directories && echo y)
	local -r mark_symdirs=$(_rl_enabled mark-symlinked-directories && echo y)

	# we have a CDPATH, so loop on its contents
	for i in ${CDPATH//:/$'\t'}; do
		# create an array of matched subdirs
		k="${#COMPREPLY[@]}"
		for j in $( compgen -d $i/$cur ); do
			if [[ ( $mark_symdirs && -h $j || $mark_dirs && ! -h $j ) && ! -d ${j#$i/} ]]; then
				j="${j}/"
			fi
			COMPREPLY[k++]=${j#$i/}
		done
	done

	_filedir -d

	if [[ ${#COMPREPLY[@]} -eq 1 ]]; then
	    i=${COMPREPLY[0]}
	    if [ "$i" == "$cur" ] && [[ $i != "*/" ]]; then
		COMPREPLY[0]="${i}/"
	    fi
	fi

	return 0
}
if shopt -q cdable_vars; then
    complete -v -F _cd $nospace cd
else
    complete -F _cd $nospace cd
fi

# a wrapper method for the next one, when the offset is unknown
_command()
{
	local offset i

	# find actual offset, as position of the first non-option
	offset=1
	for (( i=1; i <= COMP_CWORD; i++ )); do
		if [[ "${COMP_WORDS[i]}" != -* ]]; then
			offset=$i
			break
		fi
	done
	_command_offset $offset
}

# 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_offset()
{
	local cur func cline cspec noglob cmd i char_offset word_offset \
	      _COMMAND_FUNC _COMMAND_FUNC_ARGS

	word_offset=$1

	# rewrite current completion context before invoking
	# actual command completion

	# find new first word position, then
	# rewrite COMP_LINE and adjust COMP_POINT
	local first_word=${COMP_WORDS[$word_offset]}
	for (( i=0; i <= ${#COMP_LINE}; i++ )); do
		if [[ "${COMP_LINE:$i:${#first_word}}" == "$first_word" ]]; then
			char_offset=$i
			break
		fi
	done
	COMP_LINE=${COMP_LINE:$char_offset}
	COMP_POINT=$(( COMP_POINT - $char_offset ))

	# shift COMP_WORDS elements and adjust COMP_CWORD
	for (( i=0; i <= COMP_CWORD - $word_offset; i++ )); do
		COMP_WORDS[i]=${COMP_WORDS[i+$word_offset]}
	done
	for (( i; i <= COMP_CWORD; i++ )); do
		unset COMP_WORDS[i];
	done
	COMP_CWORD=$(( $COMP_CWORD - $word_offset ))

	COMPREPLY=()
	cur=`_get_cword`

	if [[ $COMP_CWORD -eq 0 ]]; then
		COMPREPLY=( $( compgen -c -- $cur ) )
	else
		cmd=${COMP_WORDS[0]}
		if complete -p $cmd &>/dev/null; then
		cspec=$( complete -p $cmd )
		if [ "${cspec#* -F }" != "$cspec" ]; then
			# complete -F <function>

			# get function name
			func=${cspec#*-F }
			func=${func%% *}
			
			if [[ ${#COMP_WORDS[@]} -ge 2 ]]; then
				$func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}"	"${COMP_WORDS[${#COMP_WORDS[@]}-2]}"
			else
				$func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}"
			fi

			# remove any \: generated by a command that doesn't
			# default to filenames or dirnames (e.g. sudo chown)
			# FIXME: I'm pretty sure this does not work!
			if [ "${cspec#*-o }" != "$cspec" ]; then
				cspec=${cspec#*-o }
				cspec=${cspec%% *}
				if [[ "$cspec" != @(dir|file)names ]]; then
					COMPREPLY=("${COMPREPLY[@]//\\\\:/:}")
				fi
			fi
		elif [ -n "$cspec" ]; then
			cspec=${cspec#complete};
			cspec=${cspec%%$cmd};
			COMPREPLY=( $( eval compgen "$cspec" -- "$cur" ) );
		fi
		fi
	fi

	[ ${#COMPREPLY[@]} -eq 0 ] && _filedir
}
complete -F _command $filenames nohup exec nice eval time ltrace then \
	else do vsound command xargs tsocks

_root_command()
{
	PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin _command $1 $2 $3
}
complete -F _root_command $filenames sudo fakeroot really gksudo gksu kdesudo

_longopt()
{
	local cur prev

	cur=`_get_cword`
	prev=${COMP_WORDS[COMP_CWORD-1]}

	if _split_longopt; then
		case "$prev" in
			*[Dd][Ii][Rr]*)
				_filedir -d
				;;
			*[Ff][Ii][Ll][Ee]*)
				_filedir
				;;
		esac
		return 0
	fi

	if [[ "$cur" == -* ]]; then
		COMPREPLY=( $( compgen -W "$( $1 --help 2>&1 | sed -e '/--/!d' \
				-e 's/.*\(--[-A-Za-z0-9]\+\).*/\1/' |sort -u )"\
				-- $cur ) )
	elif [[ "$1" == rmdir ]]; 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 diff patch enscript cp df dir du ln ls mkfifo mknod mv rm \
	 touch vdir awk gperf grep grub indent less m4 sed shar date \
	 tee who texindex cat csplit cut expand fmt fold head \
	 md5sum nl od paste pr ptx sha1sum sort split tac tail tr unexpand \
	 uniq wc ldd bash id irb mkdir rmdir; do
  have $i && complete -F _longopt $filenames $i
done

# These commands do not use filenames, so '-o filenames' is not needed.
for i in env netstat seq uname units wget; do
  have $i && complete -F _longopt $default $i
done
unset i

# look(1) completion
#
have look &&
_look()
{
	local cur

	COMPREPLY=()
	cur=`_get_cword`

	if [ $COMP_CWORD = 1 ]; then
		COMPREPLY=( $( compgen -W '$(look $cur 2>/dev/null)' ) )
	fi
} &&
complete -F _look $default look

# id(1) completion
#
have id &&
_id()
{
	local cur

	COMPREPLY=()
	cur=`_get_cword`

	if [[ "$cur" == -* ]]; then
		COMPREPLY=( $( compgen -W '-a -g --group -G --groups -n --name\
			-r --real -u --user --help --version' -- $cur ) )
	else
		COMPREPLY=( $( compgen -u $cur  ) )
	fi
} &&
complete -F _id id

_filedir_xspec()
{
	local IFS cur xspec

	IFS=$'\t\n'
	COMPREPLY=()
	cur=`_get_cword`

	_expand || return 0

	# get first exclusion compspec that matches this command
	xspec=$( sed -ne $'/^complete .*[ \t]'${1##*/}$'\([ \t]\|$\)/{p;q;}' \
		  $BASH_COMPLETION )
	# prune to leave nothing but the -X spec
	xspec=${xspec#*-X }
	xspec=${xspec%% *}

	local -a toks
	local tmp

	toks=( ${toks[@]-} $(
		compgen -d -- "$(quote_readline "$cur")" | {
			while read -r tmp; do
				# see long TODO comment in _filedir() --David
				echo $tmp
			done
		}
	))
	
	toks=( ${toks[@]-} $(
		eval compgen -f -X "$xspec" -- "\$(quote_readline "\$cur")" | {
			while read -r tmp; do
				[ -n $tmp ] && echo $tmp
			done
		}
	))
	
	COMPREPLY=( "${toks[@]}" )
}
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 completion directory definitions
if [ -d $BASH_COMPLETION_COMPAT_DIR -a -r $BASH_COMPLETION_COMPAT_DIR -a \
	 -x $BASH_COMPLETION_COMPAT_DIR ]; then
	for i in $BASH_COMPLETION_COMPAT_DIR/*; do
		[[ ${i##*/} != @(*~|*.bak|*.swp|\#*\#|*.dpkg*|*.rpm@(orig|new|save)) ]] &&
			[ \( -f $i -o -h $i \) -a -r $i ] && . $i		
	done
fi
if [ -d $BASH_COMPLETION_DIR -a -r $BASH_COMPLETION_DIR -a \
     $BASH_COMPLETION_DIR != $BASH_COMPLETION_COMPAT_DIR -a \
     -x $BASH_COMPLETION_DIR ]; then
	for i in $BASH_COMPLETION_DIR/*; do
		[[ ${i##*/} != @(*~|*.bak|*.swp|\#*\#|*.dpkg*|*.rpm@(orig|new|save)) ]] &&
			[ \( -f $i -o -h $i \) -a -r $i ] && . $i
	done
fi
unset i

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

set $BASH_COMPLETION_ORIGINAL_V_VALUE
unset BASH_COMPLETION_ORIGINAL_V_VALUE
