command-line-api icon indicating copy to clipboard operation
command-line-api copied to clipboard

zsh completion shim does not work as expected

Open Blackclaws opened this issue 3 years ago • 1 comments

As the title says the zsh completion shim doesn't work as expected or rather doesn't work at all in some cases.

The problem stems from the fact that dotnet-suggest on my system gives the following for dotnet-suggest list

dotnet-ef
dotnet ef
security-scan
dotnet-grpc-cli
dotnet grpc-cli
dotnet-suggest
dotnet suggest
dotnet-grpc
dotnet grpc
reportgenerator

So for all the dotnet prefixed global commands there is always the one with a space included as well. This leads to the situation where dotnet-suggest is registered as a completion provider for dotnet.

Resulting in this issue:

_values:compvalues:11: not enough arguments

Because there is no completion returned by dotnet-suggest for dotnet

If I understand the issue correctly this stems from this line: https://github.com/dotnet/command-line-api/blob/1d98a75ce2b109a2d7c18d81fac3f279be095e4e/src/System.CommandLine.Suggest/dotnet-suggest-shim.zsh#L32

In general if there is no completion returned there shouldn't even be a _values object that is set as far as I understand.

Blackclaws avatar Sep 13 '22 10:09 Blackclaws

I also have this issue, I thought it was "just me".

lonix1 avatar Sep 13 '22 10:09 lonix1

It can be slightly improved by enabling completion for the dotnet command separately as described in https://github.com/dotnet/docs/blob/main/docs/core/tools/enable-tab-autocomplete.md#zsh. It is based on dotnet complete command in contrast to dotnet suggest. Both configurations can be merged together and put in ~/.zshrc file.

# zsh parameter completion for the dotnet CLI
_dotnet_zsh_complete() 
{
  local completions=("$(dotnet complete "$words")")

  # If the completion list is empty, just continue with filename selection
  if [ -z "$completions" ]
  then
    _arguments '*::arguments: _normal'
    return
  fi

  # This is not a variable assignment, don't remove spaces!
  _values = "${(ps:\n:)completions}"
}

_dotnet_suggest_zsh_complete()
{
    # debug lines, uncomment to get state variables passed to this function
    # echo "\n\n\nstate:\t'$state'"
    # echo "line:\t'$line'"
    # echo "words:\t$words"

    # Get full path to script because dotnet-suggest needs it
    # NOTE: this requires a command registered with dotnet-suggest be
    # on the PATH
    full_path=`which ${words[1]}` # zsh arrays are 1-indexed
    # Get the full line
    # $words array when quoted like this gets expanded out into the full line
    full_line="$words"

    # Get the completion results, will be newline-delimited
    completions=$(dotnet suggest get --executable "$full_path" -- "$full_line")
    # explode the completions by linefeed instead of by spaces into the descriptions for the
    # _values helper function.

    # If the completion list is empty, just continue with filename selection
    if [ -z "$completions" ]
    then
      _arguments '*::arguments: _normal'
      return
    fi
    
    exploded=(${(f)completions})
    # for later - once we have descriptions from dotnet suggest, we can stitch them
    # together like so:
    # described=()
    # for i in {1..$#exploded}; do
    #     argument="${exploded[$i]}"
    #     description="hello description $i"
    #     entry=($argument"["$description"]")
    #     described+=("$entry")
    # done
    _values 'suggestions' $exploded
}

compdef _dotnet_suggest_zsh_complete $(dotnet-suggest list)
compdef _dotnet_zsh_complete dotnet

export DOTNET_SUGGEST_SCRIPT_VERSION="1.0.0"

_dotnet_suggest_zsh_complete() is just renamed _dotnet_zsh_complete() function from: https://github.com/dotnet/command-line-api/blob/3e0d47c1f468ad7047302d00d56c916bf303f636/src/System.CommandLine.Suggest/dotnet-suggest-shim.zsh#L2

The order of compdef calls is important:

compdef _dotnet_suggest_zsh_complete $(dotnet-suggest list)
compdef _dotnet_zsh_complete dotnet

It should allow to get rid off errors:

_values:compvalues:11: not enough arguments

but to get meaningful completion for dotnet prefixed commands it is necessary to use commands with hyphen, e.g. dotnet-ef instead of dotnet ef, because dotnet ef is overtook by dotnet complete based completion.

mars-low avatar Mar 08 '23 23:03 mars-low

but to get meaningful completion for dotnet prefixed commands it is necessary to use commands with hyphen, e.g. dotnet-ef instead of dotnet ef, because dotnet ef is overtook by dotnet complete based completion.

This is a long-standing issue: #343.

jonsequitur avatar Mar 10 '23 04:03 jonsequitur