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.66k stars 1.06k forks source link

Provide relevant suggestions when dotnet command is not found #23807

Open danmoseley opened 2 years ago

danmoseley commented 2 years ago

If I make a typo in my dotnet command, it tells me this:

C:\git\performance>dotnet buildserver
Could not execute because the specified command or file was not found.
Possible reasons for this include:
  * You misspelled a built-in dotnet command.
  * You intended to execute a .NET program, but dotnet-buildserver does not exist.
  * You intended to run a global tool, but a dotnet-prefixed executable with this name could not be found on the PATH.

But dotnet knows that there is a very similar valid option, "build-server".

git, however, is more useful:

C:\git\performance>git cherrypick abc123
git: 'cherrypick' is not a git command. See 'git --help'.

The most similar command is
        cherry-pick

Benchmark.NET does this also, eg

[2022/02/07 18:13:46][INFO] You must have made a typo in '*ByteMark.BenchFurier*'. Suggestions:
[2022/02/07 18:13:46][INFO]     ByteMark.BenchFourier
[2022/02/07 18:13:46][INFO] To print all available benchmarks use `--list flat` or `--list tree`.

They both do this by the well established procedure of selecting the alternatives that have the lowest Levenshtein distance from the invalid input. This can be done whenever the valid inputs are known strings. The typo does not need to be a missing or extra character, it can be a transposition or substitution - Levenshtein distance just ranks by the smallest number of insertions, deletions, or edits between the valid and the invalid strings. Typically, this handles everyday typos effectively.

Benchmark.NET has the MIT license and with attribution dotnet can reuse its code from here When a command or parameter or any other input is not one of a valid list, the CLI simply feeds it, and the valid options, to this Levenshtein calculator and it will return the most likely intended possibilities to display to the user.

danmoseley commented 2 years ago

If this sounds like a good idea to the maintainers, perhaps it's a candidate for 'up for grabs'?

baronfel commented 2 years ago

We can get this for free from the typo correction middleware in System.CommandLine, which we should do after looking at the impact to the help messages.

am11 commented 2 years ago

There was also a tab-completion mechanism built for shells: https://github.com/dotnet/sdk/blob/a30e465a2e2ea4e2550f319a2dc088daaafe5649/documentation/general/tab-completion.md. Perhaps, both features can complement each other via a common (fuzzy) lookup?

baronfel commented 2 years ago

The tab completion support linked in that document is also powered by system.commandline - so the shared data aspect should already be accounted for. In the future we'd like to make tab completion easier to opt into, so that the user doesn't have to modify their shell profiles at all.

baronfel commented 2 years ago

For anyone interested:

baronfel commented 2 years ago

This won't work out of the box due to the way the .NET CLI hooks up global and local tool lookups - we'd have to do something custom after the second-phase lookup (after global tools).

My preferred way forward would be to integrate global and local tools into the overall command tree so that System.CommandLine's default handling can just take over and provide suggestions.