Clap + yaml question

So I have an application using clap to parse arguments where the cli was beginning to get rather long. I thought I would experiment with splitting the arguments off into a yaml file as described in the documentation. It works fine, but there's one detail I am curious about. Previously I had been using the crate version()! macro in order to keep from having to update version numbers in multiple places. Basically I am wondering if there is a way to do the same with the yaml file method rather than explicitly typing in the version number.

1 Like

Do you know about structopt? It cuts down Clap boilerplate by a lot.

Other than that, how is this related to version numbers? Where/how are you using the version number, and why does it need to be duplicated?

The version number is in Cargo.toml and then repeated again in the yaml file, or in the App definition. Not a huge deal.

I do know about structopt, but haven't used it (yet).

I have a clap application that starts its definition like this

App::new(env!("CARGO_PKG_NAME"))
    .version(env!("CARGO_PKG_VERSION"))
    .author(env!("CARGO_PKG_AUTHORS"))
    .about(env!("CARGO_PKG_DESCRIPTION"))

I imagine OP wants to replicate something like this (as opposed to writing string literals there and having to remember to keep it all up to date) using a yaml definition, but since the yaml is not Rust code you can't just add macro calls there. I think the best way to do it would probably be something like this?

App::from_yaml(yml)
    .name(env!("CARGO_PKG_NAME"))
    .version(env!("CARGO_PKG_VERSION"))
    .author(env!("CARGO_PKG_AUTHORS"))
    .about(env!("CARGO_PKG_DESCRIPTION"))
2 Likes

Actually yes, that does look like a good solution. Thank you.

2 Likes

It took a while to get back to this as I was working on other things. However, here's the (simple) solution in case anyone else wants to know. I removed the version reference from the yaml file, and now my App declaration looks like this:

    let yaml = load_yaml!("cli.yaml");
    let matches = App::from(yaml).version(crate_version!()).get_matches();

Thanks again go to Heliozoa for pointing the way. It turns out that mixing and matching different methods of loading the data does work somewhat. This allows to set the version using the crate_version! macro in main.rs, while keeping the rest of it tucked away in a yaml file, thus keeping the source files nice and tidy.

The more I use and learn Rust the more I'm loving it. At this point I feel limited when trying to go back to C, and a small PyGTK gui I recently knocked together felt like playing with blocks.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.