From ee30c24d4d4764befdb80077fa3e7ebaa64ec28d Mon Sep 17 00:00:00 2001 From: "Moh.Hassan" Date: Wed, 3 Jul 2019 21:53:26 +0200 Subject: [PATCH 1/4] Fix issue #259 for HelpText.AutoBuild configuration --- src/CommandLine/ErrorExtensions.cs | 27 +++ src/CommandLine/Text/HelpText.cs | 6 +- .../Unit/Text/HelpTextAutoBuildFix.cs | 164 ++++++++++++++++++ 3 files changed, 195 insertions(+), 2 deletions(-) create mode 100644 tests/CommandLine.Tests/Unit/Text/HelpTextAutoBuildFix.cs diff --git a/src/CommandLine/ErrorExtensions.cs b/src/CommandLine/ErrorExtensions.cs index 2ffe629d..43b7cfd0 100644 --- a/src/CommandLine/ErrorExtensions.cs +++ b/src/CommandLine/ErrorExtensions.cs @@ -1,5 +1,6 @@ // Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information. +using System; using System.Collections.Generic; using System.Linq; using CommandLine.Core; @@ -23,5 +24,31 @@ public static IEnumerable OnlyMeaningfulOnes(this IEnumerable erro .Where(e => !(e.Tag == ErrorType.UnknownOptionError && ((UnknownOptionError)e).Token.EqualsOrdinalIgnoreCase("help"))); } + /// + /// return true when errors contain HelpXXXError + /// + public static bool IsHelp (this IEnumerable errs) + { + if (errs.Any(x=>x.Tag == ErrorType.HelpRequestedError || + x.Tag == ErrorType.HelpVerbRequestedError)) + return true; + //when AutoHelp=false in parser, help is disabled and Parser raise UnknownOptionError + if( errs.Any(x=> (x is UnknownOptionError ee ? ee.Token:"") == "help")) + return true; + return false; + } + + /// + /// return true when errors contain VersionXXXError + /// + public static bool IsVersion (this IEnumerable errs) + { + if (errs.Any(x=>x.Tag == ErrorType.VersionRequestedError )) + return true; + //when AutoVersion=false in parser, Version is disabled and Parser raise UnknownOptionError + if( errs.Any(x=> (x is UnknownOptionError ee ? ee.Token:"") == "version")) + return true; + return false; + } } } diff --git a/src/CommandLine/Text/HelpText.cs b/src/CommandLine/Text/HelpText.cs index 575c6fbc..2d310191 100644 --- a/src/CommandLine/Text/HelpText.cs +++ b/src/CommandLine/Text/HelpText.cs @@ -269,11 +269,13 @@ public static HelpText AutoBuild( var errors = Enumerable.Empty(); + if (onError != null && parserResult.Tag == ParserResultType.NotParsed) { errors = ((NotParsed)parserResult).Errors; - - if (errors.OnlyMeaningfulOnes().Any()) + if (errors.IsHelp()) + auto = onError(auto); + else if (errors.OnlyMeaningfulOnes().Any()) auto = onError(auto); } diff --git a/tests/CommandLine.Tests/Unit/Text/HelpTextAutoBuildFix.cs b/tests/CommandLine.Tests/Unit/Text/HelpTextAutoBuildFix.cs new file mode 100644 index 00000000..91c5b52e --- /dev/null +++ b/tests/CommandLine.Tests/Unit/Text/HelpTextAutoBuildFix.cs @@ -0,0 +1,164 @@ +using CommandLine.Tests.Fakes; +using CommandLine.Text; +using FluentAssertions; +using Xunit; + +namespace CommandLine.Tests.Unit.Text +{ + public class HelpTextTests2 + { + [Fact] + public static void error_ishelp() + { + // Fixture setup + // Exercize system + var parser = new Parser(x => x.HelpWriter = null); + var result = parser.ParseArguments(new[]{"--help"}); + + result .WithNotParsed(errs => + { + errs.IsHelp().Should().BeTrue(); + errs.IsVersion().Should().BeFalse(); + }); + } + [Fact] + public static void error_isVersion() + { + // Fixture setup + // Exercize system + var parser = new Parser(x => x.HelpWriter = null); + var result = parser.ParseArguments(new[]{"--version"}); + + result .WithNotParsed(errs => + { + errs.IsHelp().Should().BeFalse(); + errs.IsVersion().Should().BeTrue(); + }); + } + + [Fact] + public static void custom_helptext_with_AdditionalNewLineAfterOption_false() + { + // Fixture setup + // Exercize system + var parser = new Parser(x => x.HelpWriter = null); + var result = parser.ParseArguments(new[]{"--help"}); + + result .WithNotParsed(errs => + { + + var sut = HelpText.AutoBuild(result, + h => + { + h.AdditionalNewLineAfterOption = false; + return h; + } + , e => e); + //Assert + var expected = new[] + { + " --help Display this help screen.", + " --version Display version information." + }; + var lines = sut.ToString().ToLines(); + lines.Should().ContainInOrder(expected); + }); + } + + [Fact] + public static void custom_helptext_with_AdditionalNewLineAfterOption_true() + { + // Fixture setup + // Exercize system + var parser = new Parser(x => x.HelpWriter = null); + var result = parser.ParseArguments(new[]{"--help"}); + + result .WithNotParsed(errs => + { + + var sut = HelpText.AutoBuild(result, + h =>h //AdditionalNewLineAfterOption =true by default + , e => e); + + //Assert + var expected = new[] + { + string.Empty, + " --help Display this help screen.", + string.Empty, + " --version Display version information." + }; + var lines = sut.ToString().ToLines(); + lines.Should().ContainInOrder(expected); + }); + } + + + [Fact] + public static void custom_helptext_with_parser_autohelp_false_and_AdditionalNewLineAfterOption_false() + { + // Fixture setup + // Exercize system + var parser = new Parser(x => + { + x.HelpWriter = null; + x.AutoHelp=false; + //x.AutoVersion=false; + }); + var result = parser.ParseArguments(new[]{"--help"}); + //you could generate help even parser.AutoHelp is disabled + result .WithNotParsed(errs => + { + errs.IsHelp().Should().BeTrue(); + var sut = HelpText.AutoBuild(result, + h => + { + h.AdditionalNewLineAfterOption = false; + return h; + } + , e => e); + + //Assert + var expected = new[] + { + " --help Display this help screen.", + " --version Display version information." + }; + var lines = sut.ToString().ToLines(); + lines.Should().ContainInOrder(expected); + }); + } + + [Fact] + public static void custom_helptext_with_autohelp_false() + { + // Fixture setup + // Exercize system + var parser = new Parser(x => + { + x.HelpWriter = null; + x.AutoHelp=false; + //x.AutoVersion=false; + }); + var result = parser.ParseArguments(new[]{"--help"}); + + result .WithNotParsed(errs => + { + errs.IsHelp().Should().BeTrue(); + var sut = HelpText.AutoBuild(result, + h =>h,e => e); + + //Assert + var expected = new[] + { + string.Empty, + " --help Display this help screen.", + string.Empty, + " --version Display version information." + }; + var lines = sut.ToString().ToLines(); + lines.Should().ContainInOrder(expected); + }); + } + } +} From 1de518f86ebe4f34ba8782ae2d85e630ca03aa8b Mon Sep 17 00:00:00 2001 From: "Moh.Hassan" Date: Thu, 4 Jul 2019 03:04:39 +0200 Subject: [PATCH 2/4] move IsHelp/Isversion to separate file with scope public --- src/CommandLine/ErrorExtensions.cs | 28 +-- src/CommandLine/HelpTextExtensions.cs | 35 ++++ .../Unit/Text/HelpTextAutoBuildFix.cs | 193 ++++++------------ 3 files changed, 97 insertions(+), 159 deletions(-) create mode 100644 src/CommandLine/HelpTextExtensions.cs diff --git a/src/CommandLine/ErrorExtensions.cs b/src/CommandLine/ErrorExtensions.cs index 43b7cfd0..edd03478 100644 --- a/src/CommandLine/ErrorExtensions.cs +++ b/src/CommandLine/ErrorExtensions.cs @@ -1,6 +1,5 @@ // Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information. -using System; using System.Collections.Generic; using System.Linq; using CommandLine.Core; @@ -24,31 +23,6 @@ public static IEnumerable OnlyMeaningfulOnes(this IEnumerable erro .Where(e => !(e.Tag == ErrorType.UnknownOptionError && ((UnknownOptionError)e).Token.EqualsOrdinalIgnoreCase("help"))); } - /// - /// return true when errors contain HelpXXXError - /// - public static bool IsHelp (this IEnumerable errs) - { - if (errs.Any(x=>x.Tag == ErrorType.HelpRequestedError || - x.Tag == ErrorType.HelpVerbRequestedError)) - return true; - //when AutoHelp=false in parser, help is disabled and Parser raise UnknownOptionError - if( errs.Any(x=> (x is UnknownOptionError ee ? ee.Token:"") == "help")) - return true; - return false; - } - - /// - /// return true when errors contain VersionXXXError - /// - public static bool IsVersion (this IEnumerable errs) - { - if (errs.Any(x=>x.Tag == ErrorType.VersionRequestedError )) - return true; - //when AutoVersion=false in parser, Version is disabled and Parser raise UnknownOptionError - if( errs.Any(x=> (x is UnknownOptionError ee ? ee.Token:"") == "version")) - return true; - return false; - } + } } diff --git a/src/CommandLine/HelpTextExtensions.cs b/src/CommandLine/HelpTextExtensions.cs new file mode 100644 index 00000000..88bcdb18 --- /dev/null +++ b/src/CommandLine/HelpTextExtensions.cs @@ -0,0 +1,35 @@ +// Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information. + +using System.Collections.Generic; +using System.Linq; + +namespace CommandLine +{ + public static class HelpTextExtensions + { + /// + /// return true when errors contain HelpXXXError + /// + public static bool IsHelp(this IEnumerable errs) + { + if (errs.Any(x => x.Tag == ErrorType.HelpRequestedError || + x.Tag == ErrorType.HelpVerbRequestedError)) + return true; + //when AutoHelp=false in parser, help is disabled and Parser raise UnknownOptionError + return errs.Any(x => (x is UnknownOptionError ee ? ee.Token : "") == "help"); + } + + /// + /// return true when errors contain VersionXXXError + /// + public static bool IsVersion(this IEnumerable errs) + { + if (errs.Any(x => x.Tag == ErrorType.VersionRequestedError)) + return true; + //when AutoVersion=false in parser, Version is disabled and Parser raise UnknownOptionError + return errs.Any(x => (x is UnknownOptionError ee ? ee.Token : "") == "version"); + } + } +} + + diff --git a/tests/CommandLine.Tests/Unit/Text/HelpTextAutoBuildFix.cs b/tests/CommandLine.Tests/Unit/Text/HelpTextAutoBuildFix.cs index 91c5b52e..4b78aa13 100644 --- a/tests/CommandLine.Tests/Unit/Text/HelpTextAutoBuildFix.cs +++ b/tests/CommandLine.Tests/Unit/Text/HelpTextAutoBuildFix.cs @@ -1,164 +1,93 @@ -using CommandLine.Tests.Fakes; +using System; +using System.Linq; +using CommandLine.Tests.Fakes; using CommandLine.Text; using FluentAssertions; using Xunit; namespace CommandLine.Tests.Unit.Text { - public class HelpTextTests2 + public class HelpTextAutoBuildFix { - [Fact] - public static void error_ishelp() - { - // Fixture setup - // Exercize system - var parser = new Parser(x => x.HelpWriter = null); - var result = parser.ParseArguments(new[]{"--help"}); - result .WithNotParsed(errs => - { - errs.IsHelp().Should().BeTrue(); - errs.IsVersion().Should().BeFalse(); - }); - } [Fact] - public static void error_isVersion() + public void HelpText_wit_AdditionalNewLineAfterOption_true_should_have_newline() { // Fixture setup - // Exercize system - var parser = new Parser(x => x.HelpWriter = null); - var result = parser.ParseArguments(new[]{"--version"}); + // Exercize system + var sut = new HelpText { AdditionalNewLineAfterOption = true } + .AddOptions(new NotParsed(TypeInfo.Create(typeof(Simple_Options)), + Enumerable.Empty())); - result .WithNotParsed(errs => - { - errs.IsHelp().Should().BeFalse(); - errs.IsVersion().Should().BeTrue(); - }); - } - - [Fact] - public static void custom_helptext_with_AdditionalNewLineAfterOption_false() - { - // Fixture setup - // Exercize system - var parser = new Parser(x => x.HelpWriter = null); - var result = parser.ParseArguments(new[]{"--help"}); + // Verify outcome - result .WithNotParsed(errs => - { - - var sut = HelpText.AutoBuild(result, - h => - { - h.AdditionalNewLineAfterOption = false; - return h; - } - , e => e); - //Assert - var expected = new[] - { - " --help Display this help screen.", - " --version Display version information." - }; - var lines = sut.ToString().ToLines(); - lines.Should().ContainInOrder(expected); - }); + var lines = sut.ToString().ToLines(); + + lines[2].Should().BeEquivalentTo(" stringvalue Define a string value here."); + lines[3].Should().BeEquivalentTo(String.Empty); + lines[4].Should().BeEquivalentTo(" s, shortandlong Example with both short and long name."); + lines[5].Should().BeEquivalentTo(String.Empty); + lines[7].Should().BeEquivalentTo(String.Empty); + lines[9].Should().BeEquivalentTo(String.Empty); + lines[11].Should().BeEquivalentTo(String.Empty); + lines[13].Should().BeEquivalentTo(String.Empty); + lines[14].Should().BeEquivalentTo(" value pos. 0 Define a long value here."); + // Teardown } [Fact] - public static void custom_helptext_with_AdditionalNewLineAfterOption_true() + public void HelpText_wit_AdditionalNewLineAfterOption_false_should_not_have_newline() { // Fixture setup - // Exercize system - var parser = new Parser(x => x.HelpWriter = null); - var result = parser.ParseArguments(new[]{"--help"}); + // Exercize system + var sut = new HelpText { AdditionalNewLineAfterOption = false } + .AddOptions(new NotParsed(TypeInfo.Create(typeof(Simple_Options)), + Enumerable.Empty())); - result .WithNotParsed(errs => - { - - var sut = HelpText.AutoBuild(result, - h =>h //AdditionalNewLineAfterOption =true by default - , e => e); - - //Assert - var expected = new[] - { - string.Empty, - " --help Display this help screen.", - string.Empty, - " --version Display version information." - }; - var lines = sut.ToString().ToLines(); - lines.Should().ContainInOrder(expected); - }); - } + // Verify outcome + + var lines = sut.ToString().ToLines(); + + lines[2].Should().BeEquivalentTo(" stringvalue Define a string value here."); - + lines[3].Should().BeEquivalentTo(" s, shortandlong Example with both short and long name."); + lines[8].Should().BeEquivalentTo(" value pos. 0 Define a long value here."); + // Teardown + } [Fact] - public static void custom_helptext_with_parser_autohelp_false_and_AdditionalNewLineAfterOption_false() + public void HelpText_wit_by_default_should_include_help_version_option() { // Fixture setup - // Exercize system - var parser = new Parser(x => - { - x.HelpWriter = null; - x.AutoHelp=false; - //x.AutoVersion=false; - }); - var result = parser.ParseArguments(new[]{"--help"}); - //you could generate help even parser.AutoHelp is disabled - result .WithNotParsed(errs => - { - errs.IsHelp().Should().BeTrue(); - var sut = HelpText.AutoBuild(result, - h => - { - h.AdditionalNewLineAfterOption = false; - return h; - } - , e => e); - - //Assert - var expected = new[] - { - " --help Display this help screen.", - " --version Display version information." - }; - var lines = sut.ToString().ToLines(); - lines.Should().ContainInOrder(expected); - }); + // Exercize system + var sut = new HelpText () + .AddOptions(new NotParsed(TypeInfo.Create(typeof(Simple_Options)), + Enumerable.Empty())); + + // Verify outcome + + var lines = sut.ToString().ToNotEmptyLines(); + lines.Should().HaveCount(c => c ==7); + lines.Should().Contain(" help Display more information on a specific command."); + lines.Should().Contain(" version Display version information."); + // Teardown } [Fact] - public static void custom_helptext_with_autohelp_false() + public void HelpText_wit_AutoHelp_false_should_hide_help_option() { // Fixture setup - // Exercize system - var parser = new Parser(x => - { - x.HelpWriter = null; - x.AutoHelp=false; - //x.AutoVersion=false; - }); - var result = parser.ParseArguments(new[]{"--help"}); + // Exercize system + var sut = new HelpText { AutoHelp = false,AutoVersion = false} + .AddOptions(new NotParsed(TypeInfo.Create(typeof(Simple_Options)), + Enumerable.Empty())); + + // Verify outcome - result .WithNotParsed(errs => - { - errs.IsHelp().Should().BeTrue(); - var sut = HelpText.AutoBuild(result, - h =>h,e => e); - - //Assert - var expected = new[] - { - string.Empty, - " --help Display this help screen.", - string.Empty, - " --version Display version information." - }; - var lines = sut.ToString().ToLines(); - lines.Should().ContainInOrder(expected); - }); + var lines = sut.ToString().ToNotEmptyLines(); + lines.Should().HaveCount(c => c ==5); + lines.Should().NotContain(" help Display more information on a specific command."); + lines.Should().NotContain(" version Display version information."); + // Teardown } } } From d69be74fbd9854c44404ad1bbf13317bcb177795 Mon Sep 17 00:00:00 2001 From: Mohamed Hassan Date: Wed, 10 Jul 2019 13:39:41 +0200 Subject: [PATCH 3/4] Simplify if-else clause --- src/CommandLine/Text/HelpText.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/CommandLine/Text/HelpText.cs b/src/CommandLine/Text/HelpText.cs index 2d310191..1306e969 100644 --- a/src/CommandLine/Text/HelpText.cs +++ b/src/CommandLine/Text/HelpText.cs @@ -273,9 +273,7 @@ public static HelpText AutoBuild( if (onError != null && parserResult.Tag == ParserResultType.NotParsed) { errors = ((NotParsed)parserResult).Errors; - if (errors.IsHelp()) - auto = onError(auto); - else if (errors.OnlyMeaningfulOnes().Any()) + if (errors.IsHelp() || errors.OnlyMeaningfulOnes().Any()) auto = onError(auto); } From 4703c74e0ee25b8b364918f0bc5300cd8fb98e03 Mon Sep 17 00:00:00 2001 From: "Moh.Hassan" Date: Thu, 11 Jul 2019 22:10:42 +0200 Subject: [PATCH 4/4] Add errs.Output extension method to auto direct help/version to Console.Out and errors to Console.Error --- src/CommandLine/HelpTextExtensions.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/CommandLine/HelpTextExtensions.cs b/src/CommandLine/HelpTextExtensions.cs index 88bcdb18..d0106de8 100644 --- a/src/CommandLine/HelpTextExtensions.cs +++ b/src/CommandLine/HelpTextExtensions.cs @@ -1,5 +1,6 @@ // Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information. - +using System; +using System.IO; using System.Collections.Generic; using System.Linq; @@ -28,6 +29,15 @@ public static bool IsVersion(this IEnumerable errs) return true; //when AutoVersion=false in parser, Version is disabled and Parser raise UnknownOptionError return errs.Any(x => (x is UnknownOptionError ee ? ee.Token : "") == "version"); + } + /// + /// redirect errs to Console.Error, and to Console.Out for help/version error + /// + public static TextWriter Output(this IEnumerable errs) + { + if (errs.IsHelp() || errs.IsVersion()) + return Console.Out; + return Console.Error; } } }