Marvin Mednick
Marvin Mednick

Reputation: 349

How to get clap to process a single argument with multiple values without having to specify the flag multiple times?

I would like to have a command such that do_something --list 1 2 3 would result in the field in the struct being set to [1, 2, 3].

The following code works for do_something --list 1 --list 2 --list 3:

use clap::Parser; // 3.2.8

#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
pub struct Cli {
    #[clap(short, long, value_parser)]
    pub list: Option<Vec<i32>>,
}

fn main() {
    let cli = Cli::parse();
    println!("CLI is {:#?}", cli);
}

When I use --list 1 2 3, it gives me the error:

error: Found argument '2' which wasn't expected, or isn't valid in this context

I've also tried --list "1 2 3" and --list 1,2,3 but get errors for those as well.

I was also able to get multiple values to work as a positional argument, but not as a Option with a flag.

Is --list 1 2 3 something that clap supports? I thought this was supported by clap's multiple values. Is there something missing in my setup/code or my command line input?

Upvotes: 14

Views: 13179

Answers (2)

Steve Lau
Steve Lau

Reputation: 1033

In clap 4.2.7, use_value_delimiter is deprecated, which means the accepted answer no longer works, instead, you should use num_args = 1..

use clap::Parser; // 4.2.7

#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
pub struct Cli {
    #[clap(short, long, value_delimiter = ' ', num_args = 1..)]
    pub list: Option<Vec<i32>>,
}

fn main() {
    let cli = Cli::parse();
    println!("CLI is {:#?}", cli);
}
$ cargo b
$ ./target/debug/rust --list 1 2 3
CLI is Cli {
    list: Some(
        [
            1,
            2,
            3,
        ],
    ),
}

Upvotes: 25

PitaJ
PitaJ

Reputation: 15084

You're looking for the use_value_delimiter setting. Set use_value_delimiter = true and set the actual delimiter to use with value_delimiter = ','.

Upvotes: 14

Related Questions