dotnet / sdk

Core functionality needed to create .NET Core projects, that is shared between Visual Studio and CLI
https://dot.net/core
MIT License
2.64k stars 1.05k forks source link

ZSH completion breaks path completion #9782

Open matkoch opened 5 years ago

matkoch commented 5 years ago

https://github.com/dotnet/cli/blob/7af1d28dd72fb933966e6201414dc8df6753fcd3/scripts/register-completions.zsh#L10

If I'm not missing something, this indeed helps to autocomplete commands for dotnet, but equally it will break normal path completion.

matkoch commented 5 years ago

@peterhuene Not sure how this is a good first issue. What would you consider a good solution for that? I honestly have no idea.

peterhuene commented 5 years ago

@matkoch That was done in error. As this doesn't have to do with the CLI and has everything to do with ZSH scripting, I'll remove the label.

KathleenDollard commented 3 years ago

@jonsequitur Would you mind looking at this script. It came up today on Twitter as well, so it is not a silent issue.

matkoch commented 3 years ago

Afaik, this affects all of the shell-completion registries.

JohnnyWombwell commented 3 years ago

You can tell zsh to fallback to file path completion (when dotnet complete returns no suggestions) by changing

compctl -K _dotnet_zsh_complete dotnet

to

compctl -K _dotnet_zsh_complete + -f dotnet

This gets auto completion working pretty close to how you'd expect. There is a slight niggle in that when tabbing after entering a command where you'd often enter a path, e.g. dotnet add reference, showing options takes precedent over the path. It's easily worked around by entering the first char of the path (or ./ say).

matkoch commented 3 years ago

@JohnnyWombwell you make me the happiest developer in the world right now 🥳 🎈

JohnnyWombwell commented 3 years ago

Happy to help :)

This is probably overkill but the 'tabbing options over file path' thing was irritating me so this improves the experience imo:

_dotnet_zsh_complete()
{
  local completions=("$(dotnet complete "$words")")
  local completions_array=( "${(ps:\n:)completions}" )
  local narg pref
  read -nc narg
  read -Ac pref

  # To mimic the convention of 'tabbing' empty space
  # preferring file completions over command options (see ls etc),
  # this will ignore completions if the cursor is in empty space
  # and *all* completions are options (i.e. there are no command
  # completions).
  # Due to the empty result, the shell should then fallback to
  # file completions.
  if [[ ! "${pref[narg]}" = *[^[:space:]]* ]]; then
    local all_completions_are_options=true
    for completion in "${completions_array[@]}"
    do
      if [[ ${completion:0:1} != "-" ]] then
        all_completions_are_options=false
        break
      fi
    done
    if [[ "$all_completions_are_options" = true ]] then
      reply=()
      return
    fi
  fi

  reply=( $completions_array )
}