# bash command-line completion for virtualbox
#
# This version of bash completion was born due to the need of fast and easy
# access to the maze of commands and parameters VBoxManage provides. Based on
# Sebastian[1] script I've managed to improve it and adapt to newest stable
# version available in Gentoo Portage.
#
# [1] Sebastian T. Hafner <sonix@own-hero.net>
#
#
# [x] adoptstate
# [x] bandwidthctl
# [x] clonehd
# [x] clonevm
# [x] closemedium
# [x] controlvm
# [x] convertfromraw
# [ ] createhd
# [ ] createvm
# [ ] debugvm
# [ ] dhcpserver
# [ ] discardstate
# [ ] export
# [ ] extpack
# [ ] getextradata
# [ ] guestcontrol
# [ ] guestproperty
# [ ] hostonlyif
# [ ] import
# [x] list
# [ ] metrics
# [ ] modifyhd
# [ ] modifyvm  - a LOT options missing
# [ ] natnetwork
# [ ] registervm
# [ ] setextradata
# [ ] setproperty
# [ ] sharedfolder
# [x] showhdinfo
# [x] showvminfo
# [x] snapshot
# [x] startvm
# [x] storageattach
# [x] storagectl
# [x] unregistervm
# [x] usbfilter

_VBoxManage() {
    local cur prev opts cmd subcommand tmp items name index result

    # Generate registered hard disk files.
    # NOTE: This function may introduce some quirks, if there is a space or
    # other characters which usually are treated as IFS - like space. Pipe
    # character used in disk filename will ruin this completions.
    _hdd_comp() {
        local cur=$1
        local hdds
        local item

        hdds=$(VBoxManage list hdds | \
            grep -A 1 'normal (base)' | \
            grep "Location:" | \
            sed 's/Location:\s\+//' | \
            sed 's/\s/\\ /g' | \
            tr '\n' '|' | \
            sed 's/|$//')
        IFS='|' read -ra hdds <<< "$hdds"

        for item in "${hdds[@]}"
        do
            [[ ${item^^} == ${cur^^}* ]] && COMPREPLY+=("$item")
        done
    }

    _floppy_comp() {
        local cur=$1
        local floppies
        local item

        floppies=$(VBoxManage list floppies | \
            grep "Location:" | \
            sed 's/Location:\s\+//' | \
            sed 's/\s/\\ /g' | \
            tr '\n' '|' | \
            sed 's/|$//')
        IFS='|' read -ra floppies <<< "$floppies"

        for item in "${floppies[@]}"
        do
            [[ ${item^^} == ${cur^^}* ]] && COMPREPLY+=("$item")
        done
    }

    _dvds_comp() {
        local cur=$1
        local dvds
        local item

        dvds=$(VBoxManage list dvds | \
            grep "Location:" | \
            sed 's/Location:\s\+//' | \
            sed 's/\s/\\ /g' | \
            tr '\n' '|' | \
            sed 's/|$//')
        IFS='|' read -ra dvds <<< "$dvds"

        for item in "${dvds[@]}"
        do
            [[ ${item^^} == ${cur^^}* ]] && COMPREPLY+=("$item")
        done
    }

    # Complete registered VM names.
    # Issues are the same as in above function.
    _vms_comp() {
        local command=$1
        local cur=$2
        local vms
        local item

        compopt -o filenames
        vms=$(VBoxManage list $command | \
            awk -F ' {' '{ print $1 }' | \
            tr '\n' '|' | \
            sed 's/|$//' | \
            sed 's/"//g')
        IFS='|' read -ra vms <<< "$vms"
        for item in "${vms[@]}"
        do
            [[ ${item^^} == ${cur^^}* ]] && COMPREPLY+=("$item")
        done
    }

    _list_comp() {
        local cur=$1
        local list

        list=$(VBoxManage list | \
            grep '|' | \
            sed 's/\[.*\]//g'| \
            sed 's/VBoxManage list//' | \
            tr "\\n" " " | \
            sed 's/$/\n/' | \
            sed 's/\s\+//g' | \
            sed 's/|/ /g')
        COMPREPLY=( $(compgen -W "$list" -- ${cur}) )
    }
    _group_comp() {
        local cur=$1
        local list
        local item

        list=$(VBoxManage list groups | \
            tr '\n' '|' | \
            sed 's/|$//' | \
            sed 's/\s/\\ /g'| \
            sed 's/"//g')
        IFS='|' read -ra list <<< "$list"

        for item in "${list[@]}"
        do
            [[ ${item^^} == ${cur^^}* ]] && COMPREPLY+=("$item")
        done
    }

    # Check the COMP_WORDS looking for name of the vm. If name contain space or
    # is enclosed in quotes, glue name together in variable name. Variable index
    # will hold the last index of COMP_WORDS array which contain the end of the
    # name.
    _find_item_name() {
        local idx=$1
        name=""

        while true
        do
            name="${NAME}${COMP_WORDS[$idx]}"
            [[ ${COMP_WORDS[$idx]} = *'"' ]] && break

            if [[ ${COMP_WORDS[$idx]} = '"'* || ${COMP_WORDS[$idx]} = *'\ ' ]]
            then
                idx=$((++idx))
                continue
            fi
            break
        done
        index=$idx
    }

    _get_excluded_items() {
        local i

        result=""
        for i in $@; do
            [[ " ${COMP_WORDS[@]} " == *" $i "* ]] && continue
            result="$result $i"
        done
    }

    _bandwidthctl_comp() {
        local rules cur=$1
        local item

        _find_item_name 2
        rules=$(VBoxManage bandwidthctl "${name//\\/}" \
            list --machinereadable | \
            awk -F ',' '{print $1}' | \
            awk -F '=' '{print $2}' | \
            tr '\n' '|' | \
            sed 's/|$//' | \
            sed 's/\s/\\ /g')
        IFS='|' read -ra rules <<< "$rules"

        for item in "${rules[@]}"
        do
            [[ ${item^^} == ${cur^^}* ]] && COMPREPLY+=("$item")
        done
    }

    _snapshot_comp() {
        local snap cur=$1
        local item

        _find_item_name 2
        snap=$(VBoxManage snapshot "${name//\\/}" \
            list | \
            grep UUID |
            awk -F ': ' '{print $2}' | \
            sed 's/ (.*//' | \
            tr '\n' '|' | \
            sed 's/|$//' | \
            sed 's/\s/\\ /g')
        IFS='|' read -ra snap <<< "$snap"

        for item in "${snap[@]}"
        do
            [[ ${item^^} == ${cur^^}* ]] && COMPREPLY+=("$item")
        done
    }

    _webcam_comp() {
        local devs cur=$1
        local item

        _find_item_name 2
        devs=$(VBoxManage controlvm "${name//\\/}" \
            webcam list | \
            tr '\n' ' ' | \
            sed 's/|s$//')
        read -ra devs <<< "$devs"

        for item in "${devs[@]}"
        do
            [[ ${item^^} == ${cur^^}* ]] && COMPREPLY+=("$item")
        done
    }

    _webcam_avail_comp() {
        local devs cur=$1
        local item

        _find_item_name 2
        devs=$(VBoxManage list webcams | \
            grep dev | \
            tr '\n' ' ' | \
            sed 's/|s$//')
        read -ra devs <<< "$devs"

        for item in "${devs[@]}"
        do
            [[ ${item^^} == ${cur^^}* ]] && COMPREPLY+=("$item")
        done
    }

    _list_comp() {
        local list
        list=$(VBoxManage list | \
            grep '|' | \
            sed 's/\[.*\]//g'| \
            sed 's/VBoxManage list//' | \
            tr "\\n" " " | \
            sed 's/$/\n/' | \
            sed 's/\s\+//g' | \
            sed 's/|/ /g')
        COMPREPLY=( $(compgen -W "$list" -- ${cur}) )
    }

    COMP_WORDBREAKS=${COMP_WORDBREAKS//|/}  # remove pipe from comp word breaks
    COMPREPLY=()

    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    lastbutone="${COMP_WORDS[COMP_CWORD-2]}"
    if [[ COMP_CWORD -ge 2 ]]; then
        cmd="${COMP_WORDS[1]}"
        if [[ $cmd == "-q" ]]; then
                cmd="${COMP_WORDS[2]}"
        fi
    fi

    # all possible commands for the VBoxManage
    opts=$(VBoxManage -q help | \
        egrep -o "^\s\s[a-z]+ " | \
        grep -v VBoxManage | \
        awk '{print $1}'| \
        sort | \
        uniq)

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

    case "${cmd}" in
        adoptstate)
            _vms_comp vms ${cur}
            ;;
        bandwidthctl)
            local items=(add set remove list)
            if [[ ${prev} == ${cmd} ]]; then
                _vms_comp vms ${cur}
            else
                _find_item_name 2
                subcommand=${COMP_WORDS[$((index+1))]}
                if [[ " ${items[@]} " == *" $subcommand "* ]]; then
                    case "${subcommand}" in
                        add)
                            items=(--type --limit)
                            _get_excluded_items "${items[@]}"
                            COMPREPLY=( $(compgen -W "$result" -- ${cur}) )
                            ;;
                        set)
                            if [[ ${prev} == "set" ]]; then
                                _bandwidthctl_comp ${cur}
                            else
                                [[ " ${COMP_WORDS[@]} " != *" --limit "* ]] && \
                                    COMPREPLY=( $(compgen -W "--limit" -- \
                                    ${cur}) )
                            fi
                            ;;
                        remove)
                            if [[ ${prev} == "remove" ]]; then
                                _bandwidthctl_comp ${cur}
                            fi
                            ;;
                        list)
                            if [[ ${prev} == "list" ]]; then
                                COMPREPLY=( $(compgen -W "--machinereadable" \
                                    -- ${cur}) )
                            fi
                            ;;
                    esac
                    case "${prev}" in
                        --type)
                            COMPREPLY=( $(compgen -W "disk network" -- ${cur}) )
                            ;;
                    esac
                else
                    [[ ${#COMPREPLY[@]} -eq 0 ]] && \
                        COMPREPLY=( $(compgen -W "${items[*]}" -- ${cur}) )
                fi
            fi
            ;;
        clonehd)
            if [[ ${prev} == ${cmd} ]]; then
                _hdd_comp ${cur}
            else
                _find_item_name 2
                items=(--format --variant --existing)
                _get_excluded_items "${items[@]}"
                COMPREPLY=( $(compgen -W "$result" -- ${cur}) )

                case "${prev}" in
                    --format)
                        COMPREPLY=( $(compgen -W "VDI VMDK VHD RAW" -- ${cur}) )
                        ;;
                    --variant)
                        COMPREPLY=( $(compgen -W "Standard Fixed Split2G Stream
                        ESX" -- ${cur}) )
                        ;;
                esac
            fi
            ;;
        clonevm)
            if [[ ${prev} == ${cmd} ]]; then
                _vms_comp vms ${cur}
            else
                _find_item_name 2
                items=(--snapshot --mode --options --name --groups --basefolder
                --uuid --register)
                _get_excluded_items "${items[@]}"
                COMPREPLY=( $(compgen -W "$result" -- ${cur}) )
                case "${prev}" in
                    --snapshot)
                        COMPREPLY=()
                        _snapshot_comp ${cur}
                        ;;
                    --mode)
                        COMPREPLY=( $(compgen -W "machine machineandchildren
                        all" -- ${cur}) )
                        ;;
                    --options)
                        COMPREPLY=( $(compgen -W "link keepallmacs keepnatmacs
                        keepdisknames" -- ${cur}) )
                        ;;
                    --groups)
                        COMPREPLY=()
                        _group_comp ${cur}
                        ;;
                    --basefolder)
                        COMPREPLY=( $(compgen -o dirnames -- ${cur}) )
                        ;;
                esac
            fi
            ;;
        closemedium)
            if [[ ${prev} == ${cmd} ]]; then
                COMPREPLY=( $(compgen -W "disk dvd floppy" -- ${cur}) )
            else
                case "${prev}" in
                    disk)
                        _hdd_comp ${cur}
                        ;;
                    dvd)
                        _dvds_comp ${cur}
                        ;;
                    floppy)
                        _floppy_comp ${cur}
                        ;;
                    *)
                        items=(--delete)
                        _get_excluded_items "${items[@]}"
                        COMPREPLY=( $(compgen -W "$result" -- ${cur}) )
                        ;;
                esac
            fi
            ;;
        controlvm)
            if [[ ${prev} == ${cmd} ]]; then
                _vms_comp runningvms ${cur}
            else
                local items=(acpipowerbutton acpisleepbutton clipboard
                cpuexecutioncap draganddrop guestmemoryballoon
                keyboardputscancode natpf1 nic1 nicpromisc1 nicproperty1
                nictrace1 nictracefile1 natpf2 nic2 nicpromisc2 nicproperty2
                nictrace2 nictracefile2 natpf3 nic3 nicpromisc3 nicproperty3
                nictrace3 nictracefile3 natpf4 nic4 nicpromisc4 nicproperty4
                nictrace4 nictracefile4 natpf5 nic5 nicpromisc5 nicproperty5
                nictrace5 nictracefile5 natpf6 nic6 nicpromisc6 nicproperty6
                nictrace6 nictracefile6 natpf7 nic7 nicpromisc7 nicproperty7
                nictrace7 nictracefile7 natpf8 nic8 nicpromisc8 nicproperty8
                nictrace8 pause plugcpu poweroff reset resume savestate
                screenshotpng setcredentials setlinkstate1 setlinkstate2
                setlinkstate3 setlinkstate4 setlinkstate5 setlinkstate6
                setlinkstate7 setlinkstate8 setvideomodehint teleport unplugcpu
                usbattach usbdetach vcpenabled vcpscreens vrde vrdeport
                vrdeproperty vrdevideochannelquality webcam)

                _find_item_name 2
                subcommand=${COMP_WORDS[$((index+1))]}

                if [[ " ${items[@]} " == *" $subcommand "* ]]; then
                    case "${subcommand}" in
                        nictracefile[1-8])
                            [[ ${prev} == "nictracefile"* ]] && \
                                COMPREPLY=( $(compgen -f -- ${cur}) )
                            ;;
                        nictrace[1-8])
                            [[ ${prev} == "nictrace"* ]] && \
                                COMPREPLY=( $(compgen -W "on off" -- ${cur}) )
                            ;;
                        nicpromisc[1-8])
                            [[ ${prev} == "nicpromisc"* ]] && \
                                COMPREPLY=( $(compgen -W "deny allow-vms
                                allow-all" -- ${cur}) )
                            ;;
                        nic[1-8])
                            [[ ${prev} == "nic"* ]] && \
                                COMPREPLY=( $(compgen -W "null nat bridged intnet
                                hostonly generic natnetwork" -- ${cur}) )
                            ;;
                        natpf[1-8])
                            [[ ${prev} == "natpf"* ]] && \
                                COMPREPLY=( $(compgen -W "delete tcp
                                udp" -- ${cur}) )
                            ;;
                        setlinkstate[1-8])
                            [[ ${prev} == "setlinkstate"* ]] && \
                                COMPREPLY=( $(compgen -W "on off" -- ${cur}) )
                            ;;
                        clipboard)
                            [[ ${prev} == "clipboard" ]] && \
                                COMPREPLY=( $(compgen -W "disabled hosttoguest
                                guesttohost bidirectional" -- ${cur}) )
                            ;;
                        draganddrop)
                            [[ ${prev} == "draganddrop" ]] && \
                                COMPREPLY=( $(compgen -W "disabled
                                hosttoguest" -- ${cur}) )
                            ;;
                        vrde|vcpenabled)
                            [[ ${prev} == "vrde" ||
                            ${prev} == "vcpenabled" ]] && \
                                COMPREPLY=( $(compgen -W "on off" -- ${cur}) )
                            ;;
                        vcpscreens)
                            [[ ${prev} == "vcpscreens" ]] && \
                                COMPREPLY=( $(compgen -W "all none" -- ${cur}) )
                            ;;
                        setcredentials)
                            tmp=(--passwordfile --allowlocallogon)
                            _get_excluded_items "${tmp[@]}"
                            COMPREPLY=( $(compgen -W "$result" -- ${cur}) )
                            ;;
                        teleport)
                            tmp=(--host --port --maxdowntime --passwordfile
                            --password)
                            _get_excluded_items "${tmp[@]}"
                            COMPREPLY=( $(compgen -W "$result" -- ${cur}) )
                            ;;
                        webcam)
                            [[ ${prev} == "webcam" ]] && \
                                COMPREPLY=( $(compgen -W "attach detach
                                list" -- ${cur}) )
                            [[ ${prev} == "detach" ]] && \
                                _webcam_comp ${cur}
                            [[ ${prev} == "attach" ]] && \
                                _webcam_avail_comp ${cur}
                            ;;
                    esac
                else
                    [[ ${#COMPREPLY[@]} -eq 0 ]] && \
                            COMPREPLY=( $(compgen -W "${items[*]}" -- ${cur}) )
                fi
            fi
            ;;
        convertfromraw)
            local items=(--format --variant --uuid)

            if [[ ${prev} == ${cmd} ]]; then
                COMPREPLY=( $(compgen -W "${items[*]}" -- ${cur}) )
            else
                _get_excluded_items "${items[@]}"
                COMPREPLY=( $(compgen -W "$result" -- ${cur}) )
                case "${prev}" in
                    --format)
                        COMPREPLY=( $(compgen -W "VDI VMDK VHD" -- ${cur}) )
                        ;;
                    --variant)
                        COMPREPLY=( $(compgen -W "Standard Fixed Split2G Stream
                        ESX" -- ${cur}) )
                        ;;
                esac
            fi
            ;;
        createhd)
            ;;
        createvm)
            ;;
        debugvm)
            ;;
        dhcpserver)
            ;;
        discardstate)
            ;;
        "export")
            ;;
        extpack)
            ;;
        getextradata)
            ;;
        guestcontrol)
            ;;
        guestproperty)
            ;;
        hostonlyif)
            ;;
        import)
            ;;
        list)
            if [[ ${prev} == ${cmd} ]]; then
                _list_comp ${cur}
            else
                case "${prev}" in
                    --long|-l)
                        COMPREPLY=()
                        ;;
                    *)
                        COMPREPLY=( $(compgen -W "-l --long" -- ${cur}) )
                        ;;
                esac
            fi
            ;;
        metrics)
            ;;
        modifyhd)
            ;;
        modifyvm)
            ;;
        natnetwork)
            ;;
        registervm)
            ;;
        setextradata)
            ;;
        setproperty)
            ;;
        sharedfolder)
            ;;
        showhdinfo)
            _hdd_comp ${cur}
            ;;
        showvminfo)
            if [[ ${prev} == ${cmd} ]]; then
                _vms_comp vms ${cur}
            else
                if [[ " ${COMP_WORDS[@]} " == *" --log "* ]]; then
                    COMPREPLY=()
                elif [[ " ${COMP_WORDS[@]} " == *" --details "* ||
                    " ${COMP_WORDS[@]} " == *" --machinereadable "*  ]]; then
                    local items=(--details --machinereadable)
                    _get_excluded_items "${items[@]}"
                    COMPREPLY=( $(compgen -W "$result" -- ${cur}) )
                else
                    local items=(--details --machinereadable --log)
                    _get_excluded_items "${items[@]}"
                    COMPREPLY=( $(compgen -W "$result" -- ${cur}) )
                fi
            fi
            ;;
        snapshot)
            items=(take delete restore restorecurrent edit list showvminfo)
            if [[ ${prev} == ${cmd} ]]; then
                _vms_comp vms ${cur}
            else
                _find_item_name 2
                subcommand=${COMP_WORDS[$((index+1))]}
                if [[ " ${items[@]} " == *" $subcommand "* ]]; then
                    case "${subcommand}" in
                        take)
                            items=(--description --live)
                            _get_excluded_items "${items[@]}"
                            COMPREPLY=( $(compgen -W "$result" -- ${cur}) )
                            ;;
                        delete|restore|showvminfo)
                            _snapshot_comp ${cur}
                            ;;
                        restorecurrent)
                            COMPREPLY=()
                            ;;
                        edit)
                            if [[ ${prev} == "edit" &&
                                ${#COMP_WORDS[@]} == 5 ]]; then
                                _snapshot_comp ${cur}
                                COMPREPLY+=("--current")
                            else
                                items=(--name --description)
                                _get_excluded_items "${items[@]}"
                                COMPREPLY=( $(compgen -W "$result" -- ${cur}) )
                            fi
                            ;;
                        list)
                            items=(--details --machinereadable)
                            _get_excluded_items "${items[@]}"
                            COMPREPLY=( $(compgen -W "$result" -- ${cur}) )
                            ;;
                    esac
                else
                    [[ ${#COMPREPLY[@]} -eq 0 ]] && \
                        COMPREPLY=( $(compgen -W "${items[*]}" -- ${cur}) )
                fi
            fi
            ;;
        startvm)
            if [[ ${prev} == ${cmd} ]]; then
                _vms_comp vms ${cur}
            elif [[ "${prev}" == "--type" ]]; then
                COMPREPLY=( $(compgen -W "gui sdl headless" -- ${cur}) )
            else
                local items=(--type)
                _get_excluded_items "${items[@]}"
                COMPREPLY=( $(compgen -W "$result" -- ${cur}) )
            fi
            ;;
        storageattach)
            if [[ ${prev} == ${cmd} ]]; then
                _vms_comp vms ${cur}
            else
                _find_item_name 2
                local items=(--storagectl --port --device --type --medium --mtype
                --comment --setuuid --setparentuuid --passthrough --tempeject
                --nonrotational --discard --bandwidthgroup --forceunmount
                --server --target --tport --lun --encodedlun --username
                --password --initiator --intnet)
                _get_excluded_items "${items[@]}"
                COMPREPLY=( $(compgen -W "$result" -- ${cur}) )

                case "${prev}" in
                    --type)
                        COMPREPLY=( $(compgen -W "dvddrive hdd fdd" -- ${cur}) )
                        ;;
                    --medium)
                        COMPREPLY=()
                        local tmp=(none emptydrive additions)
                        _hdd_comp ${cur}
                        _floppy_comp ${cur}
                        _dvds_comp ${cur}
                        for item in "${tmp[@]}"
                        do
                            [[ ${item^^} == ${cur^^}* ]] && COMPREPLY+=("$item")
                        done
                        ;;
                    --mtype)
                        COMPREPLY=( $(compgen -W "normal writethrough immutable
                        shareable readonly multiattach" -- ${cur}) )
                        ;;
                    --passthrough|--tempeject|--nonrotational|--discard)
                        COMPREPLY=( $(compgen -W "on off" -- ${cur}) )
                        ;;
                esac
            fi
            ;;
        storagectl)
            local items=(--name --add --controller --portcount --hostiocache
            --bootable --remove)
            if [[ ${prev} == ${cmd} ]]; then
                _vms_comp vms ${cur}
            else
                _get_excluded_items "${items[@]}"
                COMPREPLY=( $(compgen -W "$result" -- ${cur}) )
                case "${prev}" in
                    --add)
                        COMPREPLY=( $(compgen -W "ide sata scsi floppy
                        sas" -- ${cur}) )
                        ;;
                    --controller)
                        COMPREPLY=( $(compgen -W "LSILogic LSILogicSAS BusLogic
                        IntelAHCI PIIX3 PIIX4 ICH6 I82078" -- ${cur}) )
                        ;;
                    --bootable|--hostiocache)
                        COMPREPLY=( $(compgen -W "on off" -- ${cur}) )
                        ;;
                esac
            fi
            ;;
        unregistervm)
            if [[ ${prev} == ${cmd} ]]; then
                _vms_comp vms ${cur}
            else
                local items=(--delete)
                _get_excluded_items "${items[@]}"
                COMPREPLY=( $(compgen -W "$result" -- ${cur}) )
            fi
            ;;
        usbfilter)
            if [[ COMP_CWORD -ge 3 ]]; then
                subcommand="${COMP_WORDS[2]}"
                if [[ $subcommand == "${cmd}" ]]; then
                    subcommand="${COMP_WORDS[3]}"
                fi
            fi

            if [[ ${prev} == ${cmd} ]]; then
                COMPREPLY=( $(compgen -W "add modify remove" -- ${cur}) )
            else
                case "${prev}" in
                    --target)
                        _vms_comp vms ${cur}
                        COMPREPLY+=( $(compgen -W "global" -- ${cur}) )
                        ;;
                    --action)
                        COMPREPLY=( $(compgen -W "ignore hold" -- ${cur}) )
                        ;;
                    --active|--remote)
                        COMPREPLY=( $(compgen -W "yes no" -- ${cur}) )
                        ;;
                esac
                if [[ ${#COMPREPLY[@]} -eq 0 ]]; then
                    case "${subcommand}" in
                        add|modify)
                            local items=(--target --name --action --active
                            --vendorid --productid --revision --manufacturer
                            --product --remote --serialnumber --maskedinterfaces)
                            _get_excluded_items "${items[@]}"
                            COMPREPLY=( $(compgen -W "$result" -- ${cur}) )
                            ;;
                        remove)
                            local items=(--target)
                            _get_excluded_items "${items[@]}"
                            COMPREPLY=( $(compgen -W "$result" -- ${cur}) )
                            ;;
                    esac
                fi
            fi
            ;;
    esac
}
complete -o default -F _VBoxManage VBoxManage

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