-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error message APIs for TypedValueParser
#5065
Comments
Partial fix for clap-rs#5065, allows using TypedValueParser::try_map to implement a ValueParserFactory.
This enables downstream consumers to set custom error messages and take advantage of the `context` mechanism for annotating errors with the provided arguments and values. Fixes clap-rs#5065
This enables downstream consumers to set custom error messages and take advantage of the `context` mechanism for annotating errors with the provided arguments and values. Fixes clap-rs#5065
This issue jumps straight for solutions but to understand them, I need to understand your problems. For example, what problem is trying to be solved with EDIT: I see that information was provided further on. Howeverr, my time for working with these issues is limited. Before we move forward, I would ask to switch this to the issue template. |
Okay, I've rewritten my issue using the feature request template. Let me know if you'd like more information. The solution here feels very obvious to me — the code is already written, just not exported for third parties to use — but I'm open to other designs.
struct MyValueParserFactory;
impl ValueParserFactory for MyValueParserFactory {
// Can't write this because `TryMapValueParser` isn't public!
type Parser = TryMapValueParser<...>;
fn value_parser() -> Self::Parser {
StringValueParser::new().try_map(...)
}
}
clap/clap_builder/src/builder/value_parser.rs Line 2037 in ca855c6
|
Technically, you could still use I'm also fine moving forward with However, I do not want to move make the constructors public. That is a lot larger of a scope of an under taking and there is a lot more of the details that could evolve / change over time that I don't want to limit ourselves in how we evolve them; that is the point of the more general manual error construction API. |
btw #5066 said it was only a partial fix. What is missing? |
btw thank you for taking the time to communicate all of this; it was a big help to have things focusing on the core of the issue |
Nothing is missing for |
I was curious if |
That is because |
Clap Version
4.3.19
Describe your use case
I'm implementing
TypedValueParser
andValueParserFactory
so that I can useclap
to parse custom types, ideally without explicitly annotating thevalue_parser
to use (most recently I'm usinghumantime::parse_duration
to parse a string like500ms
into aDuration
value, but I have a few different implementations).However, I've noticed that the error messages I return from
TypedValueParser::parse_ref
don't include the context, like when I use a function as avalue_parser
. This ultimately goes back to the fact that there's no public method onclap::Error
to set the innersource
error. For example, theError::raw
constructor sets a string message (which is not integrated into context added withError::insert
when formatting):clap/clap_builder/src/error/mod.rs
Line 89 in ca855c6
We can see that the (private)
Error::value_validation
constructor calls the (private)Error::set_source
method to set the source:clap/clap_builder/src/error/mod.rs
Line 637 in ca855c6
And indeed, all of the
TypedValueParser
implementations use this and other private methods to construct their errors:clap/clap_builder/src/builder/value_parser.rs
Line 860 in ca855c6
Here's an example showing how context information is ignored in
clap::Error
's public APIs today, and how exportingError::set_source
would let users construct error messages in the same style as clap's internalTypedValueParser
implementations:Describe the solution you'd like
The easiest and smallest-footprint solution would be to simply make the existing
Error::set_source
method public.When searching for relevant discussions and issues I happened upon #4362, which suggests using
TypedValueParser::try_map
. Unfortunately, this is not suitable forValueParserFactory
implementations that automatically register aTypedValueParser
for a given type, as theTryMapValueParser
type returned fromtry_map
is not public. I've made this type public in #5066.Alternatives, if applicable
There's several other
Error
constructors that would be useful to make public forTypedValueParser
implementers:Error::empty_value
Error::invalid_value
Error::value_validation
Making these public would obviate most of the need for making
Error::set_source
public, or we could provide them separately as helper functions.Additionally, we might consider updating the
clap::Error
constructors to take anOption<&clap::Arg>
instead of aString
as well, because currentlymostall of the use-sites do this:clap/clap_builder/src/builder/value_parser.rs
Lines 857 to 860 in ca855c6
I've implemented this (along with tests and documentation) in #5067, but I'm open to alternatives if anyone has other ideas.
Additional Context
I'm using
clap
for a project where I implementTypedValueParser
andValueParserFactory
for several types. Most recently I usedhumantime::parse_duration
to parse a string like500ms
into aDuration
value:DurationValueParser
codeThis works OK, but when I tested it I noticed that the error messages don't include any context, like which argument failed to validate:
In contrast, when an argument fails to validate for an
EnumValue
I get a nice error message that shows which argument failed and gives a short grammar snippet:We should make it possible for
TypedValueParser
implementers to create the same error messages that clap's internalTypedValueParser
implementations take advantage of.The text was updated successfully, but these errors were encountered: