# Gentoo Linux Bash Shell Command Completion
#
# $Id: gentoo 104 2010-12-17 03:40:50Z darkside $
#
# Copyright 1999-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License, v2 or later

# also defined in bash_completion proper however, will produce command
# not found warnings when this is only enabled "locally" so we define it
# here as well.
have()
{
    unset -v have
    PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin type $1 >&/dev/null && have="yes"
}

#
# Retrieve PORTDIR/PORTDIR_OVERLAY location from user's make.conf or, if it
# is not defined there, from make.globals.
#
_portdir()
{
    (
    source @GENTOO_PORTAGE_EPREFIX@/etc/make.globals 2>/dev/null
    source @GENTOO_PORTAGE_EPREFIX@/etc/make.conf 2>/dev/null

    echo ${PORTDIR}
    if [[ $1 == '-o' ]] ; then
        echo ${PORTDIR_OVERLAY}
    fi
    )
}

# like _pkgname but completes on package names only (no category)
_pkgname_only()
{
    local i pd
    local cur="$1"
    shift
    local dir="$@"

    COMPREPLY=($(compgen -W "$(\
        for pd in $dir ; do \
            builtin cd ${pd}; \
            for i in *-*/${cur}*; do \
                [[ -d ${i} ]] && { local x=${i##*/} ; echo ${x%-[0-9]*}; } \
            done ; \
        done)" -- ${cur}))
}

