Skip to content

Commit

Permalink
strip odd help option aliases, suggest only best option name, and ens…
Browse files Browse the repository at this point in the history
…ure we include recursive options from parents
  • Loading branch information
baronfel committed Jul 31, 2024
1 parent 40d28f3 commit 64269f3
Showing 1 changed file with 37 additions and 4 deletions.
41 changes: 37 additions & 4 deletions src/Cli/dotnet/commands/dotnet-completions/shells/Bash.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ private string GenerateCommandsCompletions(string[] parentCommandNames, CliComma

// generate the words for options and subcommands
var visibleSubcommands = command.Subcommands.Where(c => !c.Hidden).ToArray();
var completionOptions = command.Options.Where(o => !o.Hidden).SelectMany(o => o.Names()).ToArray();
// notably, do not generate completions for all option aliases - since a user is tab-completing we can use the longest forms
var completionOptions = AllOptionsForCommand(command).Where(o => !o.Hidden).Select(o => o.Name).ToArray();
var completionSubcommands = visibleSubcommands.Select(x => x.Name).ToArray();
string[] completionWords = [.. completionSubcommands, .. completionOptions];

Expand Down Expand Up @@ -121,6 +122,34 @@ private string GenerateCommandsCompletions(string[] parentCommandNames, CliComma
return textWriter.ToString() + string.Join('\n', visibleSubcommands.Select(c => GenerateCommandsCompletions(parentCommandNamesForSubcommands, c, isNestedCommand: true)));
}

private static IEnumerable<CliOption> AllOptionsForCommand(CliCommand c)
{
if (c.Parents.Count() == 0)
{
return c.Options;
}
else
{
return c.Options.Concat(c.Parents.OfType<CliCommand>().SelectMany(OptionsForParent));
}

}

private static IEnumerable<CliOption> OptionsForParent(CliCommand c)
{
foreach (var o in c.Options)
{
if (o.Recursive) yield return o;
}
foreach (var p in c.Parents.OfType<CliCommand>())
{
foreach (var o in OptionsForParent(p))
{
yield return o;
}
}
}

private static string[] PositionalArgumentTerms(CliArgument[] arguments)
{
var completions = new List<string>();
Expand Down Expand Up @@ -181,6 +210,8 @@ private static string GenerateDynamicCall()
/// <returns>a bash switch case expression for providing completions for this option</returns>
private static string? GenerateOptionHandler(CliOption option)
{
// unlike the completion-options generation, for actually implementing suggestions we should be able to handle all of the options' aliases.
// this ensures if the user manually enters an alias we can support that usage.
var optionNames = string.Join('|', option.Names());
string completionCommand;
if (option.GetType().IsGenericType &&
Expand Down Expand Up @@ -255,12 +286,14 @@ public static string[] Names(this CliOption option)
{
return [option.Name];
}
else if (option is System.CommandLine.Help.HelpOption) // some of the help aliases are truly horrible
{
return ["--help", "-h"];
}
else
{
return [SanitizeName(option.Name), .. option.Aliases.Select(SanitizeName)];
return [option.Name, .. option.Aliases];
}

static string SanitizeName(string name) => name.Contains('?') ? name.Replace("?", "\\?") : name;
}

/// <summary>
Expand Down

0 comments on commit 64269f3

Please sign in to comment.