4

I want one argument to imply another, though they don't take explicit values. --simple-anime or --complex-anime should imply --anime. The API that should work is default_value_ifs, saying that if either of the former is present, --anime will also be true. The problem is that that option turns on takes_value, and if I turn that off, the implication doesn't happen.

Simple example: --dog implies --mammal. Neither one should require a value--it is true if the argument is present.

use clap::Parser;

fn main() {
    let args = Args::parse_from(["prog-name", "--dog"]);
    assert_eq!(args.dog, true);
    assert_eq!(args.mammal, true);
    dbg!(&args);
    
    let args = Args::try_parse_from(["prog-name", "--mammal"]);
    dbg!(&args);
    assert!(matches!(args, Ok(_)));
}


#[derive(Parser, Debug)]
#[clap()]
struct Args {
    //#[clap(long, default_value_if("dog", None, Some("true")), takes_value(false))]
    #[clap(long, default_value_if("dog", None, Some("true")))]
    mammal: bool,

    #[clap(long)]
    dog: bool,
}

Try it in rust playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=4855a88381f65cef8d07f7eab4d41e78

piojo
  • 6,351
  • 1
  • 26
  • 36

2 Answers2

4

Instead of takes_value(false) use min_values(0) (playground):

#[clap(long, default_value_if("dog", None, Some("true")), min_values(0))]
    mammal: bool,

It looks like the default value implementation uses the same code as the values, so if you disable one you disable the other.

rodrigo
  • 94,151
  • 12
  • 143
  • 190
0

The answer @rodrigo posted no longer works with the current version of clap (4.4.0). I fixed it: (playground)

    #[clap(long, default_value_if("dog", IsPresent, Some("true")))]
    mammal: bool,