Skip to content
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

Derive attribute that specializes a user-provided function that gets to modify Arg #2991

Closed
2 tasks done
marjakm opened this issue Nov 4, 2021 · 2 comments
Closed
2 tasks done
Labels
A-derive Area: #[derive]` macro API C-enhancement Category: Raise on the bar on expectations S-wont-fix Status: Closed as there is no plan to fix this

Comments

@marjakm
Copy link
Contributor

marjakm commented Nov 4, 2021

Please complete the following tasks

  • I have searched the discussions
  • I have searched the existing issues

Clap Version

master 879dd23

Describe your use case

I have a bunch of messages defined in protobuf, I'd like to make a CLI to send those messages - clap should be able to parse the messages from terminal. I generate rust structs from protobuf definitions using prost and I can automatically add clap_derive attributes, but I can't specify the attributes flexibly enough to solve my use-case.

Problematic cases are when one struct contains another optional struct:

struct A {
   simple: u32,
   inner: Option<B>
}

struct B {
   a: u32,
   b: String,
}

When automatically adding attributes, I can differentiate between protobuf native (u32, bool, ..) types and complex types (another struct), but I don't know if the complex type is Option<B> or Option<C>.

What I want is to parse these complex types (for example A::inner) from from json string from the command line. The default value in this case should be None (empty string), which is simple enough to implement currently. But, I'd also like to generate an example json value for the Some case in the CLI help. But what annotation can I add to the field A::inner, where I only know that its a optional struct, but don't know which struct type (B or C) it actually is?

Its really easy for me to write a function to generate the string:

fn example_json<T: serde::Serialize>(t: T) -> &'static str { todo!() } 

All I'd need to have some attribute in clap_derive to call that function and I don't need to know which type is A::inner

#[derive(clap::Parser)]
struct A {
   simple: u32,
   #[clap(about = example_json]
   inner: Option<B>
}

which should call something like this in the right place:

Arg::about(arg, example_json::<Option<B>>())

default_value_t attribute actually does exactly the type-based fn specialization - I'd just like to be able to provide the generic fn and have it specialized by the field type.

Describe the solution you'd like

I implemented something that would solve my problems here:

#2990

Alternatives, if applicable

No response

Additional Context

Conversation started on #2813

@epage
Copy link
Member

epage commented Nov 4, 2021

Thank you! This context helps a lot!

So you are wanting to determine the value for an attribute based on the type of the field it is applied to, with the example being given of dynamically generating about, instead of manually doing it, to help with your code-gen use case.

This seems quite specialized. The first question to answer is if this is needed and then the second is how.

A key part stuck out in your comment

I don't know if the complex type is Option<B> or Option<C>.

This is what is leading you to wanting to defer to clap to generate this information. Could you help me understand this problem a little more? I'm wanting to learn more about how this clap struct generation is happening to see how all of this fits together and if there is a better, more general solution here.

If we do move forward with this, clap::Arg::modify_fn doesn't quite make sense on its own, only in the context of clap_derive. I wonder if we can instead do this purely within clap_derive.

Its also unclear how #2683 might impact any API design on clap in the future.

@epage epage added C-enhancement Category: Raise on the bar on expectations A-derive Area: #[derive]` macro API S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed T: new feature labels Dec 8, 2021
@epage
Copy link
Member

epage commented Jan 11, 2022

At this time, this seems too specialized. Going to close in this in favor of other options helping in the future, like #2683

@epage epage closed this as completed Jan 11, 2022
@epage epage added S-wont-fix Status: Closed as there is no plan to fix this and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jan 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-derive Area: #[derive]` macro API C-enhancement Category: Raise on the bar on expectations S-wont-fix Status: Closed as there is no plan to fix this
Projects
None yet
2 participants