# bash

have port && {
# helper functions for port completion
#

# port(1) completion
# 
_port()
{
        local cur prev mode count portdir cmdfile i port PSEUDOPORTS

        PSEUDOPORTS=( all current active inactive installed uninstalled
                      outdated obsolete requested unrequested leaves )

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

        count=0
        for i in ${COMP_WORDS[@]}; do
            [ $count -eq $COMP_CWORD ] && break
            # Last parameter was a required parameter, now go back to mode selection
            if [ "${COMP_WORDS[((count))]}" == "$portdir" -a "$mode" == "portdir" ] \
                    || [ "${COMP_WORDS[((count))]}" == "$cmdfile" -a "$mode" == "cmdfile" ]; then
                mode=""
            fi
            if [ -z "$mode" ]; then
                case $i in
                    -D)
                        mode=portdir
                        portdir=${COMP_WORDS[((count+1))]}
                        ;;
                    -F)
                        mode=cmdfile
                        cmdfile=${COMP_WORDS[((count+1))]}
                        ;;
                    activate|archive|archivefetch|build|cat|cd|checksum|clean|configure|\
                        contents|deactivate|dependents|deps|destroot|dir|distcheck|distfiles|\
                        dmg|dpkg|echo|ed|edit|exit|extract|fetch|file|gohome|help|\
                        info|install|installed|lint|list|livecheck|load|location|log|\
                        logfile|mdmg|mirror|mpkg|notes|outdated|patch|pkg|platform|\
                        portpkg|provides|quit|rdependents|rdeps|rev-upgrade|rpm|search|select|selfupdate|\
                        setrequested|space|srpm|submit|sync|test|unarchive|uninstall|\
                        unload|unsetrequested|upgrade|url|usage|variants|version|work)
                        mode=$i
                        ;;
                esac
            elif [ -z "$port" ]; then
                if [[ $i != -* ]]; then
                    case $mode in
                        contents|uninstall|upgrade)
                            if port -q installed -- "$i" | awk '{print $1}' | grep -qi '^'$i'$'; then
                                port=$i
                            fi
                            ;;
                        *)
                            if port -q search --name --exact -- "$i" | grep -qi '^'$i'$'; then
                                port=$i
                            fi
                            ;;
                    esac
                fi
            fi
            count=$((++count))
        done

        if [ -n "$port" ]; then
            # complete variants
            case $mode in
                contents|uninstall)
                    # installed variants
                    COMPREPLY=( $( port -q installed -- "$port" \
                        | awk '{print $2}' | tr '\n' ' ' 2>/dev/null ) )
                    COMPREPLY=( $( compgen -W '${COMPREPLY[@]}' -- $cur ) )
                    return 0
                    ;;
                activate)
                    # inactive variants
                    COMPREPLY=( $( port -q installed -- "$port" | grep -v '(active)' \
                        | awk '{print $2}' | tr '\n' ' ' 2>/dev/null ) )
                    COMPREPLY=( $( compgen -W '${COMPREPLY[@]}' -- $cur ) )
                    return 0
                    ;;
                deactivate)
                    # active variants
                    COMPREPLY=( $( port -q installed -- "$port" | grep '(active)' \
                        | awk '{print $2}' | tr '\n' ' ' 2>/dev/null ) )
                    COMPREPLY=( $( compgen -W '${COMPREPLY[@]}' -- $cur ) )
                    return 0
                    ;;
                *)
                    # all variants
                    COMPREPLY=( $( port -q info --line --variants -- "$port" | tr '\n,' '  ' ) )
                    COMPREPLY=( $( compgen -P'+' -W '${COMPREPLY[@]}' -- ${cur/+/} ) )
                    return 0
                    ;;
            esac

        fi

        if [ -n "$mode" ]; then
            if [[ $cur == -* ]]; then
                # complete options
                COMPREPLY=( $( port -q usage -- "$mode" 2>&1 | sed 's/Usage: $mode //' ) )
                COMPREPLY=( $( compgen -W '${COMPREPLY[@]}' -- $cur ) )
                return 0
            else
                # complete port names
                case $mode in
                    contents|installed|outdated|uninstall|upgrade)
                        # installed ports
                        COMPREPLY=( $( port -q installed -- "$cur*" \
                            | awk '{print $1}' | uniq ) \
                            $( compgen -W '${PSEUDOPORTS[@]}' -- $cur ) \
                        )
                        return 0
                        ;;
                    activate)
                        # inactive ports
                        COMPREPLY=( $( port -q installed -- "$cur*" | grep -v '(active)' \
                            | awk '{print $1}' | uniq ) \
                            $( compgen -W '${PSEUDOPORTS[@]}' -- $cur ) \
                        )
                        return 0
                        ;;
                    deactivate)
                        # active ports
                        COMPREPLY=( $( port -q installed -- "$cur*" | grep '(active)' \
                            | awk '{print $1}' | uniq ) \
                            $( compgen -W '${PSEUDOPORTS[@]}' -- $cur ) \
                        )
                        return 0
                        ;;
                    provides|cmdfile)
                        _filedir
                        return 0
                        ;;
                    portdir)
                        _filedir -d
                        return 0
                        ;;
                    selfupdate|search|sync|platform)
                        # no port
                        return 0
                        ;;
                    *)
                        # all ports
                        COMPREPLY=( $( port -q search --name --glob -- "$cur*" 2>/dev/null | uniq ) \
                            $( compgen -W '${PSEUDOPORTS[@]}' -- $cur ) \
                        )
                        return 0
                        ;;
                esac
            fi
        fi

        COMPREPLY=( $( compgen -W '-b -c -d -f -k -n -o -p -q -R -s -t -u -v -y \
                                activate archive archivefetch build cat cd checksum clean configure \
                                contents deactivate dependents deps destroot dir distcheck distfiles \
                                dmg dpkg echo ed edit exit extract fetch file gohome help \
                                info install installed lint list livecheck load location log \
                                logfile mdmg mirror mpkg notes outdated patch pkg platform \
                                portpkg provides quit rdependents rdeps rev-upgrade rpm search select selfupdate \
                                setrequested space srpm submit sync test unarchive uninstall \
                                unload unsetrequested upgrade url usage variants version work' -- $cur ) )
        return 0
}
complete -F _port $filenames port
}