#
# This function completes package names.
#
# usage: pkgname <mode> <current-directory>
#
# Where mode is one of:
#   -A  Search all available packages (except for those in the overlays)
#   -I  Only search the installed packages
#
# TODO: Look at breaking this function out and making it a "universal"
#       category/package name completion function.
#
_pkgname()
{
    local mode cur portdir only
    mode="$1"
    cur="$2"
    portdir=$(_portdir -o)
    # Ignore '=' at the beginning of the current completion
    [[ ${cur:1:1} == "=" ]] && cur=${cur:2}
    [[ ${cur:0:1} == "=" ]] && cur=${cur:1}
    case $mode in
    -I)
        # Complete either the category or the complete package name
        if [[ $cur == */* ]]; then
        COMPREPLY=($(builtin cd @GENTOO_PORTAGE_EPREFIX@/var/db/pkg; compgen -W "$(compgen -G "$cur*" )" -- $cur))
        else
        COMPREPLY=($(builtin cd @GENTOO_PORTAGE_EPREFIX@/var/db/pkg; compgen -W "$(compgen -G "$cur*" -S /)" -- $cur))
        fi
        # We may just have finished completing the category.
        # Make sure there isn't anything more to complete now.
        if [[ ${#COMPREPLY[@]} == 1 ]]; then
        COMPREPLY=($(builtin cd @GENTOO_PORTAGE_EPREFIX@/var/db/pkg; compgen -W "$(compgen -G "$COMPREPLY*")" -- $cur))
        fi

            if [[ -z "${COMPREPLY}" ]] ; then
                only=1
                _pkgname_only ${cur} @GENTOO_PORTAGE_EPREFIX@/var/db/pkg
            fi
        ;;
    -A)
        # Complete either the category or the complete package name
        if [[ $cur == */* ]]; then
            # Once the category has been completed, it's safe to use ${portdir}
            # to continue completion.
                local ww=$(\
                    for pd in ${portdir} ; do
                        builtin cd ${pd};
                        compgen -W "$(compgen -G "${cur}*")" -- "${cur}" ;
                    done)
                COMPREPLY=($(\
                    for x in ${ww}; do echo $x; done|sort -u
                        ))
            # When we've completed most of the name, also display the version for
            # possible completion.
            if [[ ${#COMPREPLY[@]} -le 1 || ${cur:${#cur}-1:1} == "-" ]] && 
                    [[ ${cur} != */ ]]; then
            # The portage cache is appropriate to complete specific versions from.
            COMPREPLY=(${COMPREPLY[@]} $(\
                        for pd in ${portdir} ; do \
                            if [[ -d ${pd}/metadata/cache ]] ; then \
                                builtin cd ${pd}/metadata/cache; \
                                compgen -W "$(compgen -G "${cur}*")" -- "${cur}" ; \
                            fi ; \
                        done))
            fi
        else
            # 1. Collect all the categories among ${portdir}
            local ww=$(\
                for pd in ${portdir}; do
                    builtin cd ${pd};
                    compgen -X "!@(*-*|virtual)" -S '/' -G "$cur*";
                done)

            # 2. Now ugly hack to delete duplicate categories
            local w x
            for x in ${ww} ; do w="${x}\n${w}"; done
            local words=$(echo -e ${w} | sort -u)

            COMPREPLY=($(compgen -W "$words" -- $cur))
                if [[ ${#COMPREPLY[@]} == 1 ]]; then
            COMPREPLY=($(compgen -W "$(\
                    for pd in ${portdir} ; do \
                        if [[ -d ${pd}/metadata/cache ]] ; then
                            builtin cd ${pd}/metadata/cache; \
                            compgen -G "$COMPREPLY*" ; \
                        fi ; \
                    done)" -- $cur))
            fi
        fi

            if [[ -z "${COMPREPLY}" ]] ; then
                only=1
                _pkgname_only ${cur} ${portdir}
            fi
        ;;
    *)
        # Somebody screwed up! :-)
        ;;
    esac
    # 'equery' wants an '=' in front of specific package versions.
    # Add it if there is only one selected package and it isn't there already.
    if [[ ${#COMPREPLY[@]} == 1 && ${COMP_WORDS[COMP_CWORD]:0:1} != "=" ]]
    then
        [[ -z "${only}" ]] && COMPREPLY=("="$COMPREPLY)
    fi
}

#
# This is an helper function for completion of  "-o <list>" / "--option=<list>"
# kind of command lines options.
# 
# Usage: _list_compgen <current> <sep> <item1>[<sep><item2> ...]
# - <current>: what we have so far on the command line
# - <sep>: the separator character used in lists
# - <itemN>: a valid item
# Returns: the function outputs each possible completion (one per line),
# and returns 0. Typical usage is COMPREPLY=($(_list_compgen ...)).
#
# Note: items must not contain the <sep> character (no backslash escaping has 
# been implemented).
#
_list_compgen()
{
    # Read the three parameters. 
    local current="${1}" ; shift
    local sep="${1}" ; shift
    local items="${*}"

    # This is the maximum number of "<current><sep><other_item>" possible
    # completions that should be listed in case <current> is a valid list.
    # Setting it to a negative value means "no bound" (always list everything).
    # Setting it to 0 means "never list anything" (only suggest <sep>).
    # Setting it to a positive value N means "list up to N possible items, and
    # only suggest <sep> if there are more".
    # It is probably not worth a parameter, thus it will defaults to my 
    # prefered setting (1) if not already defined in the environment.
    local max_others_number=${max_others_number:-1}

    # Save IFS. The <sep> character will be used instead in the following.
    local saved_IFS="${IFS}"
    IFS="${sep}"

    # Split the current items list in two parts:
    # - current_item is the last one (maybe partial or even empty)
    # - prefix_item are items are the previous ones
    local current_item="${current##*${sep}}"
    local prefix_items="${current%${current_item}}"

    # Iterate through valid items to recognize those that are:
    # - partial matches of the <current_item>
    # - already used in the list prefix
    # - not used in the list prefix, and not an exact match of <current_item>
    # Also check whether the <current_item> is exactly a valid one.
    local matching_items
    local other_items
    local exact_match
    local my_item
    for my_item in ${items} ; do
        if [[ "${sep}${prefix_items}${sep}" == *"${sep}${my_item}${sep}"* ]] ; then
            # The item has already been used in the list prefix: ignore it.
            continue
        elif [[ "${my_item}" == "${current_item}" ]] ; then
            # The item _exactly_ matches the <current_item>: that means that we
            # will have to suggest some more items to add behind.
            exact_match=1
        elif [[ "${my_item}" == "${current_item}"* ]] ; then
            # The item matches the <current_item>: it will be a possible
            # completion. It will also be a possible additional item in case of
            # exact match.
            matching_items="${matching_items}${sep}${my_item}"
            other_items="${other_items}${sep}${my_item}"
        else
            # The item neither matches the <current_item> nor has been already
            # used: it will only be a possible additional item in case of exact
            # match.
            other_items="${other_items}${sep}${my_item}"
        fi
    done
    matching_items="${matching_items#${sep}}"
    other_items="${other_items#${sep}}"

    # Takes care of the case where <current_item> is not exactly valid but
    # there is only one matching item: force this completion, and handle it
    # just as an exact match.
    if [[ -z "${exact_match}" ]] \
    && [[ "${matching_items}" != *"${sep}"* ]] ; then
        exact_match=1
        current="${current%${current_item}}${matching_items}"
        current_item="${matching_items}"
        matching_items=""
        other_items="${sep}${other_items}${sep}"
        other_items="${other_items/${sep}${current_item}${sep}/${sep}}"
        other_items="${other_items#${sep}}"
        other_items="${other_items%${sep}}"
    fi

    # List all possible completions. They are stored in an array.
    # XXX: maybe if should be COMPREPLY directly? (with no output at the end)
    local my_compreply=()
    local i=0
    if [[ -n "${exact_match}" ]] ; then
        # Found an exact match? Then add "<current>".
        my_compreply[${i}]="${current}"
        let i++
    fi
    if [[ -n "${matching_items}" ]] ; then
        # Found some matching items?
        # Then add "<prefix_items><matching_item>".
        for my_item in ${matching_items} ; do
            my_compreply[${i}]="${prefix_items}${my_item}"
            let i++
        done
    fi
    if [[ -n "${exact_match}" ]] \
    && [[ -n "${other_items}" ]] ; then
        # Found an exact match and some other possible items remain?
        # First, count them:
        local count_others=0
        for my_item in ${other_items} ; do
            let count_others++
        done
        # Then decide how to behave depending on the max_others_number setting:
        if (( max_others_number < 0 )) \
        || (( count_others <= max_others_number )) ; then
            # List the possible "<current><sep><other_item>" completions.
            for my_item in ${other_items} ; do
                my_compreply[${i}]="${current}${sep}${my_item}"
                let i++
            done
        else # Only suggest adding the <sep> character.
            my_compreply[${i}]="${current}${sep}"
            let i++
        fi
    fi

    # Restore IFS.
    IFS="${saved_IFS}"

    # Output the array of possible completions and returns.
    local j=0
    while (( i > j )) ; do
        echo ${my_compreply[$j]}
        let j++
    done
    return 0
}

#
# emerge completion command
#
have emerge && {
_emerge()
{
    local c cur prev curword numwords opts cond prepend
    local words stophere i x
    local action actionpos sysactions pkgpos
    local portdir=$(_portdir -o)
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    numwords=${#COMP_WORDS[*]}
    curword=${COMP_CWORD}
    opts=''

    if [[ ${prev} == '>' || ${prev} == '<' ]] ; then
        COMPREPLY=($(compgen -f -- ${cur}))
        return 0
    fi

    # find action
    for x in ${COMP_LINE} ; do
        if [[ ${x} =~ ^(system|world)$ ]] || [[ ${x} =~ -[CPcs] ]] || \
            [[ ${x} =~ --(clean|config|depclean|info|metadata|prune|regen|resume|search|sync|unmerge) ]]
        then
            action=${x}
            break
        fi
    done

    if [[ -n ${action} ]]; then
        for ((i = 0; i < ${numwords}; i++ )); do
            if [[ ${COMP_WORDS[${i}]} == "${action}" ]]; then
                actionpos=${i}
                pkgpos=$((actionpos + 1))
                break
            fi
        done

        if [[ ${action} == -* && ${action} != --* ]] ; then
            case "${action}" in
            -*C*) action='--unmerge' ;;
            -*P*) action='--prune' ;;
            -*c*) action='--clean' ;;
            -*s*) action='--search' ;;
            esac
        fi
    else
        for ((i = 1; i < ${numwords}; i++ )); do
            if [[ ! ${COMP_WORDS[$i]} == -* ]]; then
                pkgpos=${i}
                break
            fi
        done
        [[ -z ${pkgpos} ]] && pkgpos=${numwords}
    fi

    # Handle special cases.
    if [[ ${action} == "--search" ]] || [[ ${COMP_LINE} == *" "-@(S|-searchdesc)* ]] || \
        [[ ${COMP_LINE} == *" "-@(V|-version)* ]] || [[ ${action} == "--metadata" ]]
    then
        unset COMPREPLY
        return 0
    elif [[ ${COMP_LINE} == *" "-@(h|-help)* ]] ; then
        unset COMPREPLY
        [[ ${curword} -eq 2 ]] && COMPREPLY=($(compgen -W 'system world --sync' -- ${cur}))
        return 0
    fi

    # Complete on options.
    if [[ ${cur} == -* ]]; then
        # If a resume option was specified, it needs special handling.
        if [[ ${COMP_LINE} =~ --(resume|skipfirst) ]] ; then
            if [[ ${cur} == --* ]]; then
                opts="--ask --pretend --resume --skipfirst"
            elif [[ ${cur} == -* ]]; then
                [[ ${COMP_LINE} =~ --(ask|pretend) ]] && opts="-a -p"
            fi
        elif [[ ${cur} == --* ]]; then
            # Complete on long options.
            opts="--alphabetical --ask \
                --buildpkg --buildpkgonly \
                --changelog --clean --color=y --color=n --columns --complete-graph --config \
                --debug --deep --depclean \
                --emptytree \
                --fetch-all-uri --fetchonly \
                --getbinpkg --getbinpkgonly \
                --ignore-default-opts --info \
                --jobs= \
                --keep-going \
                --metadata \
                --newuse --noconfmem --nodeps --noreplace --nospinner \
                --oneshot --onlydeps \
                --pretend --prune \
                --quiet \
                --reinstall=changed-use --regen \
                --search \
                --sync \
                --tree \
                --unmerge --update --upgradeonly --usepkg --usepkgonly \
                --verbose \
                --with-bdeps=y --with-bdeps=n"
            if [[ ${curword} -eq 1 ]] && [[ ${numwords} -eq 2 ]] ; then
                opts="${opts} --help --resume --searchdesc --version"
            fi
        elif [[ ${cur} == -* ]]; then
            # Complete on short options.
            opts="-B -D -G -K -N -O -a -b -d -e -f -g -k -l -n -o -p -q -t -u -v"
            if [[ ${curword} -eq 1 ]] && [[ ${numwords} -eq 2 ]] ; then
                opts="${opts} -h -S -V"
            fi
            if [[ -z ${action} ]] && [[ ${curword} -eq $((pkgpos - 1)) ]] ; then
                opts="${opts} -C -P -c -s"
            fi
        fi

        COMPREPLY=($(compgen -W "${opts}" -- ${cur}))

        # NOTE: This slows things down!
        # (Adapted from bash_completion by Ian Macdonald <ian@caliban.org>)
        # This removes any options from the list of completions that have
        # already been specified on the command line.
        COMPREPLY=($(echo "${COMP_WORDS[@]}" | \
            (while read -d ' ' i; do
                [[ -z ${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
    fi # options

    # Stop completion if a special case is encountered.
    if [[ ${action} =~ (system|world) ]] || \
        [[ ${COMP_LINE} =~ --(depclean|metadata|regen|resume|skipfirst|sync) ]]
    then
        unset COMPREPLY
        return 0
    fi

    # Complete on installed packages when unmerging.
    if [[ "${action}" == '--unmerge' ]]; then
    if [[ -n "${cur}" ]] ; then
        if [[ "${cur}" == */* ]]; then
        words=$(builtin cd @GENTOO_PORTAGE_EPREFIX@/var/db/pkg; compgen -G "${cur}*")
        else
        words=$(builtin cd @GENTOO_PORTAGE_EPREFIX@/var/db/pkg; compgen -S '/' -G "${cur}*")

                local n=0
                for i in ${words} ; do
                    [[ ${i} == ${cur}* ]] && n=$((n+1))
                done

                if [[ ${n} -eq 1 ]] ; then
                    words="$(builtin cd @GENTOO_PORTAGE_EPREFIX@/var/db/pkg ; compgen -G "*-*/*")"
                fi
        fi
            COMPREPLY=($(for i in ${words} ; do \
                            [[ ${i} == ${cur}* ]] && echo ${i} ; \
                        done))
    else
        COMPREPLY=($(builtin cd @GENTOO_PORTAGE_EPREFIX@/var/db/pkg ; compgen -S '/' -G "*-*"))
    fi

        [[ -z "${COMPREPLY}" ]] && _pkgname_only ${cur} @GENTOO_PORTAGE_EPREFIX@/var/db/pkg
        return 0
    fi
    
    # Check for conditional.
    cond="${cur%%[A-Za-z0-9]*}"
    cur="${cur:${#cond}}"
    if [[ ${cond:0:1} == "'" || ${cond:0:1} == '"' ]] ; then
        prepend="-P ${cond:1}"
        c="${cond:1}"
    else
        c="${cond}"
    fi
    
    # Handle cases where a conditional is specified.
    if [[ -n "${cond}" ]]; then
    if [[ -n "${cur}" ]]; then
            if [[ ${cur} == */* ]]; then
                if [[ ${cur} == *-[0-9]* ]] ; then
                    words="$(\
                        for pd in ${portdir} ; do \
                            builtin cd ${pd} ; \
                            local cat="${cur%/*}" ; \
                            local pkg="$(echo ${cur%-[0-9]*})" ; \
                            pkg="${pkg##*/}" ; \
                            for x in ${cat}/${pkg}/*.ebuild ; do \
                                [[ -f ${x} ]] || continue ; \
                                x="${x/${pkg}\/}" ; \
                                echo "${x%*.ebuild}" ; \
                            done ; \
                        done)"
                else
            words="$(\
                    for pd in ${portdir} ; do \
                        builtin cd ${pd}; \
                        compgen -X "*metadata.xml" -G "${cur}*" -- ${cur} ; \
                    done)"
                fi

                local w
                for x in $words ; do
                    w="${x}\n${w}"
                done

                words=$(echo -ne ${w} | sort | uniq)
                COMPREPLY=( ${words} )
        
                # Complete on the specific versions (if appropriate).
                if [[ ${#COMPREPLY[@]} -le 1 ]] ; then
            COMPREPLY=($(\
                        for pd in ${portdir} ; do \
                            if [[ -d ${pd}/metadata/cache ]] ; then
                                builtin cd ${pd}/metadata/cache; \
                                compgen ${prepend} -G "${cur}*" -- "${cur}" ; \
                            else \
                                builtin cd ${pd} ; \
                                local cat="${cur%/*}" ; \
                                local pkg="$(echo ${cur%-[0-9]*}*)" ; \
                                pkg="${pkg##*/}" ; \
                                for x in ${cat}/${pkg}/*.ebuild ; do \
                                    [[ -f "${x}" ]] || continue ; \
                                    x="${x/${pkg}\/}" ; \
                                    if [[ ${cond:0:1} == "'" ]] || \
                                        [[ ${cond:0:1} == '"' ]] ; then 
                                        echo "${c}${x%*.ebuild}" ; \
                                    else
                                        echo "${x%*.ebuild}" ; \
                                    fi ; \
                                done ; \
                            fi ; \
                        done))
                else
                    COMPREPLY=($(compgen ${prepend} -W "${words}" -- $cur))
                fi
            else
                words="$(\
                    for pd in ${portdir} ; do \
                        builtin cd ${pd} ; \
                        compgen ${prepend} -S '/' -G "${cur}*" -- "${cur}" ; \
                    done)"

                local w
                for x in words ; do
                    w="${x}\n${w}"
                done

                COMPREPLY=($(echo -e ${w} | uniq))
                [[ ${#COMPREPLY[@]} = 1 ]] && \
                    COMPREPLY=($(\
                        for pd in ${portdir} ; do \
                            builtin cd ${pd} ; \
                            compgen ${prepend} -G "${cur}*/*" -- "${cur}" ; \
                        done))
            fi
        else
        words="$(\
                for pd in ${portdir} ; do \
                    builtin cd ${pd}; \
                    compgen -G "*-*"; \
                done)"
        COMPREPLY=($(compgen -W "${words}" -- "${cur}"))
    fi
        
        # If all else fails, try to complete on package names without the
    # category being specified.
    if [[ -z "${COMPREPLY}" ]]; then
        words="$(\
                for pd in ${portdir} ; do \
                    builtin cd ${pd}; \
                    for i in *-*/${cur}*; do \
                        [[ -d $i ]] && echo ${i##*/}; \
                    done ; \
                done)"

        COMPREPLY=($(compgen ${prepend} -W "${words}" -- ${cur}))

        if [[ ${#COMPREPLY[@]} -le 1 ]]; then
        # Now complete on the specific versions.
        words="$(\
                    for pd in ${portdir} ; do \
                        if [[ -d ${pd}/metadata/cache ]] ; then \
                            builtin cd ${pd}/metadata/cache; \
                            for i in */${cur}*; do \
                                [[ -f $i ]] && echo ${i##*/}; \
                            done ; \
                        fi ; \
                    done)"
        COMPREPLY=($(compgen ${prepend} -W "${words}" -- "${cur}"))
        fi
    fi
    return 0
    fi

    # Complete on packages.
    #
    # Only allow these actions if no packages have been specified.
    #
    # TODO: This doesn't block these actions if no categories are
    #       specified. Please fix me.
    #
    #       e.g. emerge -a gentoo-dev-sources
    #
    #            will still allow system and world actions to be specified,
    #            as opposed to
    #
    #            emerge -a sys-kernel/gentoo-dev-sources
    #
    if [[ ${COMP_CWORD} -eq 1 ]] || [[ ! " ${COMP_LINE} " == *" "*[/]*" "* ]] ; then
        sysactions=$'\n'"system"$'\n'"world"
    else
        sysactions=''
    fi

    if [[ -n "${cur}" ]] ; then
        if [[ ${cur} == */* ]] ; then
            words=$(\
                for pd in ${portdir} ; do \
                    builtin cd ${pd}; \
                    compgen -X "*metadata.xml" -G "${cur}*" ; \
                done)"${sysactions}"
        else
            local ww=$(\
                for pd in ${portdir} ; do \
                    builtin cd ${pd} ; \
                    compgen -X "!@(*-*|virtual)" -S '/' -G "${cur}*"; \
                done)"${sysactions}"
            # complete on virtuals
            ww="${ww} $(\
                for pd in ${portdir} ; do \
                    if [[ -d ${pd}/profiles ]] ; then
                        find ${pd}/profiles -name virtuals -exec \
                            sed -n -e 's|^\(virtual/[[:alnum:]]\+\).*$|\1|p' {} \; | \
                            sort -u
                    fi ; \
                done)"

            local w
            for x in ${ww} ; do w="${x}\n${w}" ; done

            words=$(echo -e ${w} | sort -u)

            local n=0
            for i in ${words} ; do
                [[ ${i} == ${cur}* ]] && n=$((n+1))
            done

            if [[ ${n} -eq 1 ]] ; then
                words=$(for pd in ${portdir} ; do \
                            builtin cd ${pd} ; \
                            compgen -G "*-*/*" ; \
                        done)"${sysactions}"
            fi
        fi
        COMPREPLY=($(for i in ${words} ; do \
                        [[ ${i} == ${cur}* ]] && echo ${i} ; \
                    done))
    else
        words="$(\
            for pd in ${portdir} ; do \
                builtin cd ${pd} ; \
                compgen -S '/' -G "*-*" ; \
            done)""${sysactions}"
    COMPREPLY=($(compgen -W "${words}" -- ${cur}))
    fi

    # If all else fails, try to complete on package names without the
    # category being specified.
    if [[ -z "${COMPREPLY}" ]]; then
        words="$(\
            for pd in ${portdir} ; do \
                builtin cd ${pd}; \
                for i in [a-z]*-[a-z0-9]*/${cur}*; do \
                    [[ -d $i ]] && echo ${i##*/}; \
                done ; \
            done)"
    COMPREPLY=($(compgen -W "${words}" -- ${cur}))
    fi

    return 0
}
complete -o filenames -F _emerge emerge
}

#
# ebuild completion command
#
have ebuild && {
_ebuild()
{
    local cur opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"

    opts="help setup clean fetch digest manifest unpack compile test preinst \
        install postinst qmerge merge unmerge prerm postrm config package rpm \
        configure prepare"

    if [[ $COMP_CWORD -eq 1 ]] ; then
    COMPREPLY=($(compgen -f -X "!*.ebuild" -- ${cur}) \
            $(compgen -d -- ${cur}) \
            $(compgen -W '--debug --force --help --ignore-default-opts --skip-manifest' -- ${cur}))

    elif [[ $COMP_CWORD -eq 2 && "${COMP_WORDS[1]}" = "--debug --force --ignore-default-opts --skip-manifest" ]] ; then
    COMPREPLY=($(compgen -f -X "!*.ebuild" -- ${cur}) $(compgen -d -- ${cur}))

    elif [[ $COMP_CWORD -ge 2 ]] ; then
    COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
    fi
    return 0
}
complete -o filenames -F _ebuild ebuild
}

#
# Gentoo init.d completion
#

_gentoo_style_init()
{
    local script="${COMP_WORDS[0]}"
    local cur="${COMP_WORDS[$COMP_CWORD]}"

    if [[ ( -f "${script}" || -h "${script}" ) && -r "${script}" ]] \
    && [[ "${script}" != *.sh ]] \
    && [[ "$(head -n 1 "${script}")" = "#!/sbin/runscript" ]]
    then
    [[ $COMP_CWORD -gt 1 ]] && return 1
    COMPREPLY=($(opts="start stop status restart pause zap ineed needsme iuse usesme broken"; \
            eval "$(grep '^opts=' "${script}")"; echo "${opts}"))
    [[ -n "$COMPREPLY" ]] || COMPREPLY=(start stop restart zap)
    COMPREPLY=($(compgen -W "${COMPREPLY[*]}" -- "${cur}"))
    else
    COMPREPLY=($(compgen -o default -- "${cur}"))
    fi
    return 0
}
complete -F _gentoo_style_init @GENTOO_PORTAGE_EPREFIX@/etc/init.d/*

#
# rc completion command
#
have rc && {
_rc()
{
    local cur
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    if [[ ${#COMP_WORDS[*]} -le 2 ]]; then
    COMPREPLY=($(compgen -W "$(for i in @GENTOO_PORTAGE_EPREFIX@/etc/runlevels/*; do echo ${i##*/}; done)" -- $cur))
    fi
    return 0
}
complete -F _rc rc
}

#
# rc-status completion command
#
have rc-status && {
_rcstatus()
{
    local cur
    cur="${COMP_WORDS[COMP_CWORD]}"
    if [[ $COMP_CWORD -eq 1 ]]; then
        if [[ "${cur}" == --* ]]; then
        COMPREPLY=($(compgen -W '--all --list --unused' -- ${cur}))
    elif [[ "${cur}" == -* ]]; then
        COMPREPLY=($(compgen -W '-a -l -u' -- ${cur}))
    else
        COMPREPLY=($(compgen -W "$(rc-status --list)" -- ${cur}))
    fi
    else
    unset COMPREPLY
    fi
    return 0
}
complete -F _rcstatus rc-status
}

#
# rc-update completion command
#
have rc-update && {
_rcupdate()
{
    local cur show
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    if [[ $COMP_CWORD -eq 1 ]]; then
    if [[ "${cur}" == -* ]]; then
        COMPREPLY=($(compgen -W '-a -d -s' -- ${cur}))
    else
        COMPREPLY=($(compgen -W 'add del show' ${cur}))
    fi
    else
        if [[ "${COMP_WORDS[1]}" == "show" ]] || [[ "${COMP_WORDS[1]}" == "-s" ]]; then
        show="TRUE"
    fi
    if ([[ $COMP_CWORD -eq 3 ]] && [[ -z "$show" ]]) || \
            ([[ $COMP_CWORD -eq 2 ]] && [[ -n "$show" ]])
        then
        COMPREPLY=($(compgen -W "$(for i in @GENTOO_PORTAGE_EPREFIX@/etc/runlevels/*; do echo ${i##*/}; done)" -- $cur))
    elif [[ $COMP_CWORD -eq 2 ]]; then
        COMPREPLY=($(compgen -X "*.@(c|sh|test)" -W "$(for i in @GENTOO_PORTAGE_EPREFIX@/etc/init.d/*; do echo ${i##*/}; done)" $cur))
    elif [[ ${#COMP_WORDS[*]} -gt 2 ]] ; then
        COMPREPLY=($(compgen -W "$(for i in @GENTOO_PORTAGE_EPREFIX@/etc/runlevels/*; do echo ${i##*/}; done)" -- $cur))
    else
        unset COMPREPLY
    fi
    fi
    return 0
}
complete -F _rcupdate rc-update
}

#
# gcc-config completion command
#
have gcc-config && {
_gcc_config() {
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    opts="-O --use-old \
        -P --use-portage-chost \
        -c --get-current-profile \
        -l --list-profiles \
        -E --print-environ \
        -B --get-bin-path \
        -L --get-lib-path \
        -X --get-stdcxx-incdir"

    if [[ "${cur}" == -* ]] ; then
        COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
        return 0
    elif [[ ${COMP_CWORD} -eq 1 ]] ; then
        COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) \
            $(compgen -W "$(gcc-config -l | sed -r -e 's/(\[([^]]*)\]) //g')" \
                -- ${cur}) )
        return 0
    fi

    case "${prev}" in
        -O|--use-old|-P|--use-portage-chost|-c|--get-current-profile|-l|--list-profiles)
            COMPREPLY=()
            ;;
        *)
            COMPREPLY=( $(compgen -W "\
                $(gcc-config -l | sed -r -e 's/(\[([^]]*)\]) //g')" -- ${cur}) )
            ;;
    esac
}
complete -F _gcc_config gcc-config
}

#
# distcc-config completion command
#
have distcc-config && {
_distccconfig()
{
    local cur curword numwords opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    numwords=${#COMP_WORDS[*]}
    curword=${COMP_CWORD}
    if [[ ${numwords} -gt 3 ]]; then
    unset COMPREPLY
    return 0
    fi
    if [[ "${cur}" == -* ]] || [ ${curword} -eq 1 ]; then
    if [[ ${numwords} -le 2 ]] && [[ ${curword} -eq 1 ]]; then
        opts="--get-hosts \
        --get-verbose \
        --get-log \
        --set-hosts \
        --set-verbose \
        --set-log \
        --add-path \
        --no-path"
    else
        opts=""
    fi
    else
    opts=""
    fi
    COMPREPLY=($(compgen -W "${opts}" | grep ^$cur))
    return 0
}
complete -F _distccconfig distcc-config
}

#
# java-config completion command
#
have java-config && {
_javaconfig()
{
    local cur prev curword numwords opts args arg spec flag sedcmd grepcmd
    local multiplepkgs pkgs execopts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    numwords=${#COMP_WORDS[*]}
    curword=${COMP_CWORD}
    opts=""
    args=""
    pkgs=""
    sedcmd="sed -r -e s/\[([^]]+)\].*/\1/"
    vmsedcmd="sed -r -e s/\[([^]]+)\]/\1/"
    grepcmd="egrep -o (--set-(system|user)-(classpath|vm)=)"
    multiplepkgs=""
    execopts="HtmlConverter JavaPluginControlPanel \
    appletviewer awt_robot \
    extcheck \
    idlj \
    j2sdk-config jar jarsigner \
    java java-rmi.cgi java_vm javac javadoc javah javap jdb \
    keytool kinit klist ktab \
    native2ascii \
    oldjava oldjavac oldjdb orbd \
    policytool \
    realpath rmic rmid rmiregistry \
    serialver servertool \
        tnameserv"
    if [[ "${cur}" == -* ]] || [ ${curword} -eq 1 ]; then
    case "${cur}" in
        --java)
        opts="--java --javac --java-version"
        ;;
        --j@(a@(r|va@(c|-version))|@(dk|re)-home))
        opts=""
        ;;
        --list-available-@(packages|vms))
        opts=""
        ;;
        --@(exec|set-@(user|system)-@(classpath|vm)))
        opts="${cur}="
        ;;
        --set-@(user|system)-@(classpath|vm)=)
        if [[ "${cur}" == "--set-system-vm=" ]] || [[ "${cur}" == "--set-user-vm=" ]]; then
            flag="--list-available-vms"
            args=$(java-config --nocolor "${flag}" | cut --delimiter=' ' --fields=2 | ${vmsedcmd})
        else
            flag="--list-available-packages"
            args=$(java-config --nocolor "${flag}" | ${sedcmd})
        fi
        for arg in ${args}; do
            [[ -n "${opts}" ]] && opts="${opts} ${arg}" || opts="${arg}"
        done
        COMPREPLY=($(compgen $nospace -W "${opts}"))
        return 0
        ;;
        --exec=)
        COMPREPLY=($(compgen $nospace -W "${execopts}"))
        return 0
        ;;
        *)
            if [[ "${cur}" == "--set-system-vm="* ]] || [[ "${cur}" == "--set-user-vm="* ]]; then
            args=$(java-config --nocolor --list-available-vms | cut --delimiter=' ' --fields=2 | ${vmsedcmd})
            if [[ "${cur}" == "--set-system-vm="* ]]; then
            spec=${cur##--set-system-vm=}
            else
            spec=${cur##--set-user-vm=}
            fi
            for arg in ${args}; do
            if [[ "${arg:0:${#spec}}" == "${spec}" ]]; then
                [[ -n "${opts}" ]] && opts="${opts} ${arg}" || opts="${arg}"
            fi
            done
            [[ "${opts}" == "${spec}" ]] && opts=""
            COMPREPLY=($(compgen -W "${opts}"))
            return 0
        elif [[ "${cur}" == "--set-system-classpath="* ]] || [[ "${cur}" == "--set-user-classpath="* ]]; then
            args=$(java-config --nocolor --list-available-packages | ${sedcmd})
            [[ $(echo "${cur}" | grep -c ",") -gt 0 ]] && multiplepkgs="true"
            if [[ "${cur}" == "--set-system-classpath="* ]]; then
            spec="${cur##--set-system-classpath=}"
            else
            spec="${cur##--set-user-classpath=}"
            fi
            if [[ -n "${multiplepkgs}" ]]; then
            pkgs="${spec%,*}"
            spec="${spec##*,}"
            fi
            if [[ -n "${multiplepkgs}" ]]; then
                for arg in ${args}; do
                if [[ "${spec}" ]]; then
                    if [[ "${arg:0:${#spec}}" == "${spec}" ]] \
                        && [[ ! $(echo "${cur}" | egrep -o "(=|,)${arg},") ]]
                                then
                    [[ -n "${opts}" ]] && opts="${opts} ${pkgs},${arg}" || opts="${pkgs},${arg}"
                    fi
                else
                    if [[ ! $(echo "${cur}" | egrep -o "(=|,)${arg},") ]]; then
                        [[ -n "${opts}" ]] && opts="${opts} ${pkgs},${arg}" || opts="${pkgs},${arg}"
                    fi
                fi
                done
            [[ "${opts}" == "${pkgs},${spec}" ]] && opts=""
            else
                for arg in ${args}; do
                if [[ "${spec}" ]] && [[ "${arg:0:${#spec}}" == "${spec}" ]]; then
                [[ -n "${opts}" ]] && opts="${opts} ${arg}" || opts="${arg}"
                fi
            done
            [[ "${opts}" == "${spec}" ]] && opts=""
            fi
            COMPREPLY=($(compgen -W "${opts}"))
            return 0
        elif [[ "${cur}" == "--exec="* ]]; then
            spec=${cur##--exec=}
            for arg in ${execopts}; do
            if [[ "${arg:0:${#spec}}" == "${spec}" ]]; then
                [[ -n "${opts}" ]] && opts="${opts} ${arg}" || opts="${arg}"
            fi
            done
            [[ "${opts}" == "${spec}" ]] && opts=""
            COMPREPLY=($(compgen -W "${opts}"))
            return 0
        else
            opts="--classpath --clean-system-classpath --clean-user-classpath \
                --exec \
            --full-classpath \
                --jar --java --javac --java-version --jdk-home --jre-home \
                --list-available-packages --list-available-vms \
            --nocolor \
            --set-system-classpath --set-system-vm --set-user-classpath --set-user-vm"
            [[ "$prev" == "--nocolor" ]] && opts="${opts/--nocolor}"
        fi
            ;;
        esac
    elif [[ "$prev" == "--nocolor" ]] && [ ${curword} -eq 2 ] && [ $numwords -le 3 ]; then
    opts="--classpath --clean-system-classpath --clean-user-classpath \
        --exec \
        --full-classpath \
        --jar --java --javac --java-version --jdk-home --jre-home \
        --list-available-packages --list-available-vms \
        --set-system-classpath --set-system-vm --set-user-classpath --set-user-vm"
    fi
    COMPREPLY=($(compgen $nospace -W "${opts}" -- ${cur}))
    return 0
}
complete $nospace -F _javaconfig java-config
}

#
# browser-config completion command
#
have browser-config && {
_browserconfig()
{
    local cur prev
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    if [[ ${COMP_CWORD} -eq 1 ]]; then
    COMPREPLY=($(compgen -W '-b -h -m' -- ${cur}))
    elif [[ "${prev}" == "-b" ]]; then
    COMPREPLY=($(compgen -W "$(for i in @GENTOO_PORTAGE_EPREFIX@/usr/share/browser-config/*; do [ -f $i ] && echo ${i##*/}; done)" $cur))
    elif [[ "${prev}" == "-m" ]]; then
        COMPREPLY=($(compgen -W "same_window new_window new_tab new_browser" -- ${cur}))
    if [[ -z "${COMPREPLY}" ]]; then
        COMPREPLY=''
    fi
    else
    unset COMPREPLY
    fi
    return 0
}
complete -F _browserconfig browser-config
}

#
# Bash completion for the Gentoo 'equery' command
#
have equery && {
_equery()
{
    local cur prev mode portdir i j
    portdir=$(_portdir)
    mode="GLOBAL"
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    # Find out what we're currently doing here.
    j=0
    for i in "${COMP_WORDS[@]}"; do
        if [[ $j -lt $COMP_CWORD ]]; then
        j=$((j + 1))
        case $i in
                @(belongs|ch@(anges|eck)|dep@(ends|graph)|files|glsa|list|meta|s@(ize|tats)|uses|which|hasuse|b|c|k|d|g|f|a|h|l|m|s|t|u|w))
            mode=$i
            ;;
        esac
    fi
    done
    # Now get to work.
    case $mode in
    GLOBAL)
        # Complete commands and global options.
        case $cur in
        -*)
            COMPREPLY=($(compgen -W "-q --quiet -C --nocolor -h --help -V --version" -- $cur))
            ;;
        *)
            COMPREPLY=($(compgen -W "belongs changes check depends depgraph files glsa hasuse list meta size stats uses which" -- $cur))
            ;;
        esac
        ;;
    c?(hanges)|a|glsa|t|stats)
        # These commands have not been implemented in 'equery' yet ...
        echo -n "# Not implemented! "
        ;;
    f?(iles))
        # Only complete if the previous entry on the command line is not
        # a package name.
        if [[ ${prev} == ${mode} || ${prev:0:1} == "-" ]]; then
            # --filter=<list>: completion of the files types list
            if [[ ${prev} == "-f" || "${cur}" == "--filter="* ]] ; then
                COMPREPLY=($(_list_compgen "${cur#--filter=}" , \
                    dir,obj,sym,dev,fifo,path,conf,cmd,doc,man,info))
                return 0
            fi
        case $cur in
            --f*) 
            # don't handle --filter= with others to avoid space after the "="
            COMPREPLY=($(compgen -P "--filter=" \
                -W "dir obj sym dev fifo path conf cmd doc man info"))
            ;;
            -*)
            COMPREPLY=($(compgen -W "--help --timestamp --md5sum
                        --type --filter=" -- $cur))
            ;;
            *)
            # Only installed packages can have their files listed.
                _pkgname -I $cur
            ;;
        esac
        fi
        ;;
    l?(ist))
        # Only complete if the previous entry on the command line is not
        # a package name.
        if [[ ${prev} == ${mode} || ${prev:0:1} == "-" ]]; then
        case "${cur}" in
            -*)
            COMPREPLY=($(compgen -W "--help -i --installed -I --exclude-installed -p --portage-tree -o --overlay-tree" -- $cur))
            ;;
            *)
                        case "${prev}" in
                            -i|--installed)
                                _pkgname -I $cur
                                ;;
                            *)
                    # Complete on all package names.
                    _pkgname -A $cur
                    ;;
                        esac
                        ;;
        esac
        fi
        ;;
    b?(elongs))
        # Only complete if the previous entry on the command line is not
        # a file name.
        if \
            [[ \
            ${prev} == ${mode} || \
            ${prev:0:1} == "-" || \
            ${COMP_WORDS[COMP_CWORD-2]} == "-c" || \
            ${COMP_WORDS[COMP_CWORD-2]} == "--category" \
        ]] && \
        [[ \
            ${prev} != "-c" && \
            ${prev} != "--category" \
        ]]
        then
        case $cur in
            -*)
                COMPREPLY=($(compgen -W "--help -c --category -e --earlyout" -- $cur))
                ;;
            *)
                COMPREPLY=($(compgen -f -- $cur) \
                    $(compgen -d -S '/' -- $cur))
                ;;
        esac
        # Are we completing a category?
        elif [[ ${prev} == "-c" || ${prev} == "--category" ]]; then
        COMPREPLY=($(builtin cd ${portdir}/metadata/cache; compgen -W "$(compgen -G '*')" -- $cur))
        fi
        ;;
    @(u?(ses)|w?(hich)))
        # Only complete if the previous entry on the command line is not
        # a package name.
        if [[ ${prev} == ${mode} ]]; then
            # Complete on all package names.
            _pkgname -A $cur
                COMPREPLY=($(compgen -W "${COMPREPLY[@]} --help" -- ${cur}))
        fi
        ;;
    g|depgraph)
        # Only complete if the previous entry on the command line is not
        # a package name.
        if [[ ${prev} == ${mode} || ${prev:0:1} == "-" ]]; then
            case $cur in
            -*)
                COMPREPLY=($(compgen -W "--help -U --no-useflags -l --linear" -- $cur))
            ;;
            *)
            # Complete on all package names.
            _pkgname -A $cur
            ;;
        esac
        fi
        ;;
    d?(epends))
        # Only complete if the previous entry on the command line is not
        # a package name.
        if [[ ${prev} == ${mode} || ${prev:0:1} == "-" ]]; then
        case $cur in
            -*)
                COMPREPLY=($(compgen -W "--help -a --all-packages -d --direct -D --indirect" -- $cur))
            ;;
            *)
            case $prev in
                -a|--all-packages)
                # Complete on all package names.                            
                _pkgname -A $cur
                ;;
                *)
                # Complete on installed package names.
                    _pkgname -I $cur
                ;;
                        esac
                        ;;
        esac
        fi
        ;;
    m?(eta))
        # Only complete if the previous entry on the command line is not
        # a package name.
        if [[ ${prev} == ${mode} || ${prev:0:1} == "-" ]]; then
        case $cur in
            -*)
                COMPREPLY=($(compgen -W "--help -h --description -d --herd -H --keywords -k --maintainer -m --useflags -u --upstream -U --xml -x" -- $cur))
            ;;
            *)
                _pkgname -A $cur
            ;;
        esac
        fi
        ;;
    k|check)
        # Only complete if the previous entry on the command line is not
        # a package name.
        if [[ ${prev} == ${mode} ]]; then
            case $cur in
                -*)
                    COMPREPLY=($(compgen -W "${COMPREPLY[@]} --help" -- ${cur}))
                ;;
                *)
                # Only installed packages can have their integrity verified.
                    _pkgname -I $cur
                ;;
            esac
        fi
        ;;
    s?(ize))
        # Only complete if the previous entry on the command line is not
        # a package name.
        if [[ ${prev} == ${mode} || ${prev:0:1} == "-" ]]; then
        case $cur in
            -*)
            COMPREPLY=($(compgen -W "--help -b --bytes" -- $cur))
            ;;
            *)
            # Only installed packages can have their size calculated.
            _pkgname -I $cur
            ;;
        esac
        fi
        ;;
        h?(asuse))
        # Only complete if the previous entry on the command line is not
        # a package name.
        if [[ ${prev} == ${mode} || ${prev:0:1} == "-" ]]; then
            case $cur in
                -*)
                COMPREPLY=($(compgen -W "--help -i --installed -I --exclude-installed -p --portage-tree -o --overlay" -- $cur))
                ;;
                *)
                local glob loc
                        [[ -f ${portdir}/profiles/use.desc ]] || return 0
                        [[ -f ${portdir}/profiles/use.local.desc ]] || return 0
                glob=$(sed -n -e 's/^\([^ ]\+\) - .*$/\1/p' ${portdir}/profiles/use.desc)
                loc=$(sed -n -e 's/^[^ ]\+:\([^ ]*\) - .*$/\1/p' ${portdir}/profiles/use.local.desc)
                COMPREPLY=($(compgen -W "$glob $loc" -- $cur))
                ;;
            esac
            fi
            ;;
    esac
    return 0
}
complete -F _equery equery
}

