clap icon indicating copy to clipboard operation
clap copied to clipboard

Support multiple positionals with fixed sizes

Open superstator opened this issue 4 months ago • 1 comments

Please complete the following tasks

Clap Version

4.5.4

Describe your use case

I want to build a CLI in Rust, using clap, which can accept some number of positional arguments with a set number of values each, and a final argument accepting whatever positional values were left over. For example, ./app a b c with a positional argument accepting 2 values, and a positional argument accepting leftovers, would assign a b to the first arg, and c to the second. I'm able to do this with a positional argument that accepts a single value:

        let cmd = Command::new("main")
            .arg(Arg::new("ONE").action(ArgAction::Set).num_args(1))
            .arg(Arg::new("TWO").action(ArgAction::Append));

        let matches = cmd.get_matches_from(&["bin","a","b","c"]);

        assert_eq!(matches.get_many::<String>("ONE").unwrap().collect::<Vec<_>>(), &["a"]);
        assert_eq!(matches.get_many::<String>("TWO").unwrap().collect::<Vec<_>>(), &["b","c"]);

But if I try to have the first arg accept two values like this:

        let cmd = Command::new("main")
            .arg(Arg::new("ONE").action(ArgAction::Set).num_args(2))
            .arg(Arg::new("TWO").action(ArgAction::Append));

        let matches = cmd.get_matches_from(&["bin","a","b","c"]);

        assert_eq!(matches.get_many::<String>("ONE").unwrap().collect::<Vec<_>>(), &["a","b"]);
        assert_eq!(matches.get_many::<String>("TWO").unwrap().collect::<Vec<_>>(), &["c"]);

I get the error Positional argument [TWO]... *must* have required(true) or last(true) set because a prior positional argument ([ONE] [ONE]) has num_args(1..). If I make argument TWO required, I just get a different error, and if I make them both required the last argument is always attached to TWO, making it impossible to accept something like ./app a b or ./app a b c d and still have ONE capture the first two values.

Describe the solution you'd like

Allow for one or more positional arguments that capture a fixed number of items, plus a "final" positional that can capture 0.. items.

Alternatives, if applicable

No response

Additional Context

No response

superstator avatar Apr 18 '24 14:04 superstator