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

Feature request: Add support for multiple required arguments, e.g. [-u <mode> <file> <mime>] #88

Closed
Byron opened this issue Apr 29, 2015 · 5 comments

Comments

@Byron
Copy link
Contributor

Byron commented Apr 29, 2015

I need to support an optional argument like the one noted in the subject, but was unable to achieve this. Apparently there is no support for multiple arguments of a single flag. docopt can do this though, and I believe its a useful feature to have.

A workaround I tried was to use the Arg::requires() method to enforce flags to appear together. However, a doubly-linked requires definition doesn't seem to work. For example, in the following excerpt I want -u to appear with -f and vice-versa.

➜  google-apis-rs git:(clap) ✗ make groupsmigration1-cli-cargo ARGS="run -- archive insert groupid -h"
cd gen/groupsmigration1-cli && cargo run -- archive insert groupid -h
     Running `target/debug/groupsmigration1 archive insert groupid -h`
groupsmigration1-archive-insert
Inserts a new mail into the archive of the Google group.

USAGE:
    groupsmigration1 archive insert [FLAGS] [OPTIONS] <group-id>

FLAGS:
    -h, --help       Prints help information
    -v, --version    Prints version information

OPTIONS:
    -f <file>       The file to upload
    -u <mode>       Specify which file to upload [values: resumable simple]
    -o <out>        Specify the file into which to write the programs output
    -p <v>...       Set various fields of the request structure

POSITIONAL ARGUMENTS:
    group-id    The group ID

In code, this looks like this (example is manufactured, and not actual code, might not compile)

let mut uarg = Arg::with_name("u").required(false).takes_value(true);
uarg = uarg.requires("file");
farg = Arg::with_name("file")
           .short("f")
           .required(false)
           .requires("u")
           .takes_value(true));

Maybe I am doing it wrong though. The code above results in runtime errors like this:

➜  google-apis-rs git:(clap) ✗ make groupsmigration1-cli-cargo ARGS="run -- archive insert groupid -u simple -f file"
cd gen/groupsmigration1-cli && cargo run -- archive insert groupid -u simple -f file
     Running `target/debug/groupsmigration1 archive insert groupid -u simple -f file`
One or more required arguments were not supplied
USAGE:
    groupsmigration1 archive insert [FLAGS] [OPTIONS] -f <file>  <group-id>
For more information try --help

In any case, it would be very helpful to print which dependencies are actually missing :).
Thanks for your help !

Byron added a commit to Byron/google-apis-rs that referenced this issue Apr 29, 2015
We can't have the `-u <mode> <file> <mime>` style yet, but
clap-rs/clap#88 might help with that
at some point.

Related to #92 and #81
@kbknapp
Copy link
Member

kbknapp commented Apr 29, 2015

Ok, I'll have look at how best (most ergonomically) do this. In the mean time, the requires() is correct. Here's what I just tested (using Arg::from_usage() just for brevity)

let modes = ["resumable", "simple"];
let _ = App::new("app")
                  .arg(Arg::from_usage("-u [mode] 'the mode'").possible_values(&modes).requires("file"))
                  .arg(Arg:from_usage("-f [file] 'the file'").requires("mode"))
                  .arg_from_usage("<group-id> 'the group id'")
                  .get_matches();

This works by if the user does a -f they must also do -u and vice versa. And group-id is required regardless.

Also, in ref to your last statement, that's exactly what I plan with #82 👍 It does this minimally right now (i.e. based off your current usage in the example, -f and <group-id> are required (it doesn't list -u because it already matched that). Come to think of it, what does the definition of the <group-id> look like? that may be the issue you're experiencing.

But I plan on making it much clearer in the very near future.

@Byron
Copy link
Contributor Author

Byron commented Apr 29, 2015

Thanks for much for having a look ! I will try that once again, tomorrow (note to self). Must have been some silly mistake on my side, amplified by #82 - if it would tell you the possible values of the required flag, it would have been clear which name to put there.
'' is just required and has no flag. takes_value(true) might also be called on it - but I don't know for sure as the code that does it is this one.

I will be working like a maniac until 15th of May, and am sure the few remaining kinks will be etched out until then. Generally clap is great, so are the docs ... and you even do videos :) ! Well done - I'd be surprised if clap wouldn't become the defacto standard command-line parser for Rust.

@kbknapp
Copy link
Member

kbknapp commented Apr 30, 2015

Mistakenly closed by commit message

@kbknapp kbknapp reopened this Apr 30, 2015
@kbknapp
Copy link
Member

kbknapp commented May 1, 2015

This is closed with v0.7.1 on crates.io

See the new docs or #89 for details on the changes - it should help out! Also, I'm quite happy with the new smarter usage strings which take the current attempted usage as a template for what's required, not just the defaults.

@Byron
Copy link
Contributor Author

Byron commented May 2, 2015

Thank you, this defintely works now. I could also verify that -r foo bar baz is working similarly to -r foo -r bar -r baz. Good work.
Only the smarter usage strings didn't work for me yet, I have made an issue to show what I mean.

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

No branches or pull requests

2 participants