diff --git a/src/CommandLine/Parser.cs b/src/CommandLine/Parser.cs index 4301aa52..9944cf97 100644 --- a/src/CommandLine/Parser.cs +++ b/src/CommandLine/Parser.cs @@ -201,16 +201,18 @@ private static ParserResult<T> MakeParserResult<T>(ParserResult<T> parserResult, { return DisplayHelp( parserResult, + settings.AutoVersion, + settings.AutoHelp, settings.HelpWriter, settings.MaximumDisplayWidth); } - private static ParserResult<T> DisplayHelp<T>(ParserResult<T> parserResult, TextWriter helpWriter, int maxDisplayWidth) + private static ParserResult<T> DisplayHelp<T>(ParserResult<T> parserResult, bool autoVersion, bool autoHelp, TextWriter helpWriter, int maxDisplayWidth) { parserResult.WithNotParsed( errors => Maybe.Merge(errors.ToMaybe(), helpWriter.ToMaybe()) - .Do((_, writer) => writer.Write(HelpText.AutoBuild(parserResult, maxDisplayWidth))) + .Do((_, writer) => writer.Write(HelpText.AutoBuild(parserResult, maxDisplayWidth, autoVersion, autoHelp))) ); return parserResult; diff --git a/src/CommandLine/Text/HelpText.cs b/src/CommandLine/Text/HelpText.cs index f5e9a7b9..3c798687 100644 --- a/src/CommandLine/Text/HelpText.cs +++ b/src/CommandLine/Text/HelpText.cs @@ -314,6 +314,8 @@ public SentenceBuilder SentenceBuilder /// <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='autoVersion'>A value to indicate whether <see cref="HelpText.AutoVersion" /> shall be set or not.</param> + /// <param name='autoHelp'>A value to indicate whether <see cref="HelpText.AutoHelp" /> shall be set or not.</param> /// <param name="verbsIndex">If true the output style is consistent with verb commands (no dashes), otherwise it outputs options.</param> /// <param name="maxDisplayWidth">The maximum width of the display.</param> /// <remarks>The parameter <paramref name="verbsIndex"/> is not ontly a metter of formatting, it controls whether to handle verbs or options.</remarks> @@ -322,7 +324,9 @@ public static HelpText AutoBuild<T>( Func<HelpText, HelpText> onError, Func<Example, Example> onExample, bool verbsIndex = false, - int maxDisplayWidth = DefaultMaximumLength) + int maxDisplayWidth = DefaultMaximumLength, + bool autoVersion = true, + bool autoHelp = true) { var auto = new HelpText { @@ -330,7 +334,9 @@ public static HelpText AutoBuild<T>( Copyright = CopyrightInfo.Empty, AdditionalNewLineAfterOption = true, AddDashesToOption = !verbsIndex, - MaximumDisplayWidth = maxDisplayWidth + MaximumDisplayWidth = maxDisplayWidth, + AutoVersion = autoVersion, + AutoHelp = autoHelp, }; try @@ -394,14 +400,16 @@ public static HelpText AutoBuild<T>( /// </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="maxDisplayWidth">The maximum width of the display.</param> + /// <param name='autoVersion'>A value to indicate whether <see cref="HelpText.AutoVersion" /> shall be set or not.</param> + /// <param name='autoHelp'>A value to indicate whether <see cref="HelpText.AutoHelp" /> shall be set or not.</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, int maxDisplayWidth = DefaultMaximumLength) + public static HelpText AutoBuild<T>(ParserResult<T> parserResult, int maxDisplayWidth = DefaultMaximumLength, bool autoVersion = true, bool autoHelp = true) { - return AutoBuild<T>(parserResult, h => h, maxDisplayWidth); + return AutoBuild<T>(parserResult, h => h, maxDisplayWidth, autoVersion, autoHelp); } /// <summary> @@ -411,12 +419,14 @@ public static HelpText AutoBuild<T>(ParserResult<T> parserResult, int maxDisplay /// <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="maxDisplayWidth">The maximum width of the display.</param> + /// <param name="autoVersion">A value to indicate whether <see cref="HelpText.AutoVersion" /> shall be set or not.</param> + /// <param name="autoHelp">A value to indicate whether <see cref="HelpText.AutoHelp" /> shall be set or not.</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, Func<HelpText, HelpText> onError, int maxDisplayWidth = DefaultMaximumLength) + public static HelpText AutoBuild<T>(ParserResult<T> parserResult, Func<HelpText, HelpText> onError, int maxDisplayWidth = DefaultMaximumLength, bool autoVersion = true, bool autoHelp = true) { if (parserResult.Tag != ParserResultType.NotParsed) throw new ArgumentException("Excepting NotParsed<T> type.", "parserResult"); @@ -431,7 +441,7 @@ public static HelpText AutoBuild<T>(ParserResult<T> parserResult, Func<HelpText, { onError?.Invoke(current); return DefaultParsingErrorsHandler(parserResult, current); - }, e => e, maxDisplayWidth: maxDisplayWidth); + }, e => e, maxDisplayWidth: maxDisplayWidth, autoVersion: autoVersion, autoHelp: autoHelp); var err = errors.OfType<HelpVerbRequestedError>().Single(); var pr = new NotParsed<object>(TypeInfo.Create(err.Type), new Error[] { err }); @@ -440,12 +450,12 @@ public static HelpText AutoBuild<T>(ParserResult<T> parserResult, Func<HelpText, { onError?.Invoke(current); return DefaultParsingErrorsHandler(pr, current); - }, e => e, maxDisplayWidth: maxDisplayWidth) + }, e => e, maxDisplayWidth: maxDisplayWidth, autoVersion: autoVersion, autoHelp: autoHelp) : AutoBuild(parserResult, current => { onError?.Invoke(current); return DefaultParsingErrorsHandler(parserResult, current); - }, e => e, true, maxDisplayWidth); + }, e => e, true, maxDisplayWidth, autoVersion: autoVersion, autoHelp: autoHelp); } /// <summary> diff --git a/tests/CommandLine.Tests/Unit/Issue821Tests.cs b/tests/CommandLine.Tests/Unit/Issue821Tests.cs new file mode 100644 index 00000000..e650188d --- /dev/null +++ b/tests/CommandLine.Tests/Unit/Issue821Tests.cs @@ -0,0 +1,123 @@ +using System; +using System.IO; +using System.Linq; +using System.Runtime.Serialization.Formatters; +using System.Text; +using CommandLine.Tests.Fakes; +using CommandLine.Text; +using FluentAssertions; +using Xunit; +using Xunit.Abstractions; + +//Issue #591 +//When options class is only having explicit interface declarations, it should be detected as mutable. + +namespace CommandLine.Tests.Unit +{ + public class Issue821Tests + { + [Verb("do")] + private class EmptyDoOptions{ + }; + + [Verb("nothing")] + private class EmptyNothingOptions{ + }; + + [Fact] + public void not_parsed_should_produce_version_if_set_to_true() + { + StringBuilder output = new StringBuilder(); + ParserResult<object> result; + using (StringWriter writer = new StringWriter(output)) + { + void ConfigureParser(ParserSettings settings) + { + settings.HelpWriter = writer; + settings.AutoVersion = true; + } + + using (Parser parser = new Parser(ConfigureParser)) + { + result = parser.ParseArguments<EmptyDoOptions, EmptyNothingOptions>(Array.Empty<string>()); + } + } + + result.Should().BeOfType<NotParsed<object>>(); + string outputContent = output.ToString(); + outputContent.Should().Contain("version", "Version is set to true and must be contained"); + } + + [Fact] + public void not_parsed_should_not_produce_version_if_set_to_false() + { + StringBuilder output = new StringBuilder(); + ParserResult<object> result; + using (StringWriter writer = new StringWriter(output)) + { + void ConfigureParser(ParserSettings settings) + { + settings.HelpWriter = writer; + settings.AutoVersion = false; + } + + using (Parser parser = new Parser(ConfigureParser)) + { + result = parser.ParseArguments<EmptyDoOptions, EmptyNothingOptions>(Array.Empty<string>()); + } + } + + result.Should().BeOfType<NotParsed<object>>(); + string outputContent = output.ToString(); + outputContent.Should().NotContain("version", "Version is set to false and must not be contained"); + } + + [Fact] + public void not_parsed_should_produce_help_if_set_to_true() + { + StringBuilder output = new StringBuilder(); + ParserResult<object> result; + using (StringWriter writer = new StringWriter(output)) + { + void ConfigureParser(ParserSettings settings) + { + settings.HelpWriter = writer; + settings.AutoHelp = true; + } + + using (Parser parser = new Parser(ConfigureParser)) + { + result = parser.ParseArguments<EmptyDoOptions, EmptyNothingOptions>(Array.Empty<string>()); + } + } + + result.Should().BeOfType<NotParsed<object>>(); + string outputContent = output.ToString(); + outputContent.Should().Contain("help", "Help is set to true and must be contained"); + } + + [Fact] + public void not_parsed_should_not_produce_help_if_set_to_false() + { + StringBuilder output = new StringBuilder(); + ParserResult<object> result; + using (StringWriter writer = new StringWriter(output)) + { + void ConfigureParser(ParserSettings settings) + { + settings.HelpWriter = writer; + settings.AutoHelp = false; + } + + using (Parser parser = new Parser(ConfigureParser)) + { + result = parser.ParseArguments<EmptyDoOptions, EmptyNothingOptions>(Array.Empty<string>()); + } + } + + result.Should().BeOfType<NotParsed<object>>(); + string outputContent = output.ToString(); + outputContent.Should().NotContain("help", "Help is set to false and must not be contained"); + } + } +}