click-contrib / click-completion

Add or enhance bash, fish, zsh and powershell completion in Click
MIT License
286 stars 33 forks source link

zsh: command not found: #compdef #24

Closed ssbarnea closed 3 years ago

ssbarnea commented 5 years ago

Apparently click-completion fails under zsh, as I tested with two different tools that use click-completion, molecule and pipenv, and I got similar errors.

pipenv

ssbarnea@imac: ~
$ _PIPENV_COMPLETE=source pipenv                                                                                                                                                                 #compdef pipenv
_pipenv() {
  eval $(env COMMANDLINE="${words[1,$CURRENT]}" _PIPENV_COMPLETE=complete-zsh  pipenv)
}
if [[ "$(basename -- ${(%):-%x})" != "_pipenv" ]]; then
  autoload -U compinit && compinit
  compdef _pipenv pipenv
fi

ssbarnea@imac: ~
$ $(_PIPENV_COMPLETE=source pipenv)                                                                                                                                                              zsh: command not found: #compdef
FAIL: 127

molecule

ssbarnea@imac: ~
$ _MOLECULE_COMPLETE=source molecule                                                                                                                                                             #compdef molecule
_molecule() {
  eval $(env COMMANDLINE="${words[1,$CURRENT]}" _MOLECULE_COMPLETE=complete-zsh  molecule)
}
if [[ "$(basename -- ${(%):-%x})" != "_molecule" ]]; then
  compdef _molecule molecule

zsh: command not found: ^[[0m#compdef

I can assure that compdef exists:

$ which compdef                                                                                                                                                                                  [10:16:59]
compdef () {
    local opt autol type func delete eval new i ret=0 cmd svc
    local -a match mbegin mend
    emulate -L zsh
    setopt extendedglob
    if (( ! $# ))
    then
        print -u2 "$0: I need arguments"
        return 1
    fi
    while getopts "anpPkKde" opt
    do
        case "$opt" in
            (a) autol=yes  ;;
            (n) new=yes  ;;
            ([pPkK]) if [[ -n "$type" ]]
                then
                    print -u2 "$0: type already set to $type"
                    return 1
                fi
                if [[ "$opt" = p ]]
                then
                    type=pattern
                elif [[ "$opt" = P ]]
                then
                    type=postpattern
                elif [[ "$opt" = K ]]
                then
                    type=widgetkey
                else
                    type=key
                fi ;;
            (d) delete=yes  ;;
            (e) eval=yes  ;;
        esac
    done
    shift OPTIND-1
    if (( ! $# ))
    then
        print -u2 "$0: I need arguments"
        return 1
    fi
    if [[ -z "$delete" ]]
    then
        if [[ -z "$eval" ]] && [[ "$1" = *\=* ]]
        then
            while (( $# ))
            do
                if [[ "$1" = *\=* ]]
                then
                    cmd="${1%%\=*}"
                    svc="${1#*\=}"
                    func="$_comps[${_services[(r)$svc]:-$svc}]"
                    [[ -n ${_services[$svc]} ]] && svc=${_services[$svc]}
                    [[ -z "$func" ]] && func="${${_patcomps[(K)$svc][1]}:-${_postpatcomps[(K)$svc][1]}}"
                    if [[ -n "$func" ]]
                    then
                        _comps[$cmd]="$func"
                        _services[$cmd]="$svc"
                    else
                        print -u2 "$0: unknown command or service: $svc"
                        ret=1
                    fi
                else
                    print -u2 "$0: invalid argument: $1"
                    ret=1
                fi
                shift
            done
            return ret
        fi
        func="$1"
        [[ -n "$autol" ]] && autoload -Uz "$func"
        shift
        case "$type" in
            (widgetkey) while [[ -n $1 ]]
                do
                    if [[ $# -lt 3 ]]
                    then
                        print -u2 "$0: compdef -K requires <widget> <comp-widget> <key>"
                        return 1
                    fi
                    [[ $1 = _* ]] || 1="_$1"
                    [[ $2 = .* ]] || 2=".$2"
                    [[ $2 = .menu-select ]] && zmodload -i zsh/complist
                    zle -C "$1" "$2" "$func"
                    if [[ -n $new ]]
                    then
                        bindkey "$3" | IFS=$' \t' read -A opt
                        [[ $opt[-1] = undefined-key ]] && bindkey "$3" "$1"
                    else
                        bindkey "$3" "$1"
                    fi
                    shift 3
                done ;;
            (key) if [[ $# -lt 2 ]]
                then
                    print -u2 "$0: missing keys"
                    return 1
                fi
                if [[ $1 = .* ]]
                then
                    [[ $1 = .menu-select ]] && zmodload -i zsh/complist
                    zle -C "$func" "$1" "$func"
                else
                    [[ $1 = menu-select ]] && zmodload -i zsh/complist
                    zle -C "$func" ".$1" "$func"
                fi
                shift
                for i
                do
                    if [[ -n $new ]]
                    then
                        bindkey "$i" | IFS=$' \t' read -A opt
                        [[ $opt[-1] = undefined-key ]] || continue
                    fi
                    bindkey "$i" "$func"
                done ;;
            (*) while (( $# ))
                do
                    if [[ "$1" = -N ]]
                    then
                        type=normal
                    elif [[ "$1" = -p ]]
                    then
                        type=pattern
                    elif [[ "$1" = -P ]]
                    then
                        type=postpattern
                    else
                        case "$type" in
                            (pattern) if [[ $1 = (#b)(*)=(*) ]]
                                then
                                    _patcomps[$match[1]]="=$match[2]=$func"
                                else
                                    _patcomps[$1]="$func"
                                fi ;;
                            (postpattern) if [[ $1 = (#b)(*)=(*) ]]
                                then
                                    _postpatcomps[$match[1]]="=$match[2]=$func"
                                else
                                    _postpatcomps[$1]="$func"
                                fi ;;
                            (*) if [[ "$1" = *\=* ]]
                                then
                                    cmd="${1%%\=*}"
                                    svc=yes
                                else
                                    cmd="$1"
                                    svc=
                                fi
                                if [[ -z "$new" || -z "${_comps[$1]}" ]]
                                then
                                    _comps[$cmd]="$func"
                                    [[ -n "$svc" ]] && _services[$cmd]="${1#*\=}"
                                fi ;;
                        esac
                    fi
                    shift
                done ;;
        esac
    else
        case "$type" in
            (pattern) unset "_patcomps[$^@]" ;;
            (postpattern) unset "_postpatcomps[$^@]" ;;
            (key) print -u2 "$0: cannot restore key bindings"
                return 1 ;;
            (*) unset "_comps[$^@]" ;;
        esac
    fi
}
marlonrichert commented 3 years ago
$ $(_PIPENV_COMPLETE=source pipenv)

You're doing it wrong. You're supposed to do this:

eval "$(_PIPENV_COMPLETE=source pipenv)"
ssbarnea commented 3 years ago

If I remember correctly click 8 added native support for completion and this plugin is no longer needed.