Use Multiple values in clap by allowing multiple values

let command = Command::new("hey")
        .version("1.0")
        .author("Hariprasath")
        .about("Cli Used for generating using gemini")
        .subcommand(
            Command::new("tell")
                .about("Used to ask gemini")
                .arg(Arg::new("prompt").required(true)),
        )
        .get_matches();

Are you looking for Arg::num_args?

need to get multiple args from arg in single tell id

Could you be a bit more specific please? What do you want your CLI to look like? Could you provide us with an example? I was expecting you to want a CLI like this:

hey tell "prompt 1" "prompt2" "prompt 3"

which you can do by setting the num_args of your tell subcommand's positional arguments to 1..:

use clap::{Arg, Command};

fn main() {
    let matches = Command::new("hey")
        .version("1.0")
        .author("Hariprasath")
        .about("Cli Used for generating using gemini")
        .subcommand(
            Command::new("tell")
                .about("Used to ask gemini")
                .arg(Arg::new("prompt").num_args(1..)),
        )
        .get_matches_from(vec!["hey", "tell", "prompt 1", "prompt 2", "prompt 3"]);

    match matches.subcommand() {
        Some(("tell", args)) => {
            let prompts: Vec<String> = args.get_many("prompt").unwrap().cloned().collect();
            println!("{prompts:?}");
        }
        _ => panic!(),
    }
}

Playground.

like hey tell prompt1
here i dont need to use string to iinclude prompt
the prompt can be dynamic in size so get prompt in single line
like hey tell todays date => here todays date is getting from user in no ""

That'd still work for most cases, unless your words contain quotation marks, i.e. your user would need to write it is instead of it's for example. Pretty much like the interface of the echo command. Whitespaces are treated as delimiters, so to get a single sentence from multiple words you pass as arguments to tell you can just .join(" ") them together:

use clap::{Arg, Command};
use itertools::Itertools;

fn main() {
    let matches = Command::new("hey")
        .version("1.0")
        .author("Hariprasath")
        .about("Cli Used for generating using gemini")
        .subcommand(
            Command::new("tell")
                .about("Used to ask gemini")
                .arg(Arg::new("prompt").num_args(1..)),
        )
        .get_matches_from(vec![
            "hey", "tell", "prompt", "1", "prompt", "2", "prompt", "3",
        ]);

    match matches.subcommand() {
        Some(("tell", args)) => {
            let sentence = args.get_many::<String>("prompt").unwrap().join(" ");
            assert_eq!(sentence, "prompt 1 prompt 2 prompt 3".to_owned());
        }
        _ => panic!(),
    }
}

Playground.

code like this ? appends all values after tell* then use like values

let command = Command::new("hey")
        .version("1.0")
        .author("Hariprasath")
        .about("Cli Used for generating using gemini")
        .subcommand(
            Command::new("tell").about("Used to ask gemini").arg(
                Arg::new("prompt")
                    .required(true)
                    .action(clap::ArgAction::Append),
            ),
        )
        .get_matches();

.required(true) with .action(ArgAction::Append) does the same as .num_args(1..) AFAICT. You can try it yourself on the playground.

1 Like

yep
got it !

Please don't forget to mark one of @jofas' replies as the solution.

1 Like