Markus Grunwald
Markus Grunwald

Reputation: 333

With clap v4 how can I set up multiple exclusive non-bool options?

This is a minimal version of an example from the clap crate:

use clap::{Args, Parser};

#[derive(Parser)]
#[command(version, about, long_about = None)]
struct Cli {
    #[command(flatten)]
    exclusive: Exclusive,
}

#[derive(Args)]
#[group(required = true, multiple = false)]
struct Exclusive {
    #[arg(short)]
    a: bool,

    #[arg(short)]
    b: bool,
}

fn main() {
    let _ = Cli::parse();
}

It works just like described in the docs: I can cargo run -- -a or cargo run -- -b, but not cargo run -- -a -b.

Now I would like to have options that are not bools but u8s, for example (just s/bool/u8/g of the above code):

use clap::{Args, Parser};

#[derive(Parser)]
#[command(version, about, long_about = None)]
struct Cli {
    #[command(flatten)]
    exclusive: Exclusive,
}

#[derive(Args)]
#[group(required = true, multiple = false)]
struct Exclusive {
    #[arg(short)]
    a: u8,

    #[arg(short)]
    b: u8,
}

fn main() {
    let _ = Cli::parse();
}

But that doesn't work at all:

± cargo run -- --help
Usage: bla <-a <A>|-b <B>>

Options:
  -a <A>         
  -b <B>         
  -h, --help     Print help
  -V, --version  Print version

± cargo run -- -a 1  
error: The following required argument was not provided: b

Usage: bla <-a <A>|-b <B>>

± cargo run -- -b 1
error: The following required argument was not provided: a

Usage: bla <-a <A>|-b <B>>

± cargo run -- -a 1 -b 2
error: the argument '-a <A>' cannot be used with '-b <B>'

Usage: bla <-a <A>|-b <B>>

Help looks okay, but there's no way to pass a valid parameter. What's wrong with my code?

Upvotes: 3

Views: 51

Answers (1)

Markus Grunwald
Markus Grunwald

Reputation: 333

The problem is solved by making the arguments optional:

#[derive(Args)]
#[group(required = true, multiple = false)]
struct Exclusive {
    #[arg(short)]
    a: Option<u8>,

    #[arg(short)]
    b: Option<u8>,
}

Upvotes: 6

Related Questions