Repository: pallets/click

Issue:
zsh completion requires pressing tab twice
```
❯ black --<TAB>
# Nothing will happen
❯ black --<TAB>
unsorted
--code                        Format the code passed in as a string.
...
# work after second time
```

Expected:

```
❯ black --<TAB>
unsorted
--code                        Format the code passed in as a string.
...
# work after first time
```

<details><summary>Original investigation</summary>

```zsh
❯ _BLACK_COMPLETE=zsh_source black
#compdef black

_black_completion() {
    local -a completions
    local -a completions_with_descriptions
    local -a response
    (( ! $+commands[black] )) && return 1

    response=("${(@f)$(env COMP_WORDS="${words[*]}" COMP_CWORD=$((CURRENT-1)) _BLACK_COMPLETE=zsh_complete black)}")

    for type key descr in ${response}; do
        if [[ "$type" == "plain" ]]; then
            if [[ "$descr" == "_" ]]; then
                completions+=("$key")
            else
                completions_with_descriptions+=("$key":"$descr")
            fi
        elif [[ "$type" == "dir" ]]; then
            _path_files -/
        elif [[ "$type" == "file" ]]; then
            _path_files -f
        fi
    done

    if [ -n "$completions_with_descriptions" ]; then
        _describe -V unsorted completions_with_descriptions -U
    fi

    if [ -n "$completions" ]; then
        compadd -U -V unsorted -a completions
    fi
}

compdef _black_completion black;
```

that is equivalent to

```zsh
_black() {
  _black_completion() {
      local -a completions
      local -a completions_with_descriptions
      local -a response
      (( ! $+commands[black] )) && return 1

      response=("${(@f)$(env COMP_WORDS="${words[*]}" COMP_CWORD=$((CURRENT-1)) _BLACK_COMPLETE=zsh_complete black)}")

      for type key descr in ${response}; do
          if [[ "$type" == "plain" ]]; then
              if [[ "$descr" == "_" ]]; then
                  completions+=("$key")
              else
                  completions_with_descriptions+=("$key":"$descr")
              fi
          elif [[ "$type" == "dir" ]]; then
              _path_files -/
          elif [[ "$type" == "file" ]]; then
              _path_files -f
          fi
      done

      if [ -n "$completions_with_descriptions" ]; then
          _describe -V unsorted completions_with_descriptions -U
      fi

      if [ -n "$completions" ]; then
          compadd -U -V unsorted -a completions
      fi
  }

  compdef _black_completion black;
}
compdef _black black  # because first line comment
```

So, in the first time, `compdef _black black` tell zsh the completion function is `_black()`, but `_black()` not return any completion items, only define a new function named `_black_completion` and `compdef _black_completion black`. So when the second time, it work.

The fix method is remove the nested function definition:

```zsh
❯ _BLACK_COMPLETE=zsh_source black
#compdef black

local -a completions
local -a completions_with_descriptions
local -a response
(( ! $+commands[black] )) && return 1

response=("${(@f)$(env COMP_WORDS="${words[*]}" COMP_CWORD=$((CURRENT-1)) _BLACK_COMPLETE=zsh_complete black)}")

for type key descr in ${response}; do
    if [[ "$type" == "plain" ]]; then
        if [[ "$descr" == "_" ]]; then
            completions+=("$key")
        else
            completions_with_descriptions+=("$key":"$descr")
        fi
    elif [[ "$type" == "dir" ]]; then
        _path_files -/
    elif [[ "$type" == "file" ]]; then
        _path_files -f
    fi
done

if [ -n "$completions_with_descriptions" ]; then
    _describe -V unsorted completions_with_descriptions -U
fi

if [ -n "$completions" ]; then
    compadd -U -V unsorted -a completions
fi
```

</details>


Discussion:
There is an issue here, but the explanation either isn't correct or is very unclear.

Completion works correctly the first time when using the two methods shown in the documentation: `eval "$(_BLACK_COMPLETE=zsh_source black)"`, or `_BLACK_COMPLETE=zsh_source > ~/.black-complete.zsh` with `. ~/.black-complete.zsh` in `.zshrc`.

It doesn't work with placing the script on `fpath` like `... > ~/.zfunc/_black` for ZSH's autoload. https://unix.stackexchange.com/a/240192 shows that for autoload scripts, you do need to call the script as you do in your PR. But otherwise you need to register it with `compdef` as it's done now.

Resolving patch:
diff --git a/src/click/shell_completion.py b/src/click/shell_completion.py
--- a/src/click/shell_completion.py
+++ b/src/click/shell_completion.py
@@ -157,7 +157,13 @@ def __getattr__(self, name: str) -> t.Any:
     fi
 }
 
-compdef %(complete_func)s %(prog_name)s;
+if [[ $zsh_eval_context[-1] == loadautofunc ]]; then
+    # autoload from fpath, call function directly
+    %(complete_func)s "$@"
+else
+    # eval/source/. command, register function for later
+    compdef %(complete_func)s %(prog_name)s
+fi
 """
 
 _SOURCE_FISH = """\


Test patch: