From 0ab71110ffe35dd8bef01128e4b6271fe4e85d5d Mon Sep 17 00:00:00 2001 From: Scott Xu Date: Mon, 31 Aug 2020 18:51:01 +0800 Subject: [PATCH] Show allowed values from `AllowedValues` attribute instead of Enum values for eample, when use `HashAlgorithmType` https://docs.microsoft.com/en-us/dotnet/api/system.security.authentication.hashalgorithmtype?view=netframework-4.8 as the option type, we want to limit the values to Sha256, Sha384 and Sha512. Prior the fix, there will be 2 lines of "Default values are: ..." in help text --- .../HelpText/DefaultHelpTextGenerator.cs | 32 ++++++++++++++----- .../DefaultHelpTextGeneratorTests.cs | 22 +++++++++++-- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/CommandLineUtils/HelpText/DefaultHelpTextGenerator.cs b/src/CommandLineUtils/HelpText/DefaultHelpTextGenerator.cs index 6c5665bc..da27df3e 100644 --- a/src/CommandLineUtils/HelpText/DefaultHelpTextGenerator.cs +++ b/src/CommandLineUtils/HelpText/DefaultHelpTextGenerator.cs @@ -192,20 +192,28 @@ protected virtual void GenerateArguments( foreach (var arg in visibleArguments) { - var enumNames = ExtractNamesFromEnum(arg.UnderlyingType); - var description = enumNames.Any() - ? $"{arg.Description}\nAllowed values are: {string.Join(", ", enumNames)}." - : arg.Description; + var description = arg.Description; + var allowedValuesBeenSet = false; foreach (var attributeValidator in arg.Validators.Cast()) { if (attributeValidator?.ValidationAttribute is AllowedValuesAttribute allowedValuesAttribute) { description += $"\nAllowed values are: {string.Join(", ", allowedValuesAttribute.AllowedValues)}."; + allowedValuesBeenSet = true; break; } } + if (!allowedValuesBeenSet) + { + var enumNames = ExtractNamesFromEnum(arg.UnderlyingType); + if (enumNames.Any()) + { + description += $"\nAllowed values are: {string.Join(", ", enumNames)}."; + } + } + var wrappedDescription = IndentWriter?.Write(description); var message = string.Format(outputFormat, arg.Name, wrappedDescription); @@ -236,20 +244,28 @@ protected virtual void GenerateOptions( foreach (var opt in visibleOptions) { - var enumNames = ExtractNamesFromEnum(opt.UnderlyingType); - var description = enumNames.Any() - ? $"{opt.Description}\nAllowed values are: {string.Join(", ", enumNames)}." - : opt.Description; + var description = opt.Description; + var allowedValuesBeenSet = false; foreach (var attributeValidator in opt.Validators.Cast()) { if (attributeValidator?.ValidationAttribute is AllowedValuesAttribute allowedValuesAttribute) { description += $"\nAllowed values are: {string.Join(", ", allowedValuesAttribute.AllowedValues)}."; + allowedValuesBeenSet = true; break; } } + if (!allowedValuesBeenSet) + { + var enumNames = ExtractNamesFromEnum(opt.UnderlyingType); + if (enumNames.Any()) + { + description += $"\nAllowed values are: {string.Join(", ", enumNames)}."; + } + } + var wrappedDescription = IndentWriter?.Write(description); var message = string.Format(outputFormat, Format(opt), wrappedDescription); diff --git a/test/CommandLineUtils.Tests/DefaultHelpTextGeneratorTests.cs b/test/CommandLineUtils.Tests/DefaultHelpTextGeneratorTests.cs index 4e03dc16..904959c5 100644 --- a/test/CommandLineUtils.Tests/DefaultHelpTextGeneratorTests.cs +++ b/test/CommandLineUtils.Tests/DefaultHelpTextGeneratorTests.cs @@ -112,12 +112,14 @@ public void ShowHelp() app.Option("--rStrOpt ", "restricted str option desc.", CommandOptionType.SingleValue, o => o.IsRequired().Accepts().Values("Foo", "Bar")); app.Option("--intOpt ", "int option desc.", CommandOptionType.SingleValue); app.Option("--enumOpt ", "enum option desc.", CommandOptionType.SingleValue); + app.Option("--rEnumOpt ", "restricted enum option desc.", CommandOptionType.SingleValue, o => o.Accepts().Values("None", "Normal")); app.Argument("SomeStringArgument", "string arg desc."); app.Argument("RestrictedStringArgument", "restricted string arg desc.", a => a.IsRequired().Accepts().Values("Foo", "Bar")); app.Argument("SomeEnumArgument", "enum arg desc."); + app.Argument("RestrictedEnumArgument", "restricted enum arg desc.", a => a.Accepts().Values("None", "Normal")); var helpText = GetHelpText(app); - Assert.Equal(@"Usage: [options] + Assert.Equal(@"Usage: [options] Arguments: SomeStringArgument string arg desc. @@ -125,6 +127,8 @@ RestrictedStringArgument restricted string arg desc. Allowed values are: Foo, Bar. SomeEnumArgument enum arg desc. Allowed values are: None, Normal, Extreme. + RestrictedEnumArgument restricted enum arg desc. + Allowed values are: None, Normal. Options: -?|-h|--help Show help information. @@ -134,6 +138,8 @@ SomeEnumArgument enum arg desc. --intOpt int option desc. --enumOpt enum option desc. Allowed values are: None, Normal, Extreme. + --rEnumOpt restricted enum option desc. + Allowed values are: None, Normal. ", helpText, @@ -148,7 +154,7 @@ public void ShowHelpFromAttributes() app.Conventions.UseDefaultConventions(); var helpText = GetHelpText(app); - Assert.Equal(@"Usage: test [options] + Assert.Equal(@"Usage: test [options] Arguments: SomeStringArgument string arg desc. @@ -156,6 +162,8 @@ RestrictedStringArgument restricted string arg desc. Allowed values are: Foo, Bar. SomeEnumArgument enum arg desc. Allowed values are: None, Normal, Extreme. + RestrictedEnumArgument restricted enum arg desc. + Allowed values are: None, Normal. Options: -strOpt|--str-opt str option desc. @@ -164,6 +172,8 @@ SomeEnumArgument enum arg desc. -intOpt|--int-opt int option desc. -enumOpt|--verbosity enum option desc. Allowed values are: None, Normal, Extreme. + -rEnumOpt|--verb2 restricted enum option desc. + Allowed values are: None, Normal. -?|-h|--help Show help information. ", @@ -187,6 +197,10 @@ public class MyApp [Option(ShortName = "enumOpt", Description = "enum option desc.")] public SomeEnum Verbosity { get; set; } + [Option(ShortName = "rEnumOpt", Description = "restricted enum option desc.")] + [AllowedValues("None", "Normal")] + public SomeEnum Verb2 { get; set; } + [Argument(0, Description = "string arg desc.")] public string SomeStringArgument { get; set; } @@ -197,6 +211,10 @@ public class MyApp [Argument(2, Description = "enum arg desc.")] public SomeEnum SomeEnumArgument { get; set; } + + [Argument(3, Description = "restricted enum arg desc.")] + [AllowedValues("None", "Normal")] + public SomeEnum RestrictedEnumArgument { get; set; } } [Theory]