From 7fab0b723e91264f645c5a94d33724a856580c9b Mon Sep 17 00:00:00 2001 From: yakovypg Date: Mon, 23 Feb 2026 18:59:18 +0300 Subject: [PATCH 1/3] Add the abulity to specify error message in `OptionValueRestriction` --- .../Configuration/OptionValueRestriction.cs | 2 +- Core/NetArgumentParser/Options/ValueOption.cs | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Core/NetArgumentParser/Options/Configuration/OptionValueRestriction.cs b/Core/NetArgumentParser/Options/Configuration/OptionValueRestriction.cs index a8b3f4d..4e209d3 100644 --- a/Core/NetArgumentParser/Options/Configuration/OptionValueRestriction.cs +++ b/Core/NetArgumentParser/Options/Configuration/OptionValueRestriction.cs @@ -2,4 +2,4 @@ namespace NetArgumentParser.Options.Configuration; -public record OptionValueRestriction(Predicate IsValueAllowed); +public record OptionValueRestriction(Predicate IsValueAllowed, string? ValueNotSatisfyRestrictionMessage = null); diff --git a/Core/NetArgumentParser/Options/ValueOption.cs b/Core/NetArgumentParser/Options/ValueOption.cs index 6d7b6fd..00dbb8d 100644 --- a/Core/NetArgumentParser/Options/ValueOption.cs +++ b/Core/NetArgumentParser/Options/ValueOption.cs @@ -94,12 +94,17 @@ protected ValueOption( if (valueRestriction is not null) { if (defaultValue is not null && !valueRestriction.IsValueAllowed(defaultValue.Value)) - throw new OptionValueNotSatisfyRestrictionException(null, [$"{defaultValue.Value}"]); + { + throw new OptionValueNotSatisfyRestrictionException( + valueRestriction.ValueNotSatisfyRestrictionMessage, + [$"{defaultValue.Value}"]); + } if (_choices.Count > 0 && _choices.Any(t => !valueRestriction.IsValueAllowed(t))) { throw new OptionValueNotSatisfyRestrictionException( - null, [$"{_choices.First(t => !valueRestriction.IsValueAllowed(t))}"]); + valueRestriction.ValueNotSatisfyRestrictionMessage, + [$"{_choices.First(t => !valueRestriction.IsValueAllowed(t))}"]); } } @@ -384,7 +389,11 @@ protected void VerifyValueIsAllowed(T value, string[] valueSource) ExtendedArgumentNullException.ThrowIfNull(valueSource, nameof(valueSource)); if (!IsValueSatisfyRestriction(value)) - throw new OptionValueNotSatisfyRestrictionException(null, valueSource); + { + throw new OptionValueNotSatisfyRestrictionException( + ValueRestriction?.ValueNotSatisfyRestrictionMessage, + valueSource); + } if (!IsValueSatisfyChoices(value)) { From cd51cfba5df0a1c012af53a0b9793d7df20c64b1 Mon Sep 17 00:00:00 2001 From: yakovypg Date: Mon, 23 Feb 2026 19:01:14 +0300 Subject: [PATCH 2/3] Update examples --- Examples/NetArgumentParser.Examples.AllUseCases/Program.cs | 4 +++- .../NetArgumentParser.Examples.OptionalArguments/Program.cs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Examples/NetArgumentParser.Examples.AllUseCases/Program.cs b/Examples/NetArgumentParser.Examples.AllUseCases/Program.cs index fb22dc5..fbb8f5a 100644 --- a/Examples/NetArgumentParser.Examples.AllUseCases/Program.cs +++ b/Examples/NetArgumentParser.Examples.AllUseCases/Program.cs @@ -85,7 +85,9 @@ shortName: "i", description: "images that need to be processed", isRequired: true, - valueRestriction: new OptionValueRestriction>(t => t.All(p => File.Exists(p))), + valueRestriction: new OptionValueRestriction>( + t => t.All(p => File.Exists(p)), + "all files must exist"), contextCapture: new OneOrMoreContextCapture(), afterValueParsingAction: t => resultValues.InputFiles = [.. t]), diff --git a/Examples/NetArgumentParser.Examples.OptionalArguments/Program.cs b/Examples/NetArgumentParser.Examples.OptionalArguments/Program.cs index f02e2de..9039aea 100644 --- a/Examples/NetArgumentParser.Examples.OptionalArguments/Program.cs +++ b/Examples/NetArgumentParser.Examples.OptionalArguments/Program.cs @@ -70,7 +70,9 @@ shortName: "i", description: "images that need to be processed", isRequired: true, - valueRestriction: new OptionValueRestriction>(t => t.All(p => File.Exists(p))), + valueRestriction: new OptionValueRestriction>( + t => t.All(p => File.Exists(p)), + "all files must exist"), contextCapture: new OneOrMoreContextCapture(), afterValueParsingAction: t => resultValues.InputFiles = [.. t]), From ee2679ed111a48986c28cc8b8b92ee0e360b8fef Mon Sep 17 00:00:00 2001 From: yakovypg Date: Mon, 23 Feb 2026 19:09:26 +0300 Subject: [PATCH 3/3] Update documentation --- Documentation/OptionalArgumentsConfig.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/OptionalArgumentsConfig.md b/Documentation/OptionalArgumentsConfig.md index ef3380c..d1c27b6 100644 --- a/Documentation/OptionalArgumentsConfig.md +++ b/Documentation/OptionalArgumentsConfig.md @@ -200,6 +200,16 @@ var enumValueOption = new EnumValueOption("options", "o", valueRestriction: new OptionValueRestriction(t => t != StringSplitOptions.None)); ``` +You can also specify a message to be shown if the value doesn't satisfy the restriction: + +```cs +var restriction = new OptionValueRestriction(t => t > 0, "angle must be greater than zero"); + +var valueOption = new ValueOption("angle", "a", + description: "angle by which you want to rotate the image", + valueRestriction: restriction); +``` + ### Required Options You can indicate that the option is required. In this case, if the input argument list doesn't contain a matching argument, an exception will be thrown.