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

        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|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|mdmg|mirror|\
                        mpkg|notes|outdated|patch|pkg|platform|portpkg|provides|quit|\
                        rpm|search|select|selfupdate|srpm|submit|sync|test|trace|unarchive|\
                        uninstall|unload|upgrade|url|usage|variants|version|work)
                        mode=$i
                        ;;
                esac
            elif [ -z "$port" ]; 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
            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)
                        # 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 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 mdmg mirror \
                                mpkg notes outdated patch pkg platform portpkg provides quit \
                                rpm search select selfupdate srpm submit sync test trace unarchive \
                                uninstall unload upgrade url usage variants version work' -- $cur ) )
        return 0
}
complete -F _port $filenames port
}
