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: modify_fn(user_fn) where fn user_fn<T>(a: Arg) -> Arg generates user_fn::<T>(arg) for fields of type T #2990

Closed
wants to merge 1 commit into from

Conversation

marjakm
Copy link
Contributor

@marjakm marjakm commented Nov 4, 2021

clap changes

Added method to Arg

/// // Instead of this
/// let mut arg = Arg::new("test");
/// arg = func(arg);
///
/// // You can do this
/// let arg = Arg::new("test").modify_fn(func);
/// ```
pub fn modify_fn<F>(self, mod_fn: F) -> Self
where
    F: Fn(Self) -> Self
{
    (mod_fn)(self)
}

A free function

pub fn default_value_t<T>(arg: Arg) -> Arg
where
    T: Default + ToString
{
    let s = make_static_str(<T as Default>::default());
    arg.default_value(s).required(false)
}

clap_derive changes

modify_fn(_) attribute

#[derive(Parser, PartialEq, Debug)]
struct Opt {
    #[clap(modify_fn(clap::default_value_t))]
    arg: i32,
}

Expands to (snippet)

fn augment_args<'b>(__clap_app: clap::App<'b>) -> clap::App<'b> {
    {
        let __clap_app = __clap_app;
        let __clap_app = __clap_app.arg(
            clap::Arg::new("arg")
                .takes_value(true)
                .value_name("ARG")
                .required(true)
                .validator(|s| ::std::str::FromStr::from_str(s).map(|_: i32| ()))
                .modify_fn(clap::default_value_t::<i32>),
        );
        __clap_app
    }
}

Fixes #2991

@pksunkara pksunkara requested a review from epage November 4, 2021 20:24
@marjakm
Copy link
Contributor Author

marjakm commented Nov 4, 2021

@epage Instead of making an Issue, it was easier to implement and show the idea.

By having the default_value_t function in clap crate, it can also be used by those that use the builder pattern instead of clap_derive.

This could also be more performant - the solution before was like a macro, that generated separate code for each Arg instance, but now it can generate the code for each T, but multiple args of the same T can use the same function.

@epage
Copy link
Member

epage commented Nov 4, 2021

I'll take a look, thanks!

@epage Instead of making an Issue, it was easier to implement and show the idea.

The downside is that it couples the conversation to this one PR, so if this PR doesn't work out, its hard to keep it one place.

@marjakm marjakm changed the title Derive attribute: modify_fn(user_fn) where fn user_fn<T>(a: Arg) -> Arg generates user_fn::<T>(arg) for fields of type T Derive attribute: modify_fn(user_fn) where fn user_fn<T>(a: Arg) -> Arg generates user_fn::<T>(arg) for fields of type T Nov 4, 2021
@epage
Copy link
Member

epage commented Nov 4, 2021

Looking at this more, please create an issue and let's make sure we are on the same page on the need and how to solve that need over on that issue. This PR can serve as a tool to help us understand each other in that conversation.

@marjakm
Copy link
Contributor Author

marjakm commented Nov 4, 2021

@epage I created the issue #2991

@epage
Copy link
Member

epage commented Dec 16, 2021

Closing as we work out design in #2991

@epage epage closed this Dec 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Derive attribute that specializes a user-provided function that gets to modify Arg
2 participants