#
# ekeyword completion
#

have ekeyword && {
_ekeyword()
{
    local cur portdir archl_s archl_u archl_r archl_m arch
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    portdir=$(_portdir)

    [[ -f ${portdir}/profiles/arch.list ]] || return 0

    for arch in all $(< ${portdir}/profiles/arch.list) ; do
        archl_m="${archl_m} -${arch}"
        archl_u="${archl_u} ~${arch}"
        archl_r="${archl_r} ^${arch}"
        archl_s="${archl_s}  ${arch}"
    done

    case ${cur} in
        -*)
            COMPREPLY=($(compgen -W "${archl_m}" -- ${cur}))
            ;;
        ~*)
            COMPREPLY=($(compgen -W "${archl_u}" -- ${cur}))
            ;;
        ^*)
            COMPREPLY=($(compgen -W "${archl_r}" -- ${cur}))
            ;;
        *)
            COMPREPLY=($(compgen -W "${archl_s}" -- ${cur}))
            _filedir 'ebuild'
            ;;
        esac
}
complete -o filenames -F _ekeyword ekeyword
}

#
# portageq completion
#

have portageq && {
_portageq() {
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"

    opts="config_protect_mask \
      config_protect \
      vdb_path \
      gentoo_mirrors \
      all_best_visible \
      match \
      best_visible \
      mass_best_visible \
      has_version \
      portdir \
      envvar \
      mass_best_version \
      best_version \
      pkgdir \
      portdir_overlay \
      distdir"
    
    if [[ $COMP_CWORD -eq 1 ]] ; then
    # would always be correct, but it's pretty slow...
    #COMPREPLY=($(compgen -W "$(portageq | grep '^   [[:lower:]]' | \
    #    sed -e 's/^.*[[:space:]]\([[:lower:]_]\+\)[[:space:]].*$/\1/')" \
    #    -- ${cur}))
    COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
    fi

    case "${prev}" in
    config*|vdb_path|gentoo_mirrors|*dir*)
        COMPREPLY=()
        ;;
        
    # this also isn't the fastest, but I welcome an alternative method
    envvar)
        COMPREPLY=($(compgen -W "$(env -i emerge -v --info | \
                sed -n -e '/^[[:upper:]].*=".*"/s/^\(.*\)=".*$/\1/p')" -- ${cur}))
        ;;
        
    *v@(isible|ersion)|match)
        COMPREPLY=($(compgen $nospace -W '/' -- $cur))
        ;;
    
    # $prev is a path, so complete on category/package
    */*)
            local x a=0
            for x in ${COMP_WORDS[@]} ; do
                # This is the only one 
                if [[ "${x}" == "all_best_visible" ]] ; then
                    a=1
                    break
                fi
            done

            if [[ ${a} -eq 1 ]] ; then
                COMPREPLY=()
            else
                # Check for conditional.
#                cond="${cur%%[A-Za-z0-9]*}"
#                cur="${cur:${#cond}}"

#                if [[ -n "${cond}" ]] ; then
#                    _pkgname -A $cur
#                else
                    _pkgname -A $cur
#                fi
            fi
        ;;      
    esac    
}

complete -F _portageq portageq
}

#
# webapp-config completion
#

have webapp-config && {
_webapp_complete_appver()
{
    local x proot ibase cur="$2"
    eval $(. @GENTOO_PORTAGE_EPREFIX@/etc/vhosts/webapp-config ; \
        echo proot="${MY_PERSISTROOT:-@GENTOO_PORTAGE_EPREFIX@/var/db/webapps}" ; \
        echo ibase="${WA_INSTALLSBASE:-installs}")

    case "$1" in
    # complete on installed
    installed)
        COMPREPLY=($(compgen -W "$(\
        for x in ${proot}/*/*/installs ; do \
            if [[ -f "${x}" ]] ; then \
            local y="${x%/*}" ; \
            y="${y%/*}" ; \
            echo "${y##*/}" ; \
            fi ; \
        done)" -- ${cur}))
        ;;
        
    # complete on uninstalled
    uninstalled)
        COMPREPLY=($(compgen -W "$(\
        for x in ${proot}/*/* ; do \
            if [[ ! -f "${x}/${ibase}" ]] ; then \
            local y="${x%/*}" ; \
            echo "${y##*/}" ; \
            fi ; \
        done)" -- ${cur}))
        ;;
        
    # all
    all)
        COMPREPLY=($(compgen -W "$(\
        for x in ${proot}/* ; do \
            [[ -d "${x}" ]] && echo "${x##*/}" ; \
        done)" -- ${cur}))
        ;;
        
    # complete on version
    *)
        [[ -d "${proot}/$1" ]] || return 1
        COMPREPLY=($(compgen -W "$(\
        for x in ${proot}/$1/* ; do \
            [[ -d "${x}" ]] && echo "${x##*/}" ; \
        done)" -- ${cur}))
        ;;
    esac
}

_webapp_config()
{
    local cur prev actions opts hostroot
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"

    actions="-I --install -U --upgrade -C --clean --list-installs \
    --list-unused-installs --show-installed --show-postinst \
    --help -v --version"
    opts="--bug-report --pretend -p -u --user -g --group \
    -d --dir -h --host -V --verbose --soft --secure --virtual-dirs \
    --virtual-files --force-virtual"

    eval $(. @GENTOO_PORTAGE_EPREFIX@/etc/vhosts/webapp-config ; \
    echo hostroot="${VHOST_ROOT:-@GENTOO_PORTAGE_EPREFIX@/var/www}")

    # --bug-report, --pretend, and -p can only be used as first arg
    if [[ ${COMP_CWORD} -gt 1 ]] ; then
        opts="${opts/--bug-report --pretend -p}"
    fi

    if [[ "${cur}" == -* ]] || [[ ${COMP_CWORD} -eq 1 ]] ; then
        COMPREPLY=($(compgen -W "${opts} ${actions}" -- ${cur}))
        return 0
    fi
    
    case "${prev}" in
        --bug-report|-p|--pretend)
        COMPREPLY=($(compgen -W "${opts} ${actions}" -- ${cur}))
        ;;

        -I|--install)
            _webapp_complete_appver all ${cur}
            ;;

        -U|--upgrade)
            _webapp_complete_appver installed ${cur}
            ;;

        # only complete on -d since it is required if -C is specified
        -C|--clean)
            COMPREPLY=($(compgen -W "-d" -- ${cur}))
            ;;

        --list-unused-installs)
            _webapp_complete_appver uninstalled ${cur}
            ;;
        
        --list-installs|--show-postinst)
            _webapp_complete_appver all ${cur}
            ;;
    
        #  hrm... anyone know a better way to reliably do this?
        -h|--host)
            local x
            COMPREPLY=($(compgen -W "$(\
                for x in ${hostroot}/* ; do \
                    [[ -d "${x}" ]] && echo "${x##*/}" ; \
                done)" -- ${cur}))
            ;;
        
        --virtual*)
            COMPREPLY=($(compgen -W "server-owned config-owned virtual" \
            -- ${cur}))
            ;;
        
        -d|--dir)
        local host x i=0
                # see if --host has been specified, and if so, get the value
                # that was passed to it.
        for x in ${COMP_WORDS[@]} ; do
            if [[ "${x}" == "-h" || "${x}" == "--host" ]] ; then
            host="${COMP_WORDS[((i+1))]}"
            break
            fi
            i=$((i+1))
        done

                # otherwise, use the default host
        if [[ "${host}" == "" ]] ; then
            eval $(. @GENTOO_PORTAGE_EPREFIX@/etc/vhosts/webapp-config ; \
            echo host="${VHOST_HOSTNAME:-localhost}")
        fi
        
            COMPREPLY=($(compgen -W "$(\
            for x in ${hostroot}${host}/* ; do \
            [[ -d "${x}" ]] && echo "${x}" ; \
            done)" -- ${cur}))
            ;;
        -u|--user)
            COMPREPLY=($(compgen -u -- ${cur}))
            ;;
        -g|--group)
            COMPREPLY=($(compgen -g -- ${cur}))
            ;;

        # we haven't recognized it yet, so more than likely ${prev}
        # is a 'app-name' ; assuming it is indeed a valid 'app-name'
        # (_webapp_complete_appver does the check), complete on available
        # 'app-version's
        *)
            _webapp_complete_appver ${prev} ${cur} || \
                    _webapp_complete_appver all ${cur}
            ;;
    esac
}
complete -F _webapp_config webapp-config
}

have revdep-rebuild && {
_revdep_rebuild() {
    local cur prev numwords opts
    local words i x
    local action actionpos
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    numwords=${#COMP_WORDS[*]}

    if [[ ${prev} == '>' || ${prev} == '<' ]] ; then
            COMPREPLY=($(compgen -f -- ${cur}))
            return 0
        fi  

    # find action
    for ((i = 0; i < ${numwords}; i++ )); do
        case ${COMP_WORDS[${i}]} in
            --library|-L)
                action=${COMP_WORDS[${i}]}
                actionpos=${i}
                ;;
            --help|-h)
                action=${COMP_WORDS[${i}]}
                actionpos=${i}
                ;;
        esac
    done

    if [[ ${cur} == -* ]]; then
        if [[ ${cur} == --* ]]; then
            opts="--exact --help --ignore --keep-temp --library --nocolor --no-ld-path --no-order --no-progress --no-util --pretend --quiet --verbose"
            COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
        else
            opts="-e -h -i -k -L -l -o -p -P -q -u -v"
            COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
        fi
        return 0
    fi  
    if [[ ${action} == '--library' ]] || [[ ${action} == '-L' ]] ; then
        if [[ "${cur}" == */* ]]; then
            COMPREPLY=( $(builtin cd @GENTOO_PORTAGE_EPREFIX@/lib; compgen -f -- "${cur}") )
        else
            COMPREPLY=( $(builtin cd @GENTOO_PORTAGE_EPREFIX@/lib; compgen -X '/' -f -- "${cur}") )
        fi
    fi
    return 0
}
complete -F _revdep_rebuild revdep-rebuild
}

have splat && {
_splat() {
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    opts="-h --help -v --verbose -s --summary -f --logfile -c --colored -l
    --list -u --count -p --package -t --sort -r --reverse"

    if [[ ${cur} == -* ]] ; then
        COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
        return 0
    fi

    case "${prev}" in
        -f|--logfile)
            COMPREPLY=($(compgen -f -- ${cur}))
            ;;
        *)
            _pkgname -A ${cur}
            COMPREPLY=($(compgen -W "${COMPREPLY[@]} ${opts}" -- ${cur}))
            ;;
    esac
}
complete -o filenames -F _splat splat
}

have euse && {
_euse() {
    local cur prev opts sopts use portdir
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    opts="-h --help -v --version -i --info -I --info-installed -a --active
        -E --enable -D --disable -P --prune"
    sopts="-g --global -l --local"

    if [[ ${cur} == -* ]] && [[ ${COMP_CWORD} -eq 1 ]] ; then
        COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
        return 0
    fi

    case "${prev}" in
        -h|--help|-v|--version)
            COMPREPLY=()
            ;;
        -a|--active)
            COMPREPLY=($(compgen -W "${sopts}" -- ${cur}))
            ;;
        -i|--info|-I|--info-installed|-E|--enable|-D|--disable|-P|--prune)
            portdir=$(_portdir)
        use="$(sed -n -e 's/^\([^ ]\+\) - .*$/\1/p' ${portdir}/profiles/use.desc) \
        $(sed -n -e 's/^[^ ]\+:\([^ ]*\) - .*$/\1/p' ${portdir}/profiles/use.local.desc)"
        COMPREPLY=($(compgen -W "${use} ${sopts}" -- ${cur}))
            ;;
        *)
            local l=0 g=0

            if [[ ${COMP_LINE} == *" "@(-l|--local)* ]] ; then
                l=1
            elif [[ ${COMP_LINE} == *" "@(-g|--global)* ]] ; then
                g=1
            fi

            if [[ ${COMP_LINE} == *" "@(-i|--info|-I|--info-installed|-E|--enable|-D|--disable|-P|--prune)* ]]
            then
                portdir=$(_portdir)

                if [[ ${l} -eq 1 ]] ; then
                    use=$(sed -n -e 's/^[^ ]\+:\([^ ]*\) - .*$/\1/p' ${portdir}/profiles/use.local.desc)
                elif [[ ${g} -eq 1 ]] ; then
                    use=$(sed -n -e 's/^\([^ ]\+\) - .*$/\1/p' ${portdir}/profiles/use.desc)
                fi

                COMPREPLY=($(compgen -W "${use}" -- ${cur}))
            fi
    esac
}
complete -F _euse euse
}

have glsa-check && {
_glsa_check() {
    local cur opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    opts="-l --list -d --dump --print -t --test -p --pretend -f --fix -i
    --inject -n --nocolor -e --emergelike -h --help -V --version -v --verbose
    -c --cve -m --mail"

    if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
        COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
        return 0
    fi

    # too slow otherwise
    if [[ ! -f ${ROOT}/tmp/gc.out ]] || \
        [[ $(stat ${ROOT}/tmp/gc.out | \
        sed -n -e 's/^Modify: \([[:digit:]]\+-[[:digit:]]\+-[[:digit:]]\+\).*$/\1/p') != "$(date +%F)" ]]
    then
        glsa-check -nl 2>/dev/null | \
            sed -n -e  's/^\([[:digit:]]\+-[[:digit:]]\+\) .*$/\1/p' > \
                ${ROOT}/tmp/gc.out
    fi

    COMPREPLY=($(compgen -W "${opts} $(< ${ROOT}/tmp/gc.out)" -- ${cur}))
}
complete -F _glsa_check glsa-check
}

have epm && {
_epm() {
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD]}"
    opts="-q --query -V -y --verify -e --erase --help"

    if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
        COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
        return 0
    fi

    case "${prev}" in
        --help)
            COMPREPLY=()
            ;;
        -q|--query)
            _pkgname -I ${cur}
            COMPREPLY=($(compgen -W "${COMPREPLY[@]} -l -f -G -a" -- ${cur}))
            ;;
        *)
            local x all=0 file=0
            for x in ${COMP_WORDS[@]} ; do
                [[ ${x} == -* ]] || continue
                [[ ${x} == *f* ]] && file=1
                [[ ${x} == *a* ]] && all=1
            done

            if [[ ${file} -eq 1 ]] ; then
                COMPREPLY=($(compgen -f -- ${cur}))
            elif [[ ${all} -eq 1 ]] ; then
                COMPREPLY=()
            else
                _pkgname -I ${cur}
            fi
            ;;
    esac
}
complete -o filenames -F _epm epm
}

#
# metagen completion
#

have metagen && {
_metagen() {
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    opts="-h --help -H -e -n -m -d -l -o -f -v -q -Q"

    if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
        COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
        return 0
    fi

    case "${prev}" in
        -H|-e|-n|-d|-l|-o)
            COMPREPLY=()
            ;;
        *)
            COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
            ;;
    esac
}
complete -F _metagen metagen
}

have rc-service && {
_rc_service() {
	local cur prev numwords opts
	local words i x filename
	local action actionpos
	COMPREPLY=()
	cur="${COMP_WORDS[COMP_CWORD]}"
	prev="${COMP_WORDS[COMP_CWORD-1]}"
	numwords=${#COMP_WORDS[*]}

	if [[ ${prev} == '>' || ${prev} == '<' ]] ; then
        	COMPREPLY=($(compgen -f -- ${cur}))
        	return 0
    	fi	

	# find action
	for x in ${COMP_LINE} ; do
		if [[ ${x} =~ --(list|exists|resolve) ]] || \
			[[ ${x} =~ -(l|e|r) ]]
		then
			action=${x}
			break
		fi
	done
	if [[ -n ${action} ]]; then
		for ((i = 0; i < ${numwords}; i++ )); do
			if [[ ${COMP_WORDS[${i}]} == "${action}" ]]; then
				actionpos=${i}
				break
			fi
		done
	
		for ((i = 1; i < ${numwords}; i++ )); do
			if [[ ! ${COMP_WORDS[$i]} == -* ]]; then
				break
			fi
		done
	fi

	if [[ ${COMP_CWORD} -eq 3 ]]; then
		return 1
	fi
	
	# check if an option was typed
	if [[ ${cur} == -* ]]; then
		if [[ ${cur} == --* ]]; then
			opts="--list --exists --resolve"
			COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
			return 0
		elif [[ ${cur} == -* ]]; then
			opts="-l -e -r"
			COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
			return 0
		fi

		
		# NOTE: This slows things down!
		# (Adapted from bash_completion by Ian Macdonald <ian@caliban.org>)
		# This removes any options from the list of completions that have
		# already been specified on the command line.
		COMPREPLY=($(echo "${COMP_WORDS[@]}" | \
		(while read -d ' ' i; do
			[[ -z ${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
	# if no option typed
	else
		if [[ ${COMP_CWORD} -eq 1 ]]; then				# if first word typed
			words="`rc-service -l | grep ^${cur}`"			# complete for init scripts
			COMPREPLY=($(for i in ${words} ; do \
			[[ ${i} == ${cur}* ]] && echo ${i} ; \
			done))
			return 0
		elif [[ ${COMP_CWORD} -eq 2 ]] && [[ ${prev} != -* ]]; then	# if second word typed and we didn't type in a function
			filename=`rc-service -r ${prev}`
			opts=`cat ${filename} | grep "^\w*()" | sed "s/().*$//"`	# Greps the functions included in the init script
			if [[ "x${opts}" == "x" ]] ; then 				# if no options found loosen the grep algorhythm
				opts=`cat ${filename} | grep "\w*()" | sed "s/().*$//"`
			fi
			COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
			return 0
		fi
	fi
   	if [[ ${action} == '--exists' ]] || [[ ${action} == '-e' ]] || \
	      [[ ${action} == '--resolve' ]]  || [[ ${action} == '-r' ]]; then
		words="`rc-service -l | grep ^${cur}`"
		COMPREPLY=($(for i in ${words} ; do \
			[[ ${i} == ${cur}* ]] && echo ${i} ; \
		done))
		return 0
	fi
	
return 0
}
complete -F _rc_service rc-service
}

# vim: set ft=sh tw=80 sw=4 et :
