diff --git a/src/CommandLine/Core/ArgumentsExtensions.cs b/src/CommandLine/Core/ArgumentsExtensions.cs index f4678d7f..018a3c42 100644 --- a/src/CommandLine/Core/ArgumentsExtensions.cs +++ b/src/CommandLine/Core/ArgumentsExtensions.cs @@ -10,9 +10,9 @@ namespace CommandLine.Core static class ArgumentsExtensions { public static IEnumerable Preprocess( - this IEnumerable arguments, + this IEnumerable arguments, IEnumerable< - Func, IEnumerable> + Func, IEnumerable> > preprocessorLookup) { return preprocessorLookup.TryHead().MapValueOrDefault( diff --git a/src/CommandLine/Core/InstanceBuilder.cs b/src/CommandLine/Core/InstanceBuilder.cs index ffd6250b..03f18373 100644 --- a/src/CommandLine/Core/InstanceBuilder.cs +++ b/src/CommandLine/Core/InstanceBuilder.cs @@ -32,8 +32,10 @@ public static ParserResult Build( ignoreValueCase, parsingCulture, autoHelp, + false, autoVersion, false, + false, nonFatalErrors); } @@ -45,9 +47,12 @@ public static ParserResult Build( bool ignoreValueCase, CultureInfo parsingCulture, bool autoHelp, + bool autoHelpShortName, bool autoVersion, + bool autoVersionShortName, bool allowMultiInstance, - IEnumerable nonFatalErrors) { + IEnumerable nonFatalErrors) + { var typeInfo = factory.MapValueOrDefault(f => f().GetType(), typeof(T)); var specProps = typeInfo.GetSpecifications(pi => SpecificationProperty.Create( @@ -56,7 +61,9 @@ public static ParserResult Build( var specs = from pt in specProps select pt.Specification; - var optionSpecs = specs + var autoSpecs = AddAutoSpecs(specs, nameComparer, autoHelp, autoHelpShortName, autoVersion, autoVersionShortName); + + var optionSpecs = autoSpecs .ThrowingValidate(SpecificationGuards.Lookup) .OfType() .Memoize(); @@ -71,12 +78,13 @@ public static ParserResult Build( errs => new NotParsed(makeDefault().GetType().ToTypeInfo(), errs); var argumentsList = arguments.Memoize(); - Func> buildUp = () => - { - var tokenizerResult = tokenizer(argumentsList, optionSpecs); - var tokens = tokenizerResult.SucceededWith().Memoize(); + var tokenizerResult = tokenizer(argumentsList, optionSpecs); + var tokens = tokenizerResult.SucceededWith().Memoize(); + + Func> buildUp = () => + { var partitions = TokenPartitioner.Partition( tokens, name => TypeLookup.FindTypeDescriptorAndSibling(name, optionSpecs, nameComparer)); @@ -136,8 +144,8 @@ public static ParserResult Build( }; var preprocessorErrors = ( - argumentsList.Any() - ? arguments.Preprocess(PreprocessorGuards.Lookup(nameComparer, autoHelp, autoVersion)) + tokens.Any() + ? tokens.Preprocess(PreprocessorGuards.Lookup(nameComparer, autoHelp, autoHelpShortName, autoVersion, autoVersionShortName)) : Enumerable.Empty() ).Memoize(); @@ -150,6 +158,26 @@ public static ParserResult Build( return result; } + private static IEnumerable AddAutoSpecs(IEnumerable specs, StringComparer nameComparer, bool autoHelp, bool autoHelpShortName, bool autoVersion, bool autoVersionShortName) + { + var optionSpecs = specs.OfType().Memoize(); + bool useHelpShortName = autoHelpShortName && !(optionSpecs.Any(spec => nameComparer.Equals(spec.ShortName, "h"))); + bool useVersionShortName = autoVersionShortName && !(optionSpecs.Any(spec => nameComparer.Equals(spec.ShortName, "V"))); // Uppercase V + bool addAutoHelp = autoHelp && !(optionSpecs.Any(spec => nameComparer.Equals(spec.LongName, "help"))); + bool addAutoVersion = autoVersion && !(optionSpecs.Any(spec => nameComparer.Equals(spec.LongName, "version"))); + + var autoSpecs = new List(2); + if (addAutoHelp) + { + autoSpecs.Add(OptionSpecification.NewSwitch(useHelpShortName ? "h" : String.Empty, "help", false, "Display this help screen.", String.Empty)); + } + if (addAutoVersion) + { + autoSpecs.Add(OptionSpecification.NewSwitch(useVersionShortName ? "V" : String.Empty, "version", false, "Display version information.", String.Empty)); + } + return specs.Concat(autoSpecs); + } + private static T BuildMutable(Maybe> factory, IEnumerable specPropsWithValue, List setPropertyErrors ) { var mutable = factory.MapValueOrDefault(f => f(), () => Activator.CreateInstance()); diff --git a/src/CommandLine/Core/InstanceChooser.cs b/src/CommandLine/Core/InstanceChooser.cs index 72307bf2..2769b9f9 100644 --- a/src/CommandLine/Core/InstanceChooser.cs +++ b/src/CommandLine/Core/InstanceChooser.cs @@ -31,8 +31,10 @@ public static ParserResult Choose( ignoreValueCase, parsingCulture, autoHelp, + false, autoVersion, false, + false, nonFatalErrors); } @@ -44,7 +46,9 @@ public static ParserResult Choose( bool ignoreValueCase, CultureInfo parsingCulture, bool autoHelp, + bool autoHelpShortName, bool autoVersion, + bool autoVersionShortName, bool allowMultiInstance, IEnumerable nonFatalErrors) { @@ -65,19 +69,19 @@ bool preprocCompare(string command) => nameComparer.Equals(command, firstArg) || nameComparer.Equals(string.Concat("--", command), firstArg); - return (autoHelp && preprocCompare("help")) + return (autoHelp && preprocCompare("help")) || (autoHelp && autoHelpShortName && nameComparer.Equals("-h", firstArg)) ? MakeNotParsed(types, MakeHelpVerbRequestedError(verbs, arguments.Skip(1).FirstOrDefault() ?? string.Empty, nameComparer)) - : (autoVersion && preprocCompare("version")) + : (autoVersion && preprocCompare("version")) || (autoVersion && autoVersionShortName && nameComparer.Equals("-V", firstArg)) ? MakeNotParsed(types, new VersionRequestedError()) - : MatchVerb(tokenizer, verbs, defaultVerb, arguments, nameComparer, ignoreValueCase, parsingCulture, autoHelp, autoVersion, allowMultiInstance, nonFatalErrors); + : MatchVerb(tokenizer, verbs, defaultVerb, arguments, nameComparer, ignoreValueCase, parsingCulture, autoHelp, autoHelpShortName, autoVersion, autoVersionShortName, allowMultiInstance, nonFatalErrors); } return arguments.Any() ? choose() : (defaultVerbCount == 1 - ? MatchDefaultVerb(tokenizer, verbs, defaultVerb, arguments, nameComparer, ignoreValueCase, parsingCulture, autoHelp, autoVersion, nonFatalErrors) + ? MatchDefaultVerb(tokenizer, verbs, defaultVerb, arguments, nameComparer, ignoreValueCase, parsingCulture, autoHelp, autoHelpShortName, autoVersion, autoVersionShortName, allowMultiInstance, nonFatalErrors) : MakeNotParsed(types, new NoVerbSelectedError())); } @@ -90,7 +94,10 @@ private static ParserResult MatchDefaultVerb( bool ignoreValueCase, CultureInfo parsingCulture, bool autoHelp, + bool autoHelpShortName, bool autoVersion, + bool autoVersionShortName, + bool allowMultiInstance, IEnumerable nonFatalErrors) { return !(defaultVerb is null) @@ -102,7 +109,10 @@ private static ParserResult MatchDefaultVerb( ignoreValueCase, parsingCulture, autoHelp, + autoHelpShortName, autoVersion, + autoVersionShortName, + allowMultiInstance, nonFatalErrors) : MakeNotParsed(verbs.Select(v => v.Item2), new BadVerbSelectedError(arguments.First())); } @@ -116,7 +126,9 @@ private static ParserResult MatchVerb( bool ignoreValueCase, CultureInfo parsingCulture, bool autoHelp, + bool autoHelpShortName, bool autoVersion, + bool autoVersionShortName, bool allowMultiInstance, IEnumerable nonFatalErrors) { @@ -129,7 +141,7 @@ private static ParserResult MatchVerb( if (verbUsed == default) { - return MatchDefaultVerb(tokenizer, verbs, defaultVerb, arguments, nameComparer, ignoreValueCase, parsingCulture, autoHelp, autoVersion, nonFatalErrors); + return MatchDefaultVerb(tokenizer, verbs, defaultVerb, arguments, nameComparer, ignoreValueCase, parsingCulture, autoHelp, autoHelpShortName, autoVersion, autoVersionShortName, allowMultiInstance, nonFatalErrors); } return InstanceBuilder.Build( Maybe.Just>( @@ -140,7 +152,9 @@ private static ParserResult MatchVerb( ignoreValueCase, parsingCulture, autoHelp, + autoHelpShortName, autoVersion, + autoVersionShortName, allowMultiInstance, nonFatalErrors); } diff --git a/src/CommandLine/Core/PreprocessorGuards.cs b/src/CommandLine/Core/PreprocessorGuards.cs index 8d6fb5be..1a8ff07f 100644 --- a/src/CommandLine/Core/PreprocessorGuards.cs +++ b/src/CommandLine/Core/PreprocessorGuards.cs @@ -8,31 +8,53 @@ namespace CommandLine.Core { static class PreprocessorGuards { - public static IEnumerable, IEnumerable>> - Lookup(StringComparer nameComparer, bool autoHelp, bool autoVersion) + public static IEnumerable, IEnumerable>> + Lookup(StringComparer nameComparer, bool autoHelp, bool autoHelpShortName, bool autoVersion, bool autoVersionShortName) { - var list = new List, IEnumerable>>(); + var list = new List, IEnumerable>>(); if (autoHelp) list.Add(HelpCommand(nameComparer)); + if (autoHelp && autoHelpShortName) + list.Add(ShortHelpCommand(nameComparer)); if (autoVersion) list.Add(VersionCommand(nameComparer)); + if (autoVersion && autoVersionShortName) + list.Add(ShortVersionCommand(nameComparer)); return list; } - public static Func, IEnumerable> HelpCommand(StringComparer nameComparer) + public static Func, IEnumerable> HelpCommand(StringComparer nameComparer) { return arguments => - nameComparer.Equals("--help", arguments.First()) + arguments.OfType().Any(arg => nameComparer.Equals("help", arg.Text)) ? new Error[] { new HelpRequestedError() } : Enumerable.Empty(); } - public static Func, IEnumerable> VersionCommand(StringComparer nameComparer) + public static Func, IEnumerable> ShortHelpCommand(StringComparer nameComparer) { return arguments => - nameComparer.Equals("--version", arguments.First()) + arguments.OfType().Any(arg => nameComparer.Equals("h", arg.Text)) + ? new Error[] { new HelpRequestedError() } + : Enumerable.Empty(); + } + + public static Func, IEnumerable> VersionCommand(StringComparer nameComparer) + { + return + arguments => + arguments.OfType().Any(arg => nameComparer.Equals("version", arg.Text)) + ? new Error[] { new VersionRequestedError() } + : Enumerable.Empty(); + } + + public static Func, IEnumerable> ShortVersionCommand(StringComparer nameComparer) + { + return + arguments => + arguments.OfType().Any(arg => nameComparer.Equals("V", arg.Text)) // Uppercase V ? new Error[] { new VersionRequestedError() } : Enumerable.Empty(); } diff --git a/src/CommandLine/ErrorExtensions.cs b/src/CommandLine/ErrorExtensions.cs index edd03478..28d30c30 100644 --- a/src/CommandLine/ErrorExtensions.cs +++ b/src/CommandLine/ErrorExtensions.cs @@ -19,9 +19,7 @@ public static ParserResult ToParserResult(this IEnumerable errors, public static IEnumerable OnlyMeaningfulOnes(this IEnumerable errors) { return errors - .Where(e => !e.StopsProcessing) - .Where(e => !(e.Tag == ErrorType.UnknownOptionError - && ((UnknownOptionError)e).Token.EqualsOrdinalIgnoreCase("help"))); + .Where(e => !e.StopsProcessing); } } diff --git a/src/CommandLine/Parser.cs b/src/CommandLine/Parser.cs index 10c9b4e1..954ccefd 100644 --- a/src/CommandLine/Parser.cs +++ b/src/CommandLine/Parser.cs @@ -100,7 +100,9 @@ public ParserResult ParseArguments(IEnumerable args) settings.CaseInsensitiveEnumValues, settings.ParsingCulture, settings.AutoHelp, + settings.AutoHelpShortName, settings.AutoVersion, + settings.AutoVersionShortName, settings.AllowMultiInstance, HandleUnknownArguments(settings.IgnoreUnknownArguments)), settings); @@ -131,7 +133,9 @@ public ParserResult ParseArguments(Func factory, IEnumerable ar settings.CaseInsensitiveEnumValues, settings.ParsingCulture, settings.AutoHelp, + settings.AutoHelpShortName, settings.AutoVersion, + settings.AutoVersionShortName, settings.AllowMultiInstance, HandleUnknownArguments(settings.IgnoreUnknownArguments)), settings); @@ -164,7 +168,9 @@ public ParserResult ParseArguments(IEnumerable args, params Type settings.CaseInsensitiveEnumValues, settings.ParsingCulture, settings.AutoHelp, + settings.AutoHelpShortName, settings.AutoVersion, + settings.AutoVersionShortName, settings.AllowMultiInstance, HandleUnknownArguments(settings.IgnoreUnknownArguments)), settings); diff --git a/src/CommandLine/ParserSettings.cs b/src/CommandLine/ParserSettings.cs index 95a4cd81..de2e9977 100644 --- a/src/CommandLine/ParserSettings.cs +++ b/src/CommandLine/ParserSettings.cs @@ -21,7 +21,9 @@ public class ParserSettings : IDisposable private TextWriter helpWriter; private bool ignoreUnknownArguments; private bool autoHelp; + private bool autoHelpShortName; private bool autoVersion; + private bool autoVersionShortName; private CultureInfo parsingCulture; private bool enableDashDash; private int maximumDisplayWidth; @@ -35,7 +37,9 @@ public ParserSettings() caseSensitive = true; caseInsensitiveEnumValues = false; autoHelp = true; + autoHelpShortName = false; autoVersion = true; + autoVersionShortName = false; parsingCulture = CultureInfo.InvariantCulture; maximumDisplayWidth = GetWindowWidth(); } @@ -147,6 +151,15 @@ public bool AutoHelp set { PopsicleSetter.Set(Consumed, ref autoHelp, value); } } + /// + /// Gets or sets a value indicating whether implicit option or verb 'help' should have the shortname '-h'. + /// + public bool AutoHelpShortName + { + get { return autoHelpShortName; } + set { PopsicleSetter.Set(Consumed, ref autoHelpShortName, value); } + } + /// /// Gets or sets a value indicating whether implicit option or verb 'version' should be supported. /// @@ -156,6 +169,15 @@ public bool AutoVersion set { PopsicleSetter.Set(Consumed, ref autoVersion, value); } } + /// + /// Gets or sets a value indicating whether implicit option or verb 'help' should have the shortname '-h'. + /// + public bool AutoVersionShortName + { + get { return autoVersionShortName; } + set { PopsicleSetter.Set(Consumed, ref autoVersionShortName, value); } + } + /// /// Gets or sets a value indicating whether enable double dash '--' syntax, /// that forces parsing of all subsequent tokens as values. diff --git a/tests/CommandLine.Tests/Unit/AutoHelpTests.cs b/tests/CommandLine.Tests/Unit/AutoHelpTests.cs new file mode 100644 index 00000000..89bc4237 --- /dev/null +++ b/tests/CommandLine.Tests/Unit/AutoHelpTests.cs @@ -0,0 +1,441 @@ +using System; +using Xunit; +using FluentAssertions; +using CommandLine.Core; +using CommandLine.Tests.Fakes; +using System.IO; +using System.Linq; +using System.Collections.Generic; + +namespace CommandLine.Tests.Unit +{ + public class AutoHelpTests + { + public AutoHelpTests() + { + } + + public static object[][] ValidArgsData = new [] + { + new [] { "--help" }, + new [] { "--help", "256" }, + new [] { "--help", "--stringvalue", "foo" }, + new [] { "--help", "--stringvalue=foo" }, + new [] { "--stringvalue", "foo", "--help" }, + new [] { "--stringvalue=foo", "--help" }, + new [] { "--help", "--stringvalue", "foo", "-x" }, + new [] { "--help", "--stringvalue=foo", "-x" }, + new [] { "--stringvalue", "foo", "--help", "-x" }, + new [] { "--stringvalue=foo", "--help", "-x" }, + new [] { "--stringvalue", "foo", "-x", "256", "--help" }, + new [] { "--stringvalue=foo", "-x", "256", "--help" }, + new [] { "--stringvalue", "foo", "--help", "-x", "256" }, + new [] { "--stringvalue=foo", "--help", "-x", "256" }, + new [] { "--help", "--stringvalue", "foo", "-x", "256" }, + new [] { "--help", "--stringvalue=foo", "-x", "256" }, + }; + + public static object[][] InvalidArgsData = new [] + { + new [] { "--help", "foo" }, + new [] { "--help", "-s" }, + new [] { "--help", "-i", "foo" }, + new [] {"--help", "--invalid-switch", "foo" }, + new [] {"--invalid-switch", "foo", "--help" }, + new [] {"--invalid-switch", "--help", "foo" }, + }; + + // This test requires the GetoptMode feature + // public static object[][] ConsumedDashDashHelpValidArgsData = new [] + // { + // new [] { "--stringvalue", "--help" }, + // new [] { "--stringvalue=--help" }, + // new [] { "--stringvalue", "--help", "-s", "--help" }, + // new [] { "--stringvalue=--help", "-s", "--help" }, + // new [] { "--stringvalue", "--help", "-s--help" }, + // new [] { "--stringvalue=--help", "-s--help" }, + // }; + + public static object[][] MixOfConsumedAndUnconsumedDashDashHelpValidArgsData = new [] + { + new [] { "--stringvalue", "--help", "--help" }, + new [] { "--help", "--stringvalue", "--help" }, + new [] { "--stringvalue=--help", "--help" }, + new [] { "--help", "--stringvalue=--help" }, + new [] { "--stringvalue", "--help", "-s", "--help", "--help" }, + new [] { "--stringvalue", "--help", "--help", "-s", "--help" }, + new [] { "--help", "--stringvalue", "--help", "-s", "--help" }, + new [] { "--stringvalue=--help", "-s", "--help", "--help" }, + new [] { "--stringvalue=--help", "--help", "-s", "--help" }, + new [] { "--help", "--stringvalue=--help", "-s", "--help" }, + new [] { "--stringvalue", "--help", "-s--help", "--help" }, + new [] { "--stringvalue", "--help", "--help", "-s--help", "--help" }, + new [] { "--help", "--stringvalue", "--help", "-s--help" }, + new [] { "--stringvalue=--help", "-s--help", "--help" }, + new [] { "--stringvalue=--help", "--help", "-s--help" }, + new [] { "--help", "--stringvalue=--help", "-s--help" }, + }; + + public static object[][] ConsumedDashDashHelpInvalidArgsData = new [] + { + new [] { "--stringvalue", "--help", "foo" }, + new [] { "-s", "--help", "--stringvalue" }, + new [] { "-s", "--help", "-i", "foo" }, + new [] { "--stringvalue", "--help", "--invalid-switch", "256" }, + new [] { "--stringvalue=--help", "--invalid-switch", "256" }, + new [] { "--invalid-switch", "-s", "--help" }, + }; + + public static IEnumerable ConvertDataToShortOption(object[][] data, string search, string replacement) + { + foreach (object[] row in data) + { + var strings = row as string[]; + if (strings != null) + { + yield return strings.Select(item => item.Replace(search, replacement)).ToArray(); + } + } + } + + [Theory] + [MemberData(nameof(ValidArgsData))] + public void Explicit_help_command_with_valid_args_produces_just_one_HelpRequestedError(params string[] args) + { + // Arrange + var help = new StringWriter(); + var sut = new Parser(config => { + config.AutoHelp = true; + config.HelpWriter = help; + }); + + // Act + var result = sut.ParseArguments(args); + + // Assert + result.Should().BeOfType>(); + result.As>().Errors.Should().HaveCount(x => x == 1); + result.As>().Errors.First().Should().BeOfType(); + } + + public static IEnumerable ValidArgsDataWithShortOption = + ConvertDataToShortOption(ValidArgsData, "--help", "-h"); + + [Theory] + [MemberData(nameof(ValidArgsDataWithShortOption))] + public void Explicit_help_command_with_valid_args_and_short_option_produces_just_one_HelpRequestedError(params string[] args) + { + // Arrange + var help = new StringWriter(); + var sut = new Parser(config => { + config.AutoHelp = true; + config.AutoHelpShortName = true; + config.HelpWriter = help; + }); + + // Act + var result = sut.ParseArguments(args); + + // Assert + result.Should().BeOfType>(); + result.As>().Errors.Should().HaveCount(x => x == 1); + result.As>().Errors.First().Should().BeOfType(); + } + + [Theory] + [MemberData(nameof(InvalidArgsData))] + public void Explicit_help_command_with_invalid_args_produces_just_one_HelpRequestedError(params string[] args) + { + // Arrange + var help = new StringWriter(); + var sut = new Parser(config => { + config.AutoHelp = true; + config.HelpWriter = help; + }); + + // Act + var result = sut.ParseArguments(args); + + // Assert + result.Should().BeOfType>(); + result.As>().Errors.Should().HaveCount(x => x == 1); + result.As>().Errors.First().Should().BeOfType(); + } + + public static IEnumerable InvalidArgsDataWithShortOption = + ConvertDataToShortOption(InvalidArgsData, "--help", "-h"); + + [Theory] + [MemberData(nameof(InvalidArgsDataWithShortOption))] + public void Explicit_help_command_with_invalid_args_and_short_option_produces_just_one_HelpRequestedError(params string[] args) + { + // Arrange + var help = new StringWriter(); + var sut = new Parser(config => { + config.AutoHelp = true; + config.AutoHelpShortName = true; + config.HelpWriter = help; + }); + + // Act + var result = sut.ParseArguments(args); + + // Assert + result.Should().BeOfType>(); + result.As>().Errors.Should().HaveCount(x => x == 1); + result.As>().Errors.First().Should().BeOfType(); + } + + // This test requires the GetoptMode feature + // [Theory] + // [MemberData(nameof(ConsumedDashDashHelpValidArgsData))] + // public void Dash_dash_help_in_a_string_value_does_not_produce_HelpRequestedError(params string[] args) + // { + // // Arrange + // var help = new StringWriter(); + // var sut = new Parser(config => { + // config.AutoHelp = true; + // config.HelpWriter = help; + // config.GetoptMode = true; + // }); + + // // Act + // var result = sut.ParseArguments(args); + + // // Assert + // // result.Should().BeOfType>(); + // // result.As>().Errors.Should().HaveCount(x => x == 1); + // // result.As>().Errors.First().Should().BeOfType(); + // result.Should().BeOfType>(); + // string stringValue = result.As>().Value.StringValue; + // string shortAndLong = result.As>().Value.ShortAndLong; + // stringValue.Should().Be("--help"); + // shortAndLong.Should().BeOneOf("--help", null, ""); + // } + + // public static IEnumerable ConsumedDashDashHelpValidArgsDataWithShortOption = + // ConvertDataToShortOption(ConsumedDashDashHelpValidArgsData, "--help", "-h"); + + // This test requires the GetoptMode feature + // [Theory] + // [MemberData(nameof(ConsumedDashDashHelpValidArgsDataWithShortOption))] + // public void Dash_dash_help_in_a_string_value_with_short_option_does_not_produce_HelpRequestedError(params string[] args) + // { + // // Arrange + // var help = new StringWriter(); + // var sut = new Parser(config => { + // config.AutoHelp = true; + // config.AutoHelpShortName = true; + // config.HelpWriter = help; + // config.GetoptMode = true; + // }); + + // // Act + // var result = sut.ParseArguments(args); + + // // Assert + // // result.Should().BeOfType>(); + // // result.As>().Errors.Should().HaveCount(x => x == 1); + // // result.As>().Errors.First().Should().BeOfType(); + // result.Should().BeOfType>(); + // string stringValue = result.As>().Value.StringValue; + // string shortAndLong = result.As>().Value.ShortAndLong; + // stringValue.Should().Be("-h"); + // shortAndLong.Should().BeOneOf("-h", null, ""); + // } + + // This test requires the GetoptMode feature + // public static IEnumerable ConsumedDashDashHelpValidArgsDataWithShortOptionInData = + // ConvertDataToShortOption(ConsumedDashDashHelpValidArgsData, "--help", "h"); + + // This test requires the GetoptMode feature + // [Theory] + // [MemberData(nameof(ConsumedDashDashHelpValidArgsDataWithShortOptionInData))] + // public void Dash_dash_help_in_a_string_value_with_short_option_in_data_does_not_produce_HelpRequestedError(params string[] args) + // { + // // Arrange + // var help = new StringWriter(); + // var sut = new Parser(config => { + // config.AutoHelp = true; + // config.AutoHelpShortName = true; + // config.HelpWriter = help; + // config.GetoptMode = true; + // }); + + // // Act + // var result = sut.ParseArguments(args); + + // // Assert + // // result.Should().BeOfType>(); + // // result.As>().Errors.Should().HaveCount(x => x == 1); + // // result.As>().Errors.First().Should().BeOfType(); + // result.Should().BeOfType>(); + // string stringValue = result.As>().Value.StringValue; + // string shortAndLong = result.As>().Value.ShortAndLong; + // stringValue.Should().Be("h"); + // shortAndLong.Should().BeOneOf("h", null, ""); + // } + + [Theory] + [MemberData(nameof(MixOfConsumedAndUnconsumedDashDashHelpValidArgsData))] + public void Explicit_help_command_mixed_with_some_consumed_args_produces_just_one_HelpRequestedError(params string[] args) + { + // Arrange + var help = new StringWriter(); + var sut = new Parser(config => { + config.AutoHelp = true; + config.HelpWriter = help; + }); + + // Act + var result = sut.ParseArguments(args); + + // Assert + result.Should().BeOfType>(); + result.As>().Errors.Should().HaveCount(x => x == 1); + result.As>().Errors.First().Should().BeOfType(); + } + + public static IEnumerable MixOfConsumedAndUnconsumedDashDashHelpValidArgsDataWithShortOption = + ConvertDataToShortOption(MixOfConsumedAndUnconsumedDashDashHelpValidArgsData, "--help", "-h"); + + [Theory] + [MemberData(nameof(MixOfConsumedAndUnconsumedDashDashHelpValidArgsDataWithShortOption))] + public void Explicit_short_help_command_mixed_with_some_consumed_args_produces_just_one_HelpRequestedError(params string[] args) + { + // Arrange + var help = new StringWriter(); + var sut = new Parser(config => { + config.AutoHelp = true; + config.AutoHelpShortName = true; + config.HelpWriter = help; + }); + + // Act + var result = sut.ParseArguments(args); + + // Assert + result.Should().BeOfType>(); + result.As>().Errors.Should().HaveCount(x => x == 1); + result.As>().Errors.First().Should().BeOfType(); + } + + [Theory] + [MemberData(nameof(ConsumedDashDashHelpInvalidArgsData))] + public void Dash_dash_help_consumed_by_valid_args_with_invalid_args_produces_no_HelpRequestedErrors(params string[] args) + { + // Arrange + var help = new StringWriter(); + var sut = new Parser(config => { + config.AutoHelp = true; + config.HelpWriter = help; + }); + + // Act + var result = sut.ParseArguments(args); + + // Assert + result.Should().BeOfType>(); + result.As>().Errors.Should().HaveCountGreaterOrEqualTo(1); + result.As>().Errors.Should().NotBeOfType(); + } + + public static IEnumerable ConsumedDashDashHelpInvalidArgsDataWithShortOption = + ConvertDataToShortOption(ConsumedDashDashHelpInvalidArgsData, "--help", "-h"); + + [Theory] + [MemberData(nameof(ConsumedDashDashHelpInvalidArgsDataWithShortOption))] + public void Dash_h_consumed_by_valid_args_with_invalid_args_produces_no_HelpRequestedErrors(params string[] args) + { + // Arrange + var help = new StringWriter(); + var sut = new Parser(config => { + config.AutoHelp = true; + config.AutoHelpShortName = true; + config.HelpWriter = help; + }); + + // Act + var result = sut.ParseArguments(args); + + // Assert + result.Should().BeOfType>(); + result.As>().Errors.Should().HaveCountGreaterOrEqualTo(1); + result.As>().Errors.Should().NotBeOfType(); + } + + [Fact] + public void Explicit_help_request_generates_help_requested_error() + { + // Fixture setup + var expectedError = new HelpRequestedError(); + var sut = new Parser(); + + // Exercize system + var result = sut.ParseArguments(new[] { "--help" }); + + // Verify outcome + ((NotParsed)result).Errors.Should().HaveCount(x => x == 1); + ((NotParsed)result).Errors.Should().ContainSingle(e => e.Equals(expectedError)); + // Teardown + } + + [Fact] + public void Explicit_help_request_with_AutoHelp_off_generates_unknown_option_error() + { + // Fixture setup + var expectedError = new UnknownOptionError("help"); + var sut = new Parser(config => { config.AutoHelp = false; }); + + // Exercise system + var result = sut.ParseArguments(new[] { "--help" }); + + // Verify outcome + ((NotParsed)result).Errors.Should().HaveCount(x => x == 1); + ((NotParsed)result).Errors.Single().Tag.Should().Be(expectedError.Tag); + ((NotParsed)result).Errors.First().As().Token.Should().BeEquivalentTo(expectedError.Token); + + // Teardown + } + + [Fact] + public void Explicit_help_request_with_AutoHelp_off_displays_unknown_option_error() + { + // Fixture setup + var help = new StringWriter(); + var sut = new Parser(config => { config.AutoHelp = false; config.HelpWriter = help; }); + + // Exercise system + sut.ParseArguments(new[] { "--help" }); + var result = help.ToString(); + + // Verify outcome + + // Verify outcome + result.Length.Should().BeGreaterThan(0); + var lines = result.ToNotEmptyLines().TrimStringArray(); + lines[0].Should().Be(CommandLine.Text.HeadingInfo.Default.ToString()); + lines[1].Should().Be(CommandLine.Text.CopyrightInfo.Default.ToString()); + lines[2].Should().BeEquivalentTo("ERROR(S):"); + lines[3].Should().BeEquivalentTo("Option 'help' is unknown."); + + // Teardown + } + + [Fact] + public void Explicit_help_request_with_AutoHelp_off_and_IgnoreUnknownArguments_on_does_not_generate_help_screen() + { + // Fixture setup + var help = new StringWriter(); + var sut = new Parser(config => { config.HelpWriter = help; config.AutoHelp = false; config.IgnoreUnknownArguments = true; }); + + // Exercize system + sut.ParseArguments(new[] { "--help" }); + var result = help.ToString(); + + // Verify outcome + result.Should().BeEquivalentTo(""); + // Teardown + } + } +} diff --git a/tests/CommandLine.Tests/Unit/AutoVersionTests.cs b/tests/CommandLine.Tests/Unit/AutoVersionTests.cs new file mode 100644 index 00000000..249d0e9c --- /dev/null +++ b/tests/CommandLine.Tests/Unit/AutoVersionTests.cs @@ -0,0 +1,440 @@ +using System; +using Xunit; +using FluentAssertions; +using CommandLine.Core; +using CommandLine.Tests.Fakes; +using System.IO; +using System.Linq; +using System.Collections.Generic; + +namespace CommandLine.Tests.Unit +{ + public class AutoVersionTests + { + public AutoVersionTests() + { + } + + public static object[][] ValidArgsData = new [] + { + new [] { "--version" }, + new [] { "--version", "256" }, + new [] { "--version", "--stringvalue", "foo" }, + new [] { "--version", "--stringvalue=foo" }, + new [] { "--stringvalue", "foo", "--version" }, + new [] { "--stringvalue=foo", "--version" }, + new [] { "--version", "--stringvalue", "foo", "-x" }, + new [] { "--version", "--stringvalue=foo", "-x" }, + new [] { "--stringvalue", "foo", "--version", "-x" }, + new [] { "--stringvalue=foo", "--version", "-x" }, + new [] { "--stringvalue", "foo", "-x", "256", "--version" }, + new [] { "--stringvalue=foo", "-x", "256", "--version" }, + new [] { "--stringvalue", "foo", "--version", "-x", "256" }, + new [] { "--stringvalue=foo", "--version", "-x", "256" }, + new [] { "--version", "--stringvalue", "foo", "-x", "256" }, + new [] { "--version", "--stringvalue=foo", "-x", "256" }, + }; + + public static object[][] InvalidArgsData = new [] + { + new [] { "--version", "foo" }, + new [] { "--version", "-s" }, + new [] { "--version", "-i", "foo" }, + new [] {"--version", "--invalid-switch", "foo" }, + new [] {"--invalid-switch", "foo", "--version" }, + new [] {"--invalid-switch", "--version", "foo" }, + }; + + // This test requires the GetoptMode feature + // public static object[][] ConsumedDashDashVersionValidArgsData = new [] + // { + // new [] { "--stringvalue", "--version" }, + // new [] { "--stringvalue=--version" }, + // new [] { "--stringvalue", "--version", "-s", "--version" }, + // new [] { "--stringvalue=--version", "-s", "--version" }, + // new [] { "--stringvalue", "--version", "-s--version" }, + // new [] { "--stringvalue=--version", "-s--version" }, + // }; + + public static object[][] MixOfConsumedAndUnconsumedDashDashVersionValidArgsData = new [] + { + new [] { "--stringvalue", "--version", "--version" }, + new [] { "--version", "--stringvalue", "--version" }, + new [] { "--stringvalue=--version", "--version" }, + new [] { "--version", "--stringvalue=--version" }, + new [] { "--stringvalue", "--version", "-s", "--version", "--version" }, + new [] { "--stringvalue", "--version", "--version", "-s", "--version" }, + new [] { "--version", "--stringvalue", "--version", "-s", "--version" }, + new [] { "--stringvalue=--version", "-s", "--version", "--version" }, + new [] { "--stringvalue=--version", "--version", "-s", "--version" }, + new [] { "--version", "--stringvalue=--version", "-s", "--version" }, + new [] { "--stringvalue", "--version", "-s--version", "--version" }, + new [] { "--stringvalue", "--version", "--version", "-s--version", "--version" }, + new [] { "--version", "--stringvalue", "--version", "-s--version" }, + new [] { "--stringvalue=--version", "-s--version", "--version" }, + new [] { "--stringvalue=--version", "--version", "-s--version" }, + new [] { "--version", "--stringvalue=--version", "-s--version" }, + }; + + public static object[][] ConsumedDashDashVersionInvalidArgsData = new [] + { + new [] { "--stringvalue", "--version", "foo" }, + new [] { "-s", "--version", "--stringvalue" }, + new [] { "-s", "--version", "-i", "foo" }, + new [] { "--stringvalue", "--version", "--invalid-switch", "256" }, + new [] { "--stringvalue=--version", "--invalid-switch", "256" }, + new [] { "--invalid-switch", "-s", "--version" }, + }; + + public static IEnumerable ConvertDataToShortOption(object[][] data, string search, string replacement) + { + foreach (object[] row in data) + { + var strings = row as string[]; + if (strings != null) + { + yield return strings.Select(item => item.Replace(search, replacement)).ToArray(); + } + } + } + + [Theory] + [MemberData(nameof(ValidArgsData))] + public void Explicit_version_command_with_valid_args_produces_just_one_VersionRequestedError(params string[] args) + { + // Arrange + var help = new StringWriter(); + var sut = new Parser(config => { + config.AutoVersion = true; + config.HelpWriter = help; + }); + + // Act + var result = sut.ParseArguments(args); + + // Assert + result.Should().BeOfType>(); + result.As>().Errors.Should().HaveCount(x => x == 1); + result.As>().Errors.First().Should().BeOfType(); + } + + public static IEnumerable ValidArgsDataWithShortOption = + ConvertDataToShortOption(ValidArgsData, "--version", "-V"); + + [Theory] + [MemberData(nameof(ValidArgsDataWithShortOption))] + public void Explicit_version_command_with_valid_args_and_short_option_produces_just_one_VersionRequestedError(params string[] args) + { + // Arrange + var help = new StringWriter(); + var sut = new Parser(config => { + config.AutoVersion = true; + config.AutoVersionShortName = true; + config.HelpWriter = help; + }); + + // Act + var result = sut.ParseArguments(args); + + // Assert + result.Should().BeOfType>(); + result.As>().Errors.Should().HaveCount(x => x == 1); + result.As>().Errors.First().Should().BeOfType(); + } + + [Theory] + [MemberData(nameof(InvalidArgsData))] + public void Explicit_version_command_with_invalid_args_produces_just_one_VersionRequestedError(params string[] args) + { + // Arrange + var help = new StringWriter(); + var sut = new Parser(config => { + config.AutoVersion = true; + config.HelpWriter = help; + }); + + // Act + var result = sut.ParseArguments(args); + + // Assert + result.Should().BeOfType>(); + result.As>().Errors.Should().HaveCount(x => x == 1); + result.As>().Errors.First().Should().BeOfType(); + } + + public static IEnumerable InvalidArgsDataWithShortOption = + ConvertDataToShortOption(InvalidArgsData, "--version", "-V"); + + [Theory] + [MemberData(nameof(InvalidArgsDataWithShortOption))] + public void Explicit_version_command_with_invalid_args_and_short_option_produces_just_one_VersionRequestedError(params string[] args) + { + // Arrange + var help = new StringWriter(); + var sut = new Parser(config => { + config.AutoVersion = true; + config.AutoVersionShortName = true; + config.HelpWriter = help; + }); + + // Act + var result = sut.ParseArguments(args); + + // Assert + result.Should().BeOfType>(); + result.As>().Errors.Should().HaveCount(x => x == 1); + result.As>().Errors.First().Should().BeOfType(); + } + + // This test requires the GetoptMode feature + // [Theory] + // [MemberData(nameof(ConsumedDashDashVersionValidArgsData))] + // public void Dash_dash_version_in_a_string_value_does_not_produce_VersionRequestedError(params string[] args) + // { + // // Arrange + // var help = new StringWriter(); + // var sut = new Parser(config => { + // config.AutoVersion = true; + // config.HelpWriter = help; + // config.GetoptMode = true; + // }); + + // // Act + // var result = sut.ParseArguments(args); + + // // Assert + // // result.Should().BeOfType>(); + // // result.As>().Errors.Should().HaveCount(x => x == 1); + // // result.As>().Errors.First().Should().BeOfType(); + // result.Should().BeOfType>(); + // string stringValue = result.As>().Value.StringValue; + // string shortAndLong = result.As>().Value.ShortAndLong; + // stringValue.Should().Be("--version"); + // shortAndLong.Should().BeOneOf("--version", null, ""); + // } + + // public static IEnumerable ConsumedDashDashVersionValidArgsDataWithShortOption = + // ConvertDataToShortOption(ConsumedDashDashVersionValidArgsData, "--version", "-V"); + + // This test requires the GetoptMode feature + // [Theory] + // [MemberData(nameof(ConsumedDashDashVersionValidArgsDataWithShortOption))] + // public void Dash_dash_version_in_a_string_value_with_short_option_does_not_produce_VersionRequestedError(params string[] args) + // { + // // Arrange + // var help = new StringWriter(); + // var sut = new Parser(config => { + // config.AutoVersion = true; + // config.AutoVersionShortName = true; + // config.HelpWriter = help; + // config.GetoptMode = true; + // }); + + // // Act + // var result = sut.ParseArguments(args); + + // // Assert + // // result.Should().BeOfType>(); + // // result.As>().Errors.Should().HaveCount(x => x == 1); + // // result.As>().Errors.First().Should().BeOfType(); + // result.Should().BeOfType>(); + // string stringValue = result.As>().Value.StringValue; + // string shortAndLong = result.As>().Value.ShortAndLong; + // stringValue.Should().Be("-V"); + // shortAndLong.Should().BeOneOf("-V", null, ""); + // } + + // public static IEnumerable ConsumedDashDashVersionValidArgsDataWithShortOptionInData = + // ConvertDataToShortOption(ConsumedDashDashVersionValidArgsData, "--version", "h"); + + // This test requires the GetoptMode feature + // [Theory] + // [MemberData(nameof(ConsumedDashDashVersionValidArgsDataWithShortOptionInData))] + // public void Dash_dash_version_in_a_string_value_with_short_option_in_data_does_not_produce_VersionRequestedError(params string[] args) + // { + // // Arrange + // var help = new StringWriter(); + // var sut = new Parser(config => { + // config.AutoVersion = true; + // config.AutoVersionShortName = true; + // config.HelpWriter = help; + // config.GetoptMode = true; + // }); + + // // Act + // var result = sut.ParseArguments(args); + + // // Assert + // // result.Should().BeOfType>(); + // // result.As>().Errors.Should().HaveCount(x => x == 1); + // // result.As>().Errors.First().Should().BeOfType(); + // result.Should().BeOfType>(); + // string stringValue = result.As>().Value.StringValue; + // string shortAndLong = result.As>().Value.ShortAndLong; + // stringValue.Should().Be("h"); + // shortAndLong.Should().BeOneOf("h", null, ""); + // } + + [Theory] + [MemberData(nameof(MixOfConsumedAndUnconsumedDashDashVersionValidArgsData))] + public void Explicit_version_command_mixed_with_some_consumed_args_produces_just_one_VersionRequestedError(params string[] args) + { + // Arrange + var help = new StringWriter(); + var sut = new Parser(config => { + config.AutoVersion = true; + config.HelpWriter = help; + }); + + // Act + var result = sut.ParseArguments(args); + + // Assert + result.Should().BeOfType>(); + result.As>().Errors.Should().HaveCount(x => x == 1); + result.As>().Errors.First().Should().BeOfType(); + } + + public static IEnumerable MixOfConsumedAndUnconsumedDashDashVersionValidArgsDataWithShortOption = + ConvertDataToShortOption(MixOfConsumedAndUnconsumedDashDashVersionValidArgsData, "--version", "-V"); + + [Theory] + [MemberData(nameof(MixOfConsumedAndUnconsumedDashDashVersionValidArgsDataWithShortOption))] + public void Explicit_short_version_command_mixed_with_some_consumed_args_produces_just_one_VersionRequestedError(params string[] args) + { + // Arrange + var help = new StringWriter(); + var sut = new Parser(config => { + config.AutoVersion = true; + config.AutoVersionShortName = true; + config.HelpWriter = help; + }); + + // Act + var result = sut.ParseArguments(args); + + // Assert + result.Should().BeOfType>(); + result.As>().Errors.Should().HaveCount(x => x == 1); + result.As>().Errors.First().Should().BeOfType(); + } + + [Theory] + [MemberData(nameof(ConsumedDashDashVersionInvalidArgsData))] + public void Dash_dash_version_consumed_by_valid_args_with_invalid_args_produces_no_VersionRequestedErrors(params string[] args) + { + // Arrange + var help = new StringWriter(); + var sut = new Parser(config => { + config.AutoVersion = true; + config.HelpWriter = help; + }); + + // Act + var result = sut.ParseArguments(args); + + // Assert + result.Should().BeOfType>(); + result.As>().Errors.Should().HaveCountGreaterOrEqualTo(1); + result.As>().Errors.Should().NotBeOfType(); + } + + public static IEnumerable ConsumedDashDashVersionInvalidArgsDataWithShortOption = + ConvertDataToShortOption(ConsumedDashDashVersionInvalidArgsData, "--version", "-V"); + + [Theory] + [MemberData(nameof(ConsumedDashDashVersionInvalidArgsDataWithShortOption))] + public void Dash_h_consumed_by_valid_args_with_invalid_args_produces_no_VersionRequestedErrors(params string[] args) + { + // Arrange + var help = new StringWriter(); + var sut = new Parser(config => { + config.AutoVersion = true; + config.AutoVersionShortName = true; + config.HelpWriter = help; + }); + + // Act + var result = sut.ParseArguments(args); + + // Assert + result.Should().BeOfType>(); + result.As>().Errors.Should().HaveCountGreaterOrEqualTo(1); + result.As>().Errors.Should().NotBeOfType(); + } + + [Fact] + public void Explicit_version_request_generates_version_requested_error() + { + // Fixture setup + var expectedError = new VersionRequestedError(); + var sut = new Parser(); + + // Exercize system + var result = sut.ParseArguments(new[] { "--version" }); + + // Verify outcome + ((NotParsed)result).Errors.Should().HaveCount(x => x == 1); + ((NotParsed)result).Errors.Should().ContainSingle(e => e.Equals(expectedError)); + // Teardown + } + + [Fact] + public void Explicit_version_request_with_AutoVersion_off_generates_unknown_option_error() + { + // Fixture setup + var expectedError = new UnknownOptionError("version"); + var sut = new Parser(config => { config.AutoVersion = false; }); + + // Exercise system + var result = sut.ParseArguments(new[] { "--version" }); + + // Verify outcome + ((NotParsed)result).Errors.Should().HaveCount(x => x == 1); + ((NotParsed)result).Errors.Single().Tag.Should().Be(expectedError.Tag); + ((NotParsed)result).Errors.First().As().Token.Should().BeEquivalentTo(expectedError.Token); + + // Teardown + } + + [Fact] + public void Explicit_version_request_with_AutoVersion_off_displays_unknown_option_error() + { + // Fixture setup + var help = new StringWriter(); + var sut = new Parser(config => { config.AutoVersion = false; config.HelpWriter = help; }); + + // Exercise system + sut.ParseArguments(new[] { "--version" }); + var result = help.ToString(); + + // Verify outcome + + // Verify outcome + result.Length.Should().BeGreaterThan(0); + var lines = result.ToNotEmptyLines().TrimStringArray(); + lines[0].Should().Be(CommandLine.Text.HeadingInfo.Default.ToString()); + lines[1].Should().Be(CommandLine.Text.CopyrightInfo.Default.ToString()); + lines[2].Should().BeEquivalentTo("ERROR(S):"); + lines[3].Should().BeEquivalentTo("Option 'version' is unknown."); + + // Teardown + } + + [Fact] + public void Explicit_version_request_with_AutoVersion_off_and_IgnoreUnknownArguments_on_does_not_generate_version_screen() + { + // Fixture setup + var help = new StringWriter(); + var sut = new Parser(config => { config.HelpWriter = help; config.AutoVersion = false; config.IgnoreUnknownArguments = true; }); + + // Exercize system + sut.ParseArguments(new[] { "--version" }); + var result = help.ToString(); + + // Verify outcome + result.Should().BeEquivalentTo(""); + // Teardown + } + } +} diff --git a/tests/CommandLine.Tests/Unit/Core/InstanceBuilderTests.cs b/tests/CommandLine.Tests/Unit/Core/InstanceBuilderTests.cs index be09f375..57db5cb2 100644 --- a/tests/CommandLine.Tests/Unit/Core/InstanceBuilderTests.cs +++ b/tests/CommandLine.Tests/Unit/Core/InstanceBuilderTests.cs @@ -19,7 +19,10 @@ namespace CommandLine.Tests.Unit.Core { public class InstanceBuilderTests { - private static ParserResult InvokeBuild(string[] arguments, bool autoHelp = true, bool autoVersion = true, bool multiInstance = false) + private static ParserResult InvokeBuild(string[] arguments, + bool autoHelp = true, bool autoHelpShortName = false, + bool autoVersion = true, bool autoVersionShortName = false, + bool multiInstance = false) where T : new() { return InstanceBuilder.Build( @@ -30,7 +33,9 @@ private static ParserResult InvokeBuild(string[] arguments, bool autoHelp false, CultureInfo.InvariantCulture, autoHelp, + autoHelpShortName, autoVersion, + autoVersionShortName, multiInstance, Enumerable.Empty()); } diff --git a/tests/CommandLine.Tests/Unit/Core/InstanceChooserTests.cs b/tests/CommandLine.Tests/Unit/Core/InstanceChooserTests.cs index d5cb9a21..0643b8af 100644 --- a/tests/CommandLine.Tests/Unit/Core/InstanceChooserTests.cs +++ b/tests/CommandLine.Tests/Unit/Core/InstanceChooserTests.cs @@ -26,7 +26,9 @@ private static ParserResult InvokeChoose( false, CultureInfo.InvariantCulture, true, + false, true, + false, multiInstance, Enumerable.Empty()); } diff --git a/tests/CommandLine.Tests/Unit/ParserTests.cs b/tests/CommandLine.Tests/Unit/ParserTests.cs index 58ce7d3f..95cfed53 100644 --- a/tests/CommandLine.Tests/Unit/ParserTests.cs +++ b/tests/CommandLine.Tests/Unit/ParserTests.cs @@ -727,14 +727,12 @@ public void Properly_formatted_help_screen_excludes_help_as_unknown_option() var lines = result.ToNotEmptyLines().TrimStringArray(); lines[0].Should().Be(HeadingInfo.Default.ToString()); lines[1].Should().Be(CopyrightInfo.Default.ToString()); - lines[2].Should().BeEquivalentTo("ERROR(S):"); - lines[3].Should().BeEquivalentTo("Option 'bad-arg' is unknown."); - lines[4].Should().BeEquivalentTo("--no-hardlinks Optimize the cloning process from a repository on a local"); - lines[5].Should().BeEquivalentTo("filesystem by copying files."); - lines[6].Should().BeEquivalentTo("-q, --quiet Suppress summary message."); - lines[7].Should().BeEquivalentTo("--help Display this help screen."); - lines[8].Should().BeEquivalentTo("--version Display version information."); - lines[9].Should().BeEquivalentTo("value pos. 0"); + lines[2].Should().BeEquivalentTo("--no-hardlinks Optimize the cloning process from a repository on a local"); + lines[3].Should().BeEquivalentTo("filesystem by copying files."); + lines[4].Should().BeEquivalentTo("-q, --quiet Suppress summary message."); + lines[5].Should().BeEquivalentTo("--help Display this help screen."); + lines[6].Should().BeEquivalentTo("--version Display version information."); + lines[7].Should().BeEquivalentTo("value pos. 0"); // Teardown }