diff --git a/Directory.Build.props b/Directory.Build.props index b0d18da2..db23f03e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -30,7 +30,7 @@ true $(WarningsNotAsErrors);1591 - 8.0 + 9.0 annotations $(MSBuildThisFileDirectory)src\StrongName.snk true diff --git a/README.md b/README.md index 209be6c2..dde6f551 100644 --- a/README.md +++ b/README.md @@ -81,21 +81,19 @@ using McMaster.Extensions.CommandLineUtils; var app = new CommandLineApplication(); app.HelpOption(); -var optionSubject = app.Option("-s|--subject ", "The subject", CommandOptionType.SingleValue); -var optionRepeat = app.Option("-n|--count ", "Repeat", CommandOptionType.SingleValue); + +var subject = app.Option("-s|--subject ", "The subject", CommandOptionType.SingleValue); +subject.DefaultValue = "world"; + +var repeat = app.Option("-n|--count ", "Repeat", CommandOptionType.SingleValue); +repeat.DefaultValue = 1; app.OnExecute(() => { - var subject = optionSubject.HasValue() - ? optionSubject.Value() - : "world"; - - var count = optionRepeat.HasValue() ? optionRepeat.ParsedValue : 1; - for (var i = 0; i < count; i++) + for (var i = 0; i < repeat.ParsedValue; i++) { - Console.WriteLine($"Hello {subject}!"); + Console.WriteLine($"Hello {subject.Value()}!"); } - return 0; }); return app.Execute(args); diff --git a/docs/docs/intro.md b/docs/docs/intro.md index a740237f..65d034c8 100644 --- a/docs/docs/intro.md +++ b/docs/docs/intro.md @@ -64,15 +64,12 @@ public class Program var app = new CommandLineApplication(); app.HelpOption(); - var optionSubject = app.Option("-s|--subject ", "The subject", CommandOptionType.SingleValue); + var subject = app.Option("-s|--subject ", "The subject", CommandOptionType.SingleValue); + subject.DefaultValue = "world"; app.OnExecute(() => { - var subject = optionSubject.HasValue() - ? optionSubject.Value() - : "world"; - - Console.WriteLine($"Hello {subject}!"); + Console.WriteLine($"Hello {subject.Value()}!"); return 0; }); diff --git a/docs/samples/custom-attribute/Program.cs b/docs/samples/custom-attribute/Program.cs index 41c8e5b5..001b706a 100644 --- a/docs/samples/custom-attribute/Program.cs +++ b/docs/samples/custom-attribute/Program.cs @@ -44,12 +44,10 @@ public void Apply(ConventionContext context, MemberInfo member) if (member is FieldInfo field) { var opt = context.Application.Option("--working-dir", "The working directory", CommandOptionType.SingleOrNoValue); + opt.DefaultValue = context.Application.WorkingDirectory; context.Application.OnParsingComplete(_ => { - var cwd = opt.HasValue() - ? opt.Value() - : context.Application.WorkingDirectory; - field.SetValue(context.ModelAccessor.GetModel(), cwd); + field.SetValue(context.ModelAccessor.GetModel(), opt.Value()); }); } } diff --git a/docs/samples/helloworld-async/Program.cs b/docs/samples/helloworld-async/Program.cs index 1e382ff5..099cbd37 100644 --- a/docs/samples/helloworld-async/Program.cs +++ b/docs/samples/helloworld-async/Program.cs @@ -5,24 +5,22 @@ var app = new CommandLineApplication(); app.HelpOption(); -var optionSubject = app.Option("-s|--subject ", "The subject", CommandOptionType.SingleValue); -var optionRepeat = app.Option("-n|--count ", "Repeat", CommandOptionType.SingleValue); +var subject = app.Option("-s|--subject ", "The subject", CommandOptionType.SingleValue); +subject.DefaultValue = "world"; + +var repeat = app.Option("-n|--count ", "Repeat", CommandOptionType.SingleValue); +repeat.DefaultValue = 1; app.OnExecuteAsync(async cancellationToken => { - var subject = optionSubject.HasValue() - ? optionSubject.Value() - : "world"; - - var count = optionRepeat.HasValue() ? optionRepeat.ParsedValue : 1; - for (var i = 0; i < count; i++) + for (var i = 0; i < repeat.ParsedValue; i++) { Console.Write($"Hello"); // Pause for dramatic effect await Task.Delay(2000, cancellationToken); - Console.WriteLine($" {subject}!"); + Console.WriteLine($" {subject.Value()}!"); } }); diff --git a/docs/samples/helloworld/HelloWorld.csproj b/docs/samples/helloworld/HelloWorld.csproj index 9fe71e36..135c4fc5 100644 --- a/docs/samples/helloworld/HelloWorld.csproj +++ b/docs/samples/helloworld/HelloWorld.csproj @@ -3,6 +3,7 @@ Exe net5.0 + enable diff --git a/docs/samples/helloworld/Program.cs b/docs/samples/helloworld/Program.cs index 96c6c267..6a0e80d9 100644 --- a/docs/samples/helloworld/Program.cs +++ b/docs/samples/helloworld/Program.cs @@ -4,21 +4,17 @@ var app = new CommandLineApplication(); app.HelpOption(); -var optionSubject = app.Option("-s|--subject ", "The subject", CommandOptionType.SingleValue); -var optionRepeat = app.Option("-n|--count ", "Repeat", CommandOptionType.SingleValue); +var subject = app.Option("-s|--subject ", "The subject", CommandOptionType.SingleValue); +subject.DefaultValue = "world"; +var repeat = app.Option("-n|--count ", "Repeat", CommandOptionType.SingleValue); +repeat.DefaultValue = 1; app.OnExecute(() => { - var subject = optionSubject.HasValue() - ? optionSubject.Value() - : "world"; - - var count = optionRepeat.HasValue() ? optionRepeat.ParsedValue : 1; - for (var i = 0; i < count; i++) + for (var i = 0; i < repeat.ParsedValue; i++) { - Console.WriteLine($"Hello {subject}!"); + Console.WriteLine($"Hello {subject.Value()}!"); } - return 0; }); return app.Execute(args); diff --git a/src/CommandLineUtils/CommandArgument.cs b/src/CommandLineUtils/CommandArgument.cs index 24264d82..5d6ffee8 100644 --- a/src/CommandLineUtils/CommandArgument.cs +++ b/src/CommandLineUtils/CommandArgument.cs @@ -36,7 +36,17 @@ public class CommandArgument /// /// All values specified, if any. /// - public IReadOnlyList Values => _values; + public IReadOnlyList Values + { + get + { + if (_values.Count == 0 && DefaultValue != null) + { + return new List { DefaultValue }; + } + return _values; + } + } /// /// Allow multiple values. @@ -44,7 +54,7 @@ public class CommandArgument public bool MultipleValues { get; set; } /// - /// The first value from , if any. + /// The first value from , if any, or . /// public string? Value => Values.FirstOrDefault(); @@ -54,7 +64,7 @@ public class CommandArgument public string? DefaultValue { get; set; } /// - /// True if this argument has been assigned values. + /// True when is not empty or when a is given. /// public bool HasValue => Values.Any(); diff --git a/src/CommandLineUtils/CommandArgument{T}.cs b/src/CommandLineUtils/CommandArgument{T}.cs index bc99a216..e43e4f2f 100644 --- a/src/CommandLineUtils/CommandArgument{T}.cs +++ b/src/CommandLineUtils/CommandArgument{T}.cs @@ -20,7 +20,9 @@ public class CommandArgument : CommandArgument, IInternalCommandParamOfT { private readonly List _parsedValues = new List(); private readonly IValueParser _valueParser; - private T _defaultValue; + private bool _hasBeenParsed; + private bool _hasDefaultValue; + private T? _defaultValue; /// /// Initializes a new instance of @@ -30,27 +32,43 @@ public CommandArgument(IValueParser valueParser) { _valueParser = valueParser ?? throw new ArgumentNullException(nameof(valueParser)); UnderlyingType = typeof(T); - SetBaseDefaultValue(default); } /// /// The parsed value. /// - public T ParsedValue => _parsedValues.FirstOrDefault(); + public T ParsedValue => ParsedValues.FirstOrDefault(); /// /// All parsed values; /// - public IReadOnlyList ParsedValues => _parsedValues; + public IReadOnlyList ParsedValues + { + get + { + if (!_hasBeenParsed) + { + ((IInternalCommandParamOfT)this).Parse(CultureInfo.CurrentCulture); + } + + if (_parsedValues.Count == 0 && _hasDefaultValue) + { + return new[] { DefaultValue }; + } + + return _parsedValues; + } + } /// /// The default value of the argument. /// - public new T DefaultValue + public new T? DefaultValue { get => _defaultValue; set { + _hasDefaultValue = value != null; _defaultValue = value; SetBaseDefaultValue(value); } @@ -58,8 +76,9 @@ public CommandArgument(IValueParser valueParser) void IInternalCommandParamOfT.Parse(CultureInfo culture) { + _hasBeenParsed = true; _parsedValues.Clear(); - foreach (var t in Values) + foreach (var t in base._values) { _parsedValues.Add(_valueParser.Parse(Name, t, culture)); } @@ -79,5 +98,13 @@ void SetBaseDefaultValue(T value) } } } + + /// + public override void Reset() + { + _hasBeenParsed = false; + _parsedValues.Clear(); + base.Reset(); + } } } diff --git a/src/CommandLineUtils/CommandOption.cs b/src/CommandLineUtils/CommandOption.cs index df1010df..a318a9e3 100644 --- a/src/CommandLineUtils/CommandOption.cs +++ b/src/CommandLineUtils/CommandOption.cs @@ -100,7 +100,17 @@ internal CommandOption(CommandOptionType type) /// /// Any values found during parsing, if any. /// - public IReadOnlyList Values => _values; + public IReadOnlyList Values + { + get + { + if (_values.Count == 0 && DefaultValue != null) + { + return new List { DefaultValue }; + } + return _values; + } + } /// /// The default value of the option. @@ -171,7 +181,7 @@ public bool TryParse(string? value) } /// - /// True when is not empty. + /// True when is not empty or when a is given. /// /// public bool HasValue() @@ -180,13 +190,10 @@ public bool HasValue() } /// - /// Returns the first element of , if any. + /// Returns the first element of , if any, or . /// /// - public string? Value() - { - return HasValue() ? Values[0] : null; - } + public string? Value() => Values.FirstOrDefault(); /// /// Generates the template string in the format "-{Symbol}|-{Short}|--{Long} <{Value}>" for display in help text. diff --git a/src/CommandLineUtils/CommandOption{T}.cs b/src/CommandLineUtils/CommandOption{T}.cs index f3dcbe7a..755a3495 100644 --- a/src/CommandLineUtils/CommandOption{T}.cs +++ b/src/CommandLineUtils/CommandOption{T}.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; -using System.Reflection; using McMaster.Extensions.CommandLineUtils.Abstractions; namespace McMaster.Extensions.CommandLineUtils @@ -20,7 +19,9 @@ public class CommandOption : CommandOption, IInternalCommandParamOfT { private readonly List _parsedValues = new List(); private readonly IValueParser _valueParser; - private T _defaultValue; + private T? _defaultValue; + private bool _hasDefaultValue; + private bool _hasBeenParsed; /// /// Initializes a new instance of @@ -33,27 +34,43 @@ public CommandOption(IValueParser valueParser, string template, CommandOption { _valueParser = valueParser ?? throw new ArgumentNullException(nameof(valueParser)); UnderlyingType = typeof(T); - SetBaseDefaultValue(default); } /// /// The parsed value. /// - public T ParsedValue => _parsedValues.FirstOrDefault(); + public T ParsedValue => ParsedValues.FirstOrDefault(); /// /// All parsed values; /// - public IReadOnlyList ParsedValues => _parsedValues; + public IReadOnlyList ParsedValues + { + get + { + if (!_hasBeenParsed) + { + ((IInternalCommandParamOfT)this).Parse(CultureInfo.CurrentCulture); + } + + if (_parsedValues.Count == 0 && _hasDefaultValue) + { + return new[] { DefaultValue }; + } + + return _parsedValues; + } + } /// /// The default value of the option. /// - public new T DefaultValue + public new T? DefaultValue { get => _defaultValue; set { + _hasDefaultValue = value != null; _defaultValue = value; SetBaseDefaultValue(value); } @@ -61,14 +78,15 @@ public CommandOption(IValueParser valueParser, string template, CommandOption void IInternalCommandParamOfT.Parse(CultureInfo culture) { + _hasBeenParsed = true; _parsedValues.Clear(); - foreach (var t in Values) + foreach (var t in base._values) { _parsedValues.Add(_valueParser.Parse(LongName ?? ShortName ?? SymbolName, t, culture)); } } - void SetBaseDefaultValue(T value) + private void SetBaseDefaultValue(T value) { if (!ReflectionHelper.IsSpecialValueTupleType(typeof(T), out _)) { @@ -82,5 +100,13 @@ void SetBaseDefaultValue(T value) } } } + + /// + public override void Reset() + { + _hasBeenParsed = false; + _parsedValues.Clear(); + base.Reset(); + } } } diff --git a/src/CommandLineUtils/PublicAPI.Shipped.txt b/src/CommandLineUtils/PublicAPI.Shipped.txt index 49e347eb..1476d1c4 100644 --- a/src/CommandLineUtils/PublicAPI.Shipped.txt +++ b/src/CommandLineUtils/PublicAPI.Shipped.txt @@ -53,8 +53,6 @@ McMaster.Extensions.CommandLineUtils.ArgumentAttribute.ShowInHelpText.set -> voi McMaster.Extensions.CommandLineUtils.ArgumentEscaper McMaster.Extensions.CommandLineUtils.CommandArgument McMaster.Extensions.CommandLineUtils.CommandArgument.CommandArgument() -> void -McMaster.Extensions.CommandLineUtils.CommandArgument.DefaultValue.get -> string? -McMaster.Extensions.CommandLineUtils.CommandArgument.DefaultValue.set -> void McMaster.Extensions.CommandLineUtils.CommandArgument.Description.get -> string? McMaster.Extensions.CommandLineUtils.CommandArgument.Description.set -> void McMaster.Extensions.CommandLineUtils.CommandArgument.MultipleValues.get -> bool @@ -68,8 +66,6 @@ McMaster.Extensions.CommandLineUtils.CommandArgument.Value.get -> string? McMaster.Extensions.CommandLineUtils.CommandArgument.Values.get -> System.Collections.Generic.IReadOnlyList! McMaster.Extensions.CommandLineUtils.CommandArgument McMaster.Extensions.CommandLineUtils.CommandArgument.CommandArgument(McMaster.Extensions.CommandLineUtils.Abstractions.IValueParser! valueParser) -> void -McMaster.Extensions.CommandLineUtils.CommandArgument.DefaultValue.get -> T -McMaster.Extensions.CommandLineUtils.CommandArgument.DefaultValue.set -> void McMaster.Extensions.CommandLineUtils.CommandArgument.ParsedValue.get -> T McMaster.Extensions.CommandLineUtils.CommandArgument.ParsedValues.get -> System.Collections.Generic.IReadOnlyList! McMaster.Extensions.CommandLineUtils.CommandAttribute @@ -198,8 +194,6 @@ McMaster.Extensions.CommandLineUtils.CommandLineApplication.ModelFactory McMaster.Extensions.CommandLineUtils.CommandLineApplicationExtensions McMaster.Extensions.CommandLineUtils.CommandOption McMaster.Extensions.CommandLineUtils.CommandOption.CommandOption(string! template, McMaster.Extensions.CommandLineUtils.CommandOptionType optionType) -> void -McMaster.Extensions.CommandLineUtils.CommandOption.DefaultValue.get -> string? -McMaster.Extensions.CommandLineUtils.CommandOption.DefaultValue.set -> void McMaster.Extensions.CommandLineUtils.CommandOption.Description.get -> string? McMaster.Extensions.CommandLineUtils.CommandOption.Description.set -> void McMaster.Extensions.CommandLineUtils.CommandOption.HasValue() -> bool @@ -222,8 +216,6 @@ McMaster.Extensions.CommandLineUtils.CommandOption.ValueName.set -> void McMaster.Extensions.CommandLineUtils.CommandOption.Values.get -> System.Collections.Generic.IReadOnlyList! McMaster.Extensions.CommandLineUtils.CommandOption McMaster.Extensions.CommandLineUtils.CommandOption.CommandOption(McMaster.Extensions.CommandLineUtils.Abstractions.IValueParser! valueParser, string! template, McMaster.Extensions.CommandLineUtils.CommandOptionType optionType) -> void -McMaster.Extensions.CommandLineUtils.CommandOption.DefaultValue.get -> T -McMaster.Extensions.CommandLineUtils.CommandOption.DefaultValue.set -> void McMaster.Extensions.CommandLineUtils.CommandOption.ParsedValue.get -> T McMaster.Extensions.CommandLineUtils.CommandOption.ParsedValues.get -> System.Collections.Generic.IReadOnlyList! McMaster.Extensions.CommandLineUtils.CommandOptionType diff --git a/src/CommandLineUtils/PublicAPI.Unshipped.txt b/src/CommandLineUtils/PublicAPI.Unshipped.txt index 5018755e..451b9220 100644 --- a/src/CommandLineUtils/PublicAPI.Unshipped.txt +++ b/src/CommandLineUtils/PublicAPI.Unshipped.txt @@ -1,7 +1,17 @@ #nullable enable +McMaster.Extensions.CommandLineUtils.CommandOption.DefaultValue.get -> string? +McMaster.Extensions.CommandLineUtils.CommandOption.DefaultValue.set -> void +McMaster.Extensions.CommandLineUtils.CommandArgument.DefaultValue.get -> string? +McMaster.Extensions.CommandLineUtils.CommandArgument.DefaultValue.set -> void +McMaster.Extensions.CommandLineUtils.CommandArgument.DefaultValue.get -> T? +McMaster.Extensions.CommandLineUtils.CommandArgument.DefaultValue.set -> void McMaster.Extensions.CommandLineUtils.CommandArgument.HasValue.get -> bool McMaster.Extensions.CommandLineUtils.CommandArgument.TryParse(string? value) -> bool +McMaster.Extensions.CommandLineUtils.CommandOption.DefaultValue.get -> T? +McMaster.Extensions.CommandLineUtils.CommandOption.DefaultValue.set -> void virtual McMaster.Extensions.CommandLineUtils.CommandArgument.Reset() -> void virtual McMaster.Extensions.CommandLineUtils.CommandOption.Reset() -> void +override McMaster.Extensions.CommandLineUtils.CommandArgument.Reset() -> void +override McMaster.Extensions.CommandLineUtils.CommandOption.Reset() -> void McMaster.Extensions.CommandLineUtils.CommandLineApplication.AddArgument(McMaster.Extensions.CommandLineUtils.CommandArgument! argument) -> void McMaster.Extensions.CommandLineUtils.CommandLineApplication.AddOption(McMaster.Extensions.CommandLineUtils.CommandOption! option) -> void diff --git a/test/CommandLineUtils.Tests/CommandArgumentTests.cs b/test/CommandLineUtils.Tests/CommandArgumentTests.cs new file mode 100644 index 00000000..aca3ce49 --- /dev/null +++ b/test/CommandLineUtils.Tests/CommandArgumentTests.cs @@ -0,0 +1,104 @@ +// Copyright (c) Nate McMaster. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using McMaster.Extensions.CommandLineUtils.Abstractions; +using Xunit; + +namespace McMaster.Extensions.CommandLineUtils.Tests +{ + public class CommandArgumentTests + { + + [Fact] + public void DoesNotHaveDefaultForValueTypes() + { + var app = new CommandLineApplication(); + var arg = app.Argument("abc", "xyz"); + Assert.False(arg.HasValue); + Assert.Null(arg.Value); + } + + [Fact] + public void DoesNotHaveDefaultForReferenceTypes() + { + var app = new CommandLineApplication(); + var arg = app.Argument("abc", "xyz"); + Assert.Null(arg.DefaultValue); + Assert.False(arg.HasValue); + } + + [Fact] + public void DefaultValueReturnedIfUnset() + { + var arg = new CommandArgument + { + DefaultValue = "ABC" + }; + + Assert.Equal("ABC", arg.Value); + Assert.True(arg.HasValue); + Assert.Equal(new List { "ABC" }, arg.Values); + } + + [Fact] + public void DefaultValueOfTReturnedIfUnset() + { + var arg = new CommandArgument(StockValueParsers.Int32) + { + DefaultValue = 42 + }; + + Assert.Equal("42", arg.Value); + Assert.True(arg.HasValue); + Assert.Equal(new List { "42" }, arg.Values); + Assert.Equal(42, arg.ParsedValue); + Assert.Equal(new List { 42 }, arg.ParsedValues); + } + + [Fact] + public void DefaultOverriddenBySettingValue() + { + var arg = new CommandArgument + { + DefaultValue = "ABC" + }; + + arg.TryParse("xyz"); + + Assert.Equal("xyz", arg.Value); + } + + [Fact] + public void DefaultOfTOverriddenBySettingValue() + { + var arg = new CommandArgument(StockValueParsers.Int32) + { + DefaultValue = 42 + }; + + arg.TryParse("999"); + + Assert.Equal("999", arg.Value); + Assert.True(arg.HasValue); + Assert.Equal(new List { "999" }, arg.Values); + Assert.Equal(999, arg.ParsedValue); + Assert.Equal(new List { 999 }, arg.ParsedValues); + } + + [Fact] + public void DefaultOverriddenAndResetReturnsDefault() + { + var option = new CommandArgument + { + DefaultValue = "ABC" + }; + + option.TryParse("xyz"); + + option.Reset(); + + Assert.Equal("ABC", option.Value); + } + } +} diff --git a/test/CommandLineUtils.Tests/CommandOptionTests.cs b/test/CommandLineUtils.Tests/CommandOptionTests.cs index afa16678..7e05006c 100644 --- a/test/CommandLineUtils.Tests/CommandOptionTests.cs +++ b/test/CommandLineUtils.Tests/CommandOptionTests.cs @@ -1,6 +1,8 @@ // Copyright (c) Nate McMaster. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Collections.Generic; +using McMaster.Extensions.CommandLineUtils.Abstractions; using Xunit; namespace McMaster.Extensions.CommandLineUtils.Tests @@ -46,5 +48,96 @@ public void ItParsesSingleOrNoValueTemplate(string template, string shortName, s Assert.Equal(longName, opt.LongName); Assert.Equal(valueName, opt.ValueName); } + + [Fact] + public void DoesNotHaveDefaultForValueTypes() + { + var app = new CommandLineApplication(); + var option = app.Option("--value ", "abc", CommandOptionType.SingleValue); + Assert.False(option.HasValue()); + Assert.Null(option.Value()); + } + + [Fact] + public void DoesNotHaveDefaultForReferenceTypes() + { + var app = new CommandLineApplication(); + var option = app.Option("--value ", "abc", CommandOptionType.SingleValue); + Assert.Null(option.DefaultValue); + Assert.False(option.HasValue()); + } + + [Fact] + public void DefaultValueReturnedIfUnset() + { + var option = new CommandOption("--value ", CommandOptionType.SingleValue) + { + DefaultValue = "ABC" + }; + + Assert.True(option.HasValue()); + Assert.Equal("ABC", option.Value()); + Assert.Equal(new List { "ABC" }, option.Values); + } + + [Fact] + public void DefaultValueOfTReturnedIfUnset() + { + var option = new CommandOption(StockValueParsers.Int32, "--value ", CommandOptionType.SingleValue) + { + DefaultValue = 42 + }; + + Assert.True(option.HasValue()); + Assert.Equal("42", option.Value()); + Assert.Equal(new List { "42" }, option.Values); + Assert.Equal(42, option.ParsedValue); + Assert.Equal(new List { 42 }, option.ParsedValues); + } + + [Fact] + public void DefaultOverriddenBySettingValue() + { + var option = new CommandOption("--value ", CommandOptionType.SingleValue) + { + DefaultValue = "ABC" + }; + + option.TryParse("xyz"); + + Assert.Equal("xyz", option.Value()); + } + + [Fact] + public void DefaultOfTOverriddenBySettingValue() + { + var option = new CommandOption(StockValueParsers.Int32, "--value ", CommandOptionType.SingleValue) + { + DefaultValue = 42 + }; + + option.TryParse("999"); + + Assert.True(option.HasValue()); + Assert.Equal("999", option.Value()); + Assert.Equal(new List { "999" }, option.Values); + Assert.Equal(999, option.ParsedValue); + Assert.Equal(new List { 999 }, option.ParsedValues); + } + + [Fact] + public void DefaultOverriddenAndResetReturnsDefault() + { + var option = new CommandOption("--value ", CommandOptionType.SingleValue) + { + DefaultValue = "ABC" + }; + + option.TryParse("xyz"); + + option.Reset(); + + Assert.Equal("ABC", option.Value()); + } } } diff --git a/test/CommandLineUtils.Tests/DefaultHelpTextGeneratorTests.cs b/test/CommandLineUtils.Tests/DefaultHelpTextGeneratorTests.cs index 802de6e7..ab708084 100644 --- a/test/CommandLineUtils.Tests/DefaultHelpTextGeneratorTests.cs +++ b/test/CommandLineUtils.Tests/DefaultHelpTextGeneratorTests.cs @@ -113,17 +113,23 @@ public void ShowHelp() app.Option("--rStrOpt ", "restricted str option desc.", CommandOptionType.SingleValue, o => o.IsRequired().Accepts().Values("Foo", "Bar")); app.Option("--dStrOpt ", "str option with default value desc.", CommandOptionType.SingleValue, o => o.DefaultValue = "Foo"); app.Option("--intOpt ", "int option desc.", CommandOptionType.SingleValue); - app.Option("--enumOpt ", "enum option desc.", CommandOptionType.SingleValue); - app.Option("--enumOpt2 ", "restricted enum option desc.", CommandOptionType.SingleValue, o => o.Accepts().Values("None", "Normal")); + app.Option("--enumOpt ", "enum option desc.", CommandOptionType.SingleValue, o => o.DefaultValue = default); + app.Option("--enumOpt2 ", "restricted enum option desc.", CommandOptionType.SingleValue, o => + { + o.DefaultValue = default; + o.Accepts().Values("None", "Normal"); + }); app.Option<(bool, SomeEnum)>("--enumOpt3 ", "nullable enum option desc.", CommandOptionType.SingleOrNoValue); app.Option("--enumOpt4 ", "nullable enum option desc.", CommandOptionType.SingleOrNoValue); app.Argument("SomeStringArgument", "string arg desc."); app.Argument("RestrictedStringArgument", "restricted string arg desc.", a => a.IsRequired().Accepts().Values("Foo", "Bar")); app.Argument("DefaultValStringArgument", "string arg with default value desc.", a => a.DefaultValue = "Foo"); - app.Argument("SomeEnumArgument", "enum arg desc."); - app.Argument("RestrictedEnumArgument", "restricted enum arg desc.", a => a.Accepts().Values("None", "Normal")); + app.Argument("SomeEnumArgument", "enum arg desc.", a => a.DefaultValue = default); + var a = app.Argument("RestrictedEnumArgument", "restricted enum arg desc.", a => a.Accepts().Values("None", "Normal")); + a.DefaultValue = SomeEnum.Normal; app.Argument<(bool, SomeEnum)>("SomeNullableEnumArgument", "nullable enum arg desc."); var helpText = GetHelpText(app); + _output.WriteLine(helpText); Assert.Equal(@"Usage: [options] @@ -138,7 +144,7 @@ SomeEnumArgument enum arg desc. Default value is: None. RestrictedEnumArgument restricted enum arg desc. Allowed values are: None, Normal. - Default value is: None. + Default value is: Normal. SomeNullableEnumArgument nullable enum arg desc. Allowed values are: None, Normal, Extreme. @@ -150,7 +156,6 @@ SomeNullableEnumArgument nullable enum arg desc. --dStrOpt str option with default value desc. Default value is: Foo. --intOpt int option desc. - Default value is: 0. --enumOpt enum option desc. Allowed values are: None, Normal, Extreme. Default value is: None. diff --git a/test/CommandLineUtils.Tests/ValidationTests.cs b/test/CommandLineUtils.Tests/ValidationTests.cs index 0fd79fd4..b3953cb8 100644 --- a/test/CommandLineUtils.Tests/ValidationTests.cs +++ b/test/CommandLineUtils.Tests/ValidationTests.cs @@ -37,7 +37,7 @@ public void ValidationHandlerOfSubcommandIsInvoked() var sub = app.Command("sub", c => { }); var called = false; sub.OnValidationError(_ => called = true); - CommandArgument arg = sub.Argument("t", "test").IsRequired(); + var arg = sub.Argument("t", "test").IsRequired(); Assert.NotEqual(0, app.Execute("sub")); Assert.True(called, "Validation on subcommand should be called"); }