From e0edf1801e2ba9b4b5f733e3484aa7dbe8bc8aca Mon Sep 17 00:00:00 2001 From: Sarah Oslund Date: Wed, 4 Aug 2021 13:14:40 -0700 Subject: [PATCH 1/4] Show ArgumentHelpName in help if explicitly set by user --- .../Help/HelpBuilderTests.Approval.cs | 2 -- .../Help/HelpBuilderTests.cs | 28 ++++++++++++++++++- src/System.CommandLine/Argument.cs | 11 ++++++++ src/System.CommandLine/Help/HelpBuilder.cs | 8 +++++- src/System.CommandLine/Option.cs | 6 +++- 5 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/System.CommandLine.Tests/Help/HelpBuilderTests.Approval.cs b/src/System.CommandLine.Tests/Help/HelpBuilderTests.Approval.cs index 576956c9ad..0d0672d721 100644 --- a/src/System.CommandLine.Tests/Help/HelpBuilderTests.Approval.cs +++ b/src/System.CommandLine.Tests/Help/HelpBuilderTests.Approval.cs @@ -53,12 +53,10 @@ public void Help_describes_default_values_for_complex_root_command_scenario() new Option(aliases: new string[] {"--the-root-option-enum-arg", "-troea"}, () => FileAccess.Read) { Description = "the-root-option-description", - ArgumentHelpName = "the-root-option-arg", }, new Option(aliases: new string[] {"--the-root-option-required-enum-arg", "-trorea"}, () => FileAccess.Read) { Description = "the-root-option-description", - ArgumentHelpName = "the-root-option-arg", IsRequired = true }, new Option(aliases: new string[] {"--the-root-option-multi-line-description", "-tromld"}) { diff --git a/src/System.CommandLine.Tests/Help/HelpBuilderTests.cs b/src/System.CommandLine.Tests/Help/HelpBuilderTests.cs index 589096ce89..c6bb2c4759 100644 --- a/src/System.CommandLine.Tests/Help/HelpBuilderTests.cs +++ b/src/System.CommandLine.Tests/Help/HelpBuilderTests.cs @@ -469,6 +469,32 @@ public void Arguments_section_includes_configured_argument_aliases() help.Should().Contain("Sets the verbosity."); } + + private enum VerbosityOptions + { + q, + m, + n, + d, + } + + [Fact] + public void Arguments_section_uses_name_over_suggestions_if_specified() + { + var command = new Command("the-command") + { + new Option(new[] { "-v", "--verbosity" }) + { + ArgumentHelpName = "LEVEL" + } + }; + + _helpBuilder.Write(command); + + var help = _console.Out.ToString(); + help.Should().Contain("-v, --verbosity "); + } + [Fact] public void Arguments_section_uses_description_if_provided() { @@ -1240,7 +1266,7 @@ public void Help_describes_default_value_for_option_with_argument_having_default help.Should().Contain($"[default: the-arg-value]"); } - + [Fact] public void Option_arguments_with_default_values_that_are_enumerable_display_pipe_delimited_list() { diff --git a/src/System.CommandLine/Argument.cs b/src/System.CommandLine/Argument.cs index 850980db73..c65cb15b18 100644 --- a/src/System.CommandLine/Argument.cs +++ b/src/System.CommandLine/Argument.cs @@ -17,6 +17,7 @@ public class Argument : Symbol, IArgument { private Func? _defaultValueFactory; private IArgumentArity? _arity; + private bool _isHelpNameSpecified; private TryConvertArgument? _convertArguments; private Type _argumentType = typeof(string); private SuggestionSourceList? _suggestions = null; @@ -65,6 +66,16 @@ public IArgumentArity? Arity set => _arity = value; } + + /// + /// Gets or sets if the ArgumentHelpName is specified by the user. + /// + public bool IsHelpNameSpecified + { + get => _isHelpNameSpecified; + set => _isHelpNameSpecified = value; + } + internal TryConvertArgument? ConvertArguments { get diff --git a/src/System.CommandLine/Help/HelpBuilder.cs b/src/System.CommandLine/Help/HelpBuilder.cs index 23ce4d6b36..3104a06c5d 100644 --- a/src/System.CommandLine/Help/HelpBuilder.cs +++ b/src/System.CommandLine/Help/HelpBuilder.cs @@ -522,7 +522,7 @@ protected string GetArgumentDescriptor(IArgument argument) string descriptor; var suggestions = argument.GetSuggestions().ToArray(); - if (suggestions.Length > 0) + if (suggestions.Length > 0 && UseSuggestionsInHelp(argument)) { descriptor = string.Join("|", suggestions); } @@ -538,6 +538,12 @@ protected string GetArgumentDescriptor(IArgument argument) return descriptor; } + private bool UseSuggestionsInHelp(IArgument argument) + { + var arg = argument as Argument; + return arg == null || !arg.IsHelpNameSpecified; + } + private class Customization { public Customization(Func? getDescriptor, diff --git a/src/System.CommandLine/Option.cs b/src/System.CommandLine/Option.cs index d9139b0ccd..54a9ccd0e9 100644 --- a/src/System.CommandLine/Option.cs +++ b/src/System.CommandLine/Option.cs @@ -134,7 +134,11 @@ internal virtual Argument Argument public string ArgumentHelpName { get => Argument.Name; - set => Argument.Name = value; + set + { + Argument.Name = value; + Argument.IsHelpNameSpecified = true; + } } /// From d947ca7b340c6f8a29990e793ba23ef8a177f2d1 Mon Sep 17 00:00:00 2001 From: Sarah Oslund Date: Thu, 5 Aug 2021 14:26:18 -0700 Subject: [PATCH 2/4] Add HelpName field to Argument --- src/System.CommandLine/Argument.cs | 10 ++-------- src/System.CommandLine/Help/HelpBuilder.cs | 11 ++++++++--- src/System.CommandLine/Option.cs | 5 ++--- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/System.CommandLine/Argument.cs b/src/System.CommandLine/Argument.cs index c65cb15b18..b7d4e3ee55 100644 --- a/src/System.CommandLine/Argument.cs +++ b/src/System.CommandLine/Argument.cs @@ -17,7 +17,6 @@ public class Argument : Symbol, IArgument { private Func? _defaultValueFactory; private IArgumentArity? _arity; - private bool _isHelpNameSpecified; private TryConvertArgument? _convertArguments; private Type _argumentType = typeof(string); private SuggestionSourceList? _suggestions = null; @@ -66,15 +65,10 @@ public IArgumentArity? Arity set => _arity = value; } - /// - /// Gets or sets if the ArgumentHelpName is specified by the user. + /// Argument help name /// - public bool IsHelpNameSpecified - { - get => _isHelpNameSpecified; - set => _isHelpNameSpecified = value; - } + internal string? HelpName { get; set; } internal TryConvertArgument? ConvertArguments { diff --git a/src/System.CommandLine/Help/HelpBuilder.cs b/src/System.CommandLine/Help/HelpBuilder.cs index 3104a06c5d..3f0891a9bd 100644 --- a/src/System.CommandLine/Help/HelpBuilder.cs +++ b/src/System.CommandLine/Help/HelpBuilder.cs @@ -522,7 +522,12 @@ protected string GetArgumentDescriptor(IArgument argument) string descriptor; var suggestions = argument.GetSuggestions().ToArray(); - if (suggestions.Length > 0 && UseSuggestionsInHelp(argument)) + var helpName = GetArgumentHelpName(argument); + if (helpName != null) + { + descriptor = helpName; + } + else if (suggestions.Length > 0) { descriptor = string.Join("|", suggestions); } @@ -538,10 +543,10 @@ protected string GetArgumentDescriptor(IArgument argument) return descriptor; } - private bool UseSuggestionsInHelp(IArgument argument) + private string? GetArgumentHelpName(IArgument argument) { var arg = argument as Argument; - return arg == null || !arg.IsHelpNameSpecified; + return arg == null ? null : arg.HelpName; } private class Customization diff --git a/src/System.CommandLine/Option.cs b/src/System.CommandLine/Option.cs index 54a9ccd0e9..f48173f97a 100644 --- a/src/System.CommandLine/Option.cs +++ b/src/System.CommandLine/Option.cs @@ -133,11 +133,10 @@ internal virtual Argument Argument /// public string ArgumentHelpName { - get => Argument.Name; + get => Argument.HelpName ?? Argument.Name; set { - Argument.Name = value; - Argument.IsHelpNameSpecified = true; + Argument.HelpName = value; } } From e3a09fdf4b26fcf2314cbe5e943b541326c30d2f Mon Sep 17 00:00:00 2001 From: Sarah Oslund Date: Fri, 6 Aug 2021 09:44:06 -0700 Subject: [PATCH 3/4] PR feedback --- src/System.CommandLine.Tests/OptionTests.cs | 3 ++- src/System.CommandLine/Help/HelpBuilder.cs | 6 +++--- src/System.CommandLine/Option.cs | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/System.CommandLine.Tests/OptionTests.cs b/src/System.CommandLine.Tests/OptionTests.cs index 7096df7f74..00860f7a55 100644 --- a/src/System.CommandLine.Tests/OptionTests.cs +++ b/src/System.CommandLine.Tests/OptionTests.cs @@ -240,7 +240,8 @@ public void Argument_takes_option_alias_as_its_name_when_it_is_not_provided() { var command = new Option("--alias", arity: ArgumentArity.ZeroOrOne); - command.ArgumentHelpName.Should().Be("alias"); + command.Name.Should().Be("alias"); + command.ArgumentHelpName.Should().Be(null); } [Fact] diff --git a/src/System.CommandLine/Help/HelpBuilder.cs b/src/System.CommandLine/Help/HelpBuilder.cs index 3f0891a9bd..5cba0c8502 100644 --- a/src/System.CommandLine/Help/HelpBuilder.cs +++ b/src/System.CommandLine/Help/HelpBuilder.cs @@ -523,9 +523,9 @@ protected string GetArgumentDescriptor(IArgument argument) string descriptor; var suggestions = argument.GetSuggestions().ToArray(); var helpName = GetArgumentHelpName(argument); - if (helpName != null) + if (!string.IsNullOrEmpty(helpName)) { - descriptor = helpName; + descriptor = helpName!; } else if (suggestions.Length > 0) { @@ -546,7 +546,7 @@ protected string GetArgumentDescriptor(IArgument argument) private string? GetArgumentHelpName(IArgument argument) { var arg = argument as Argument; - return arg == null ? null : arg.HelpName; + return arg?.HelpName; } private class Customization diff --git a/src/System.CommandLine/Option.cs b/src/System.CommandLine/Option.cs index f48173f97a..423738cb14 100644 --- a/src/System.CommandLine/Option.cs +++ b/src/System.CommandLine/Option.cs @@ -131,9 +131,9 @@ internal virtual Argument Argument /// /// The name of the argument when displayed in help. /// - public string ArgumentHelpName + public string? ArgumentHelpName { - get => Argument.HelpName ?? Argument.Name; + get => Argument.HelpName; set { Argument.HelpName = value; From e5b96529d73ef6351734a0c1b133932fa9757ee6 Mon Sep 17 00:00:00 2001 From: Sarah Oslund Date: Fri, 6 Aug 2021 12:59:34 -0700 Subject: [PATCH 4/4] PR feedback --- src/System.CommandLine.Tests/OptionTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/System.CommandLine.Tests/OptionTests.cs b/src/System.CommandLine.Tests/OptionTests.cs index 00860f7a55..c00315e3d7 100644 --- a/src/System.CommandLine.Tests/OptionTests.cs +++ b/src/System.CommandLine.Tests/OptionTests.cs @@ -241,7 +241,6 @@ public void Argument_takes_option_alias_as_its_name_when_it_is_not_provided() var command = new Option("--alias", arity: ArgumentArity.ZeroOrOne); command.Name.Should().Be("alias"); - command.ArgumentHelpName.Should().Be(null); } [Fact]