Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use single best completion item for commands, options, and global options #1700

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

baronfel
Copy link
Member

@baronfel baronfel commented Apr 5, 2022

This is an attempt to make completions less noisy by using the most relevant available alias for each Subcommand or Option provided for completions. Currently, each of these adds all of its aliases to the pool of available completions, which is quite noisy and can be distracting to a user. Imagine a shell that displays descriptions for completions. Would you want completions at the top-level of the command to emit all 5 Help Option aliases on new rows, along with the same description? I don't think so.

Instead, we try to find the best alias for the Subcommand or Option. What 'best' means varies by context:

  • when the user hasn't typed any part of the subcommand or option, the best should be the longest alias. This is typically a most-descriptive form of the option. While such an alias might be a pain to type out manually, with tab completion we can trade precision for verbosity in a way that costs very little effort.
  • when the user has typed a part of the subcommand or option, we use that stem to:
    • filter the aliases by those that contain the stem
    • sort those descending by Levenstein distance ---------------------- These two steps are taken from the TypoCorrection middleware, it seemed good and relevant to reuse this algorithm
    • then sort descending by the length of the matching starting stem _/
    • then take the first match

Left to do:

  • get feedback on algorithm
  • add tests specifically around verifying that only one alias is returned per option

{
#if NET6_0_OR_GREATER
"" => aliases.MaxBy(a => a.Length), // find the longest alias
(string stem) => aliases.Where(a => a.Contains(stem, StringComparison.OrdinalIgnoreCase)).OrderByDescending(a => TokenDistances.GetLevensteinDistance(stem, a)).ThenByDescending(a => TokenDistances.GetStartsWithDistance(stem, a)).FirstOrDefault()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use alias.ContainsCaseInsensitive extension method instead here to remove TFM split

@KalleOlaviNiemitalo
Copy link

the best should be the longest alias

Consider using the first alias, or even Symbol.Name. This would give the app developer better control on which alias is preferred.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants