Skip to content

Commit

Permalink
fix: update help text to show allowed values from AllowedValues att…
Browse files Browse the repository at this point in the history
…ribute instead of Enum values (#391)
  • Loading branch information
scott-xu authored Sep 12, 2020
1 parent 497f598 commit 569b913
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 10 deletions.
32 changes: 24 additions & 8 deletions src/CommandLineUtils/HelpText/DefaultHelpTextGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<AttributeValidator>())
{
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);

Expand Down Expand Up @@ -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<AttributeValidator>())
{
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);

Expand Down
22 changes: 20 additions & 2 deletions test/CommandLineUtils.Tests/DefaultHelpTextGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,19 +112,23 @@ public void ShowHelp()
app.Option("--rStrOpt <E>", "restricted str option desc.", CommandOptionType.SingleValue, o => o.IsRequired().Accepts().Values("Foo", "Bar"));
app.Option<int>("--intOpt <E>", "int option desc.", CommandOptionType.SingleValue);
app.Option<SomeEnum>("--enumOpt <E>", "enum option desc.", CommandOptionType.SingleValue);
app.Option<SomeEnum>("--rEnumOpt <E>", "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<SomeEnum>("SomeEnumArgument", "enum arg desc.");
app.Argument<SomeEnum>("RestrictedEnumArgument", "restricted enum arg desc.", a => a.Accepts().Values("None", "Normal"));
var helpText = GetHelpText(app);

Assert.Equal(@"Usage: [options] <SomeStringArgument> <RestrictedStringArgument> <SomeEnumArgument>
Assert.Equal(@"Usage: [options] <SomeStringArgument> <RestrictedStringArgument> <SomeEnumArgument> <RestrictedEnumArgument>
Arguments:
SomeStringArgument string arg desc.
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.
Expand All @@ -134,6 +138,8 @@ SomeEnumArgument enum arg desc.
--intOpt <E> int option desc.
--enumOpt <E> enum option desc.
Allowed values are: None, Normal, Extreme.
--rEnumOpt <E> restricted enum option desc.
Allowed values are: None, Normal.
",
helpText,
Expand All @@ -148,14 +154,16 @@ public void ShowHelpFromAttributes()
app.Conventions.UseDefaultConventions();
var helpText = GetHelpText(app);

Assert.Equal(@"Usage: test [options] <SomeStringArgument> <RestrictedStringArgument> <SomeEnumArgument>
Assert.Equal(@"Usage: test [options] <SomeStringArgument> <RestrictedStringArgument> <SomeEnumArgument> <RestrictedEnumArgument>
Arguments:
SomeStringArgument string arg desc.
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_OPT> str option desc.
Expand All @@ -164,6 +172,8 @@ SomeEnumArgument enum arg desc.
-intOpt|--int-opt <INT_OPT> int option desc.
-enumOpt|--verbosity <VERBOSITY> enum option desc.
Allowed values are: None, Normal, Extreme.
-rEnumOpt|--verb2 <VERB2> restricted enum option desc.
Allowed values are: None, Normal.
-?|-h|--help Show help information.
",
Expand All @@ -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; }

Expand All @@ -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]
Expand Down

0 comments on commit 569b913

Please sign in to comment.