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
Original investigation
❯ _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
_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:
❯ _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