Skip to content

Propagate parser-settings to HelpText (fix #414 and #455) #461

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions src/CommandLine/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,16 +194,15 @@ private static ParserResult<T> MakeParserResult<T>(ParserResult<T> parserResult,
{
return DisplayHelp(
parserResult,
settings.HelpWriter,
settings.MaximumDisplayWidth);
settings);
}

private static ParserResult<T> DisplayHelp<T>(ParserResult<T> parserResult, TextWriter helpWriter, int maxDisplayWidth)
private static ParserResult<T> DisplayHelp<T>(ParserResult<T> parserResult, ParserSettings settings)
{
parserResult.WithNotParsed(
errors =>
Maybe.Merge(errors.ToMaybe(), helpWriter.ToMaybe())
.Do((_, writer) => writer.Write(HelpText.AutoBuild(parserResult, maxDisplayWidth)))
Maybe.Merge(errors.ToMaybe(), settings.HelpWriter.ToMaybe())
.Do((_, writer) => writer.Write(HelpText.AutoBuild(parserResult, settings)))
);

return parserResult;
Expand All @@ -229,4 +228,4 @@ private void Dispose(bool disposing)
}
}
}
}
}
54 changes: 48 additions & 6 deletions src/CommandLine/Text/HelpText.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,14 +235,39 @@ public static HelpText AutoBuild<T>(
Func<Example, Example> onExample,
bool verbsIndex = false,
int maxDisplayWidth = DefaultMaximumLength)
{
var settings = new ParserSettings() { MaximumDisplayWidth = maxDisplayWidth };
return HelpText.AutoBuild<T>(parserResult, onError, onExample, settings, verbsIndex);
}

/// <summary>
/// Creates a new instance of the <see cref="CommandLine.Text.HelpText"/> class using common defaults.
/// </summary>
/// <returns>
/// An instance of <see cref="CommandLine.Text.HelpText"/> class.
/// </returns>
/// <param name='parserResult'>The <see cref="CommandLine.ParserResult{T}"/> containing the instance that collected command line arguments parsed with <see cref="CommandLine.Parser"/> class.</param>
/// <param name='onError'>A delegate used to customize the text block of reporting parsing errors text block.</param>
/// <param name='onExample'>A delegate used to customize <see cref="CommandLine.Text.Example"/> model used to render text block of usage examples.</param>
/// <param name="verbsIndex">If true the output style is consistent with verb commands (no dashes), otherwise it outputs options.</param>
/// <param name="settings">The parser settings</param>
/// <remarks>The parameter <paramref name="verbsIndex"/> is not ontly a metter of formatting, it controls whether to handle verbs or options.</remarks>
public static HelpText AutoBuild<T>(
ParserResult<T> parserResult,
Func<HelpText, HelpText> onError,
Func<Example, Example> onExample,
ParserSettings settings,
bool verbsIndex = false)
{
var auto = new HelpText
{
Heading = HeadingInfo.Empty,
Copyright = CopyrightInfo.Empty,
AdditionalNewLineAfterOption = true,
AddDashesToOption = !verbsIndex,
MaximumDisplayWidth = maxDisplayWidth
MaximumDisplayWidth = settings.MaximumDisplayWidth,
AutoHelp = settings.AutoHelp,
AutoVersion = settings.AutoVersion
};

try
Expand Down Expand Up @@ -308,23 +333,40 @@ public static HelpText AutoBuild<T>(
/// <remarks>This feature is meant to be invoked automatically by the parser, setting the HelpWriter property
/// of <see cref="CommandLine.ParserSettings"/>.</remarks>
public static HelpText AutoBuild<T>(ParserResult<T> parserResult, int maxDisplayWidth = DefaultMaximumLength)
{
var settings = new ParserSettings() { MaximumDisplayWidth = maxDisplayWidth };
return HelpText.AutoBuild<T>(parserResult, settings);
}

/// <summary>
/// Creates a new instance of the <see cref="CommandLine.Text.HelpText"/> class,
/// automatically handling verbs or options scenario.
/// </summary>
/// <param name='parserResult'>The <see cref="CommandLine.ParserResult{T}"/> containing the instance that collected command line arguments parsed with <see cref="CommandLine.Parser"/> class.</param>
/// <param name="settings">The parser settings.</param>
/// <returns>
/// An instance of <see cref="CommandLine.Text.HelpText"/> class.
/// </returns>
/// <remarks>This feature is meant to be invoked automatically by the parser, setting the HelpWriter property
/// of <see cref="CommandLine.ParserSettings"/>.</remarks>
public static HelpText AutoBuild<T>(ParserResult<T> parserResult, ParserSettings settings)
{
if (parserResult.Tag != ParserResultType.NotParsed)
throw new ArgumentException("Excepting NotParsed<T> type.", "parserResult");

var errors = ((NotParsed<T>)parserResult).Errors;

if (errors.Any(e => e.Tag == ErrorType.VersionRequestedError))
return new HelpText(HeadingInfo.Default){MaximumDisplayWidth = maxDisplayWidth }.AddPreOptionsLine(Environment.NewLine);
return new HelpText(HeadingInfo.Default){MaximumDisplayWidth = settings.MaximumDisplayWidth, AutoHelp = settings.AutoHelp, AutoVersion = settings.AutoVersion }.AddPreOptionsLine(Environment.NewLine);

if (!errors.Any(e => e.Tag == ErrorType.HelpVerbRequestedError))
return AutoBuild(parserResult, current => DefaultParsingErrorsHandler(parserResult, current), e => e, maxDisplayWidth: maxDisplayWidth);
return AutoBuild(parserResult, current => DefaultParsingErrorsHandler(parserResult, current), e => e, settings);

var err = errors.OfType<HelpVerbRequestedError>().Single();
var pr = new NotParsed<object>(TypeInfo.Create(err.Type), Enumerable.Empty<Error>());
return err.Matched
? AutoBuild(pr, current => DefaultParsingErrorsHandler(pr, current), e => e, maxDisplayWidth: maxDisplayWidth)
: AutoBuild(parserResult, current => DefaultParsingErrorsHandler(parserResult, current), e => e, true, maxDisplayWidth);
? AutoBuild(pr, current => DefaultParsingErrorsHandler(pr, current), e => e, settings)
: AutoBuild(parserResult, current => DefaultParsingErrorsHandler(parserResult, current), e => e, settings, true);
}

/// <summary>
Expand Down Expand Up @@ -998,4 +1040,4 @@ private static string FormatDefaultValue<T>(T value)
: string.Empty;
}
}
}
}
112 changes: 112 additions & 0 deletions tests/CommandLine.Tests/Unit/ParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -860,5 +860,117 @@ public void Parse_options_with_shuffled_index_values()
Assert.Equal("two", args.Arg2);
});
}

[Fact]
// Tests a fix for issue #455
public void Help_screen_does_not_show_help_verb_if_AutoHelp_is_disabled()
{
var output = new StringWriter();
var sut = new Parser(config => { config.AutoHelp = false; config.HelpWriter = output; });

sut.ParseArguments<Secert_Verb, Add_Verb_With_Usage_Attribute>(new string[] { });

var helpText = output.ToString();
Assert.DoesNotContain("help", helpText, StringComparison.InvariantCulture);
Assert.DoesNotContain("Display more information on a specific command", helpText, StringComparison.InvariantCulture);
}

[Fact]
// Tests a fix for issue #455
public void Help_screen_does_not_show_help_option_if_AutoHelp_is_disabled()
{
var output = new StringWriter();
var sut = new Parser(config => { config.AutoHelp = false; config.HelpWriter = output; });

sut.ParseArguments<Simple_Options_With_HelpText_Set>(new string[] { });

var helpText = output.ToString();
Assert.DoesNotContain("--help", helpText, StringComparison.InvariantCulture);
Assert.DoesNotContain("Display this help screen.", helpText, StringComparison.InvariantCulture);
}

[Fact]
// Tests a fix for issue #455
public void Help_screen_shows_help_verb_if_AutoHelp_is_enabled()
{
var output = new StringWriter();
var sut = new Parser(config => { config.AutoHelp = true; config.HelpWriter = output; });

sut.ParseArguments<Secert_Verb, Add_Verb_With_Usage_Attribute>(new string[] { });

var helpText = output.ToString();
Assert.Contains("help", helpText, StringComparison.InvariantCulture);
Assert.Contains("Display more information on a specific command", helpText, StringComparison.InvariantCulture);
}

[Fact]
// Tests a fix for issue #455
public void Help_screen_shows_help_option_if_AutoHelp_is_enabled()
{
var output = new StringWriter();
var sut = new Parser(config => { config.AutoHelp = true; config.HelpWriter = output; });

sut.ParseArguments<Simple_Options_With_HelpText_Set>(new string[] { });

var helpText = output.ToString();
Assert.Contains("help", helpText, StringComparison.InvariantCulture);
Assert.Contains("Display this help screen.", helpText, StringComparison.InvariantCulture);
}

[Fact]
// Tests a fix for issue #414
public void Help_screen_does_not_show_version_verb_if_AutoVersion_is_disabled()
{
var output = new StringWriter();
var sut = new Parser(config => { config.AutoVersion = false; config.HelpWriter = output; });

sut.ParseArguments<Secert_Verb, Add_Verb_With_Usage_Attribute>(new string[] { });

var helpText = output.ToString();
Assert.DoesNotContain("version", helpText, StringComparison.InvariantCulture);
Assert.DoesNotContain("Display version information.", helpText, StringComparison.InvariantCulture);
}

[Fact]
// Tests a fix for issue #414
public void Help_screen_does_not_show_version_option_if_AutoVersion_is_disabled()
{
var output = new StringWriter();
var sut = new Parser(config => { config.AutoVersion = false; config.HelpWriter = output; });

sut.ParseArguments<Simple_Options_With_HelpText_Set>(new string[] { });

var helpText = output.ToString();
Assert.DoesNotContain("--version", helpText, StringComparison.InvariantCulture);
Assert.DoesNotContain("Display version information.", helpText, StringComparison.InvariantCulture);
}

[Fact]
// Tests a fix for issue #414
public void Help_screen_shows_version_verb_if_AutoVersion_is_enabled()
{
var output = new StringWriter();
var sut = new Parser(config => { config.AutoVersion = true; config.HelpWriter = output; });

sut.ParseArguments<Secert_Verb, Add_Verb_With_Usage_Attribute>(new string[] { });

var helpText = output.ToString();
Assert.Contains("version", helpText, StringComparison.InvariantCulture);
Assert.Contains("Display version information.", helpText, StringComparison.InvariantCulture);
}

[Fact]
// Tests a fix for issue #414
public void Help_screen_shows_version_option_if_AutoVersion_is_ensabled()
{
var output = new StringWriter();
var sut = new Parser(config => { config.AutoVersion = true; config.HelpWriter = output; });

sut.ParseArguments<Simple_Options_With_HelpText_Set>(new string[] { });

var helpText = output.ToString();
Assert.Contains("--version", helpText, StringComparison.InvariantCulture);
Assert.Contains("Display version information.", helpText, StringComparison.InvariantCulture);
}
}
}
55 changes: 46 additions & 9 deletions tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,10 @@ public void Invoke_AutoBuild_for_Options_returns_appropriate_formatted_text()
new BadFormatTokenError("badtoken"),
new SequenceOutOfRangeError(new NameInfo("i", ""))
});
var settings = new ParserSettings();

// Exercize system
var helpText = HelpText.AutoBuild(fakeResult);
var helpText = HelpText.AutoBuild(fakeResult, settings);

// Verify outcome
var lines = helpText.ToString().ToNotEmptyLines().TrimStringArray();
Expand Down Expand Up @@ -353,9 +354,10 @@ public void Invoke_AutoBuild_for_Verbs_with_specific_verb_returns_appropriate_fo
{
new HelpVerbRequestedError("commit", typeof(Commit_Verb), true)
});
var settings = new ParserSettings();

// Exercize system
var helpText = HelpText.AutoBuild(fakeResult);
var helpText = HelpText.AutoBuild(fakeResult, settings);

// Verify outcome
var lines = helpText.ToString().ToNotEmptyLines().TrimStringArray();
Expand Down Expand Up @@ -386,9 +388,10 @@ public void Invoke_AutoBuild_for_Verbs_with_specific_verb_returns_appropriate_fo
{
new HelpVerbRequestedError("commit", typeof(Commit_Verb), true)
});
var settings = new ParserSettings() { MaximumDisplayWidth = 100 };

// Exercize system
var helpText = HelpText.AutoBuild(fakeResult, maxDisplayWidth: 100);
var helpText = HelpText.AutoBuild(fakeResult, settings);

// Verify outcome
var lines = helpText.ToString().ToNotEmptyLines().TrimStringArray();
Expand Down Expand Up @@ -418,9 +421,10 @@ public void Invoke_AutoBuild_for_Verbs_with_unknown_verb_returns_appropriate_for
TypeInfo.Create(typeof(NullInstance),
verbTypes),
new Error[] { new HelpVerbRequestedError(null, null, false) });
var settings = new ParserSettings();

// Exercize system
var helpText = HelpText.AutoBuild(fakeResult);
var helpText = HelpText.AutoBuild(fakeResult, settings);

// Verify outcome
var lines = helpText.ToString().ToNotEmptyLines().TrimStringArray();
Expand Down Expand Up @@ -504,9 +508,10 @@ public void Invoke_AutoBuild_for_Options_with_Usage_returns_appropriate_formatte
{
new BadFormatTokenError("badtoken")
});
var settings = new ParserSettings();

// Exercize system
var helpText = HelpText.AutoBuild(fakeResult);
var helpText = HelpText.AutoBuild(fakeResult, settings);

// Verify outcome
var text = helpText.ToString();
Expand Down Expand Up @@ -556,10 +561,11 @@ public void Default_set_to_sequence_should_be_properly_printed()
new NotParsed<Options_With_Default_Set_To_Sequence>(
typeof(Options_With_Default_Set_To_Sequence).ToTypeInfo(),
new Error[] { new BadFormatTokenError("badtoken") });
var settings = new ParserSettings();

// Exercize system
handlers.ChangeCulture();
var helpText = HelpText.AutoBuild(fakeResult);
var helpText = HelpText.AutoBuild(fakeResult, settings);
handlers.ResetCulture();

// Verify outcome
Expand All @@ -577,6 +583,7 @@ public void Default_set_to_sequence_should_be_properly_printed()
[Fact]
public void AutoBuild_when_no_assembly_attributes()
{
var settings = new ParserSettings();
string expectedCopyright = "Copyright (C) 1 author";

ReflectionHelper.SetAttributeOverride(new Attribute[0]);
Expand All @@ -588,7 +595,7 @@ public void AutoBuild_when_no_assembly_attributes()
{
onErrorCalled = true;
return ht;
}, ex => ex);
}, ex => ex, settings);

onErrorCalled.Should().BeTrue();
actualResult.Copyright.Should().Be(expectedCopyright);
Expand All @@ -597,6 +604,7 @@ public void AutoBuild_when_no_assembly_attributes()
[Fact]
public void AutoBuild_with_assembly_title_and_version_attributes_only()
{
var settings = new ParserSettings();
string expectedTitle = "Title";
string expectedVersion = "1.2.3.4";

Expand All @@ -613,7 +621,7 @@ public void AutoBuild_with_assembly_title_and_version_attributes_only()
{
onErrorCalled = true;
return ht;
}, ex => ex);
}, ex => ex, settings);

onErrorCalled.Should().BeTrue();
actualResult.Heading.Should().Be(string.Format("{0} {1}", expectedTitle, expectedVersion));
Expand All @@ -623,6 +631,7 @@ public void AutoBuild_with_assembly_title_and_version_attributes_only()
[Fact]
public void AutoBuild_with_assembly_company_attribute_only()
{
var settings = new ParserSettings();
string expectedCompany = "Company";

ReflectionHelper.SetAttributeOverride(new Attribute[]
Expand All @@ -637,7 +646,7 @@ public void AutoBuild_with_assembly_company_attribute_only()
{
onErrorCalled = true;
return ht;
}, ex => ex);
}, ex => ex, settings);

onErrorCalled.Should().BeFalse(); // Other attributes have fallback logic
actualResult.Copyright.Should().Be(string.Format("Copyright (C) {0} {1}", DateTime.Now.Year, expectedCompany));
Expand All @@ -653,5 +662,33 @@ public void Add_line_with_two_empty_spaces_at_the_end()

Assert.Equal("T" + Environment.NewLine + "e" + Environment.NewLine + "s" + Environment.NewLine + "t", b.ToString());
}

[Fact]
public void AutoBuild_without_settings_contains_help_and_version()
{
var parserResult = new NotParsed<object>(TypeInfo.Create(typeof(NullInstance)), new[] { new BadFormatConversionError(new NameInfo("f", "foo")) });

var helpText = HelpText.AutoBuild(parserResult);

var text = helpText.ToString();
Assert.Contains("--help", helpText, StringComparison.InvariantCulture);
Assert.Contains("Display version information.", helpText, StringComparison.InvariantCulture);
Assert.Contains("--version", helpText, StringComparison.InvariantCulture);
Assert.Contains("Display this help screen.", helpText, StringComparison.InvariantCulture);
}

[Fact]
public void AutoBuild_with_settings_does_not_contain_help_and_version()
{
var parserResult = new NotParsed<object>(TypeInfo.Create(typeof(NullInstance)), new[] { new BadFormatConversionError(new NameInfo("f", "foo")) });
var settings = new ParserSettings() { AutoHelp = false, AutoVersion = false };
var helpText = HelpText.AutoBuild(parserResult, settings);

var text = helpText.ToString();
Assert.DoesNotContain("--help", helpText, StringComparison.InvariantCulture);
Assert.DoesNotContain("Display version information.", helpText, StringComparison.InvariantCulture);
Assert.DoesNotContain("--version", helpText, StringComparison.InvariantCulture);
Assert.DoesNotContain("Display this help screen.", helpText, StringComparison.InvariantCulture);
}
}
}