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


comp_include _filedir _get_cword


_remove_comp_word()
{
	if [[ COMP_CWORD -eq 0 ]]; then
		return
	elif [[ ${#COMP_WORDS[@]} -ge 2 ]]; then
		local old_cw0="${COMP_WORDS[0]}"
		local new_cw0="${COMP_WORDS[1]}"
		local old_length="${#COMP_LINE}"
		COMP_LINE=${COMP_LINE#${old_cw0}}
		local head=${COMP_LINE:0:${#new_cw0}}
		local i=1
		while [[ $head != $new_cw0 ]]; do
			COMP_LINE=${COMP_LINE:1}
			head=${COMP_LINE:0:${#new_cw0}}
			if (( ++i > 10 )); then
				break
			fi
		done
		local new_length="${#COMP_LINE}"
		COMP_POINT=$(( COMP_POINT + new_length - old_length ))
		
		COMP_CWORD=$(( COMP_CWORD - 1 ))
		for (( i=0; i < ${#COMP_WORDS[@]} - 1; ++i )); do
			COMP_WORDS[i]="${COMP_WORDS[i+1]}"
		done
		unset COMP_WORDS[${#COMP_WORDS[@]}-1]
	else
		return
	fi
}


_command()
{
	local cur func cline cspec noglob cmd done i \
	      _COMMAND_FUNC _COMMAND_FUNC_ARGS

	_remove_comp_word
	COMPREPLY=()
	cur=`_get_cword`
	# If the the first arguments following our meta-command-invoker are
	# switches, get rid of them. Most definitely not foolproof.
	done=
	while [ -z $done ] ; do
		cmd=${COMP_WORDS[0]}
		if [[ "$cmd" == -* ]] && [[ $COMP_CWORD -ge 1 ]]; then
	    	_remove_comp_word
	    elif [[ "$cmd" == -* ]] && [[ $COMP_CWORD -eq 0 ]]; then
	    	return
	    else
			done=1
	    fi
	done

	if [[ $COMP_CWORD -eq 0 ]]; then
		COMPREPLY=( $( compgen -c -- $cur ) )
	elif complete -p $cmd &>/dev/null; then
		cspec=$( complete -p $cmd )
		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%% *}
			
			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

	[ ${#COMPREPLY[@]} -eq 0 ] && _filedir
} # _command()
