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)) { 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. 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]),