Clap: how to parse `mv <files>... <target>`?

Created on 1 Nov 2016  路  9Comments  路  Source: clap-rs/clap

E.g.: mv a1 a2 a3/

I use the code like this:

let m = App::new()
  .arg(Arg::with_name("files").required(true).multiple(true))
  .arg(Arg::with_name("target").required(true))
  .get_matches();

When input mv a1 a2 a3/, I expect result like this:

{
  files: ["a1", "a2"],
  target: "a3",
}

But I got a error:

error: The following required arguments were not provided:
    <target>
args parsing nice to have RFC / question enhancement 2.x

Most helpful comment

It's fixed in #730 :wink:

All 9 comments

This is because there's no way to know when <files> ends and <target> starts. Positional arguments that take multiple values must be the _last_ positional argument.

There are two ways to fix this, either swap the arguments (i.e. <target> <files>...) or limit the number of values to a fixed number (i.e. <file> <file> <target>). Obviously one of those solutions is less viable than the other (fixed number of files), but it's still an option.

Hope this helps! I'm also open to suggestions :wink:

Also, thinking about this a little more, there may be a way I could add this feature. Let me play with some implementations and get back with you!

I found a way to make this work, after #727 merges I'll upload v2.17.0 to crates.io

At which point this will give the expected results:

let m = App::new()
  .arg(Arg::with_name("files").required(true).multiple(true))
  .arg(Arg::with_name("target").required(true))
  .get_matches();

@hh9527 v2.17.0 is up on crates.io now

waooo, it is so nice of you! thank you for this great project!

@kbknapp I have tried v2.17.0, it works without subcommand, but still break in subcommand.

This works:

    let m = App::new("mv")
        .arg(Arg::with_name("paths").required(true).multiple(true))
        .arg(Arg::with_name("target").required(true))
        .get_matches();

And this not:

    let m = App::new("cli")
        .subcommand(
            SubCommand::with_name("mv")
                .arg(Arg::with_name("paths").required(true).multiple(true))
                .arg(Arg::with_name("target").required(true))
        ).get_matches();

Ah, thanks for pointing this out, I hadn't testsed it _after_ a subcommand, only before!

It's fixed in #730 :wink:

v2.17.1 is up now!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Licenser picture Licenser  路  25Comments

kbknapp picture kbknapp  路  23Comments

ruabmbua picture ruabmbua  路  17Comments

CAD97 picture CAD97  路  21Comments

pickfire picture pickfire  路  21Comments