23

I want to add a command line flag. It's a flag, so it does not take an argument, it is either present or not. I also need to know how to read the flag, either TRUE or FALSE.

This is the code for defining the flag:

.arg(
    Arg::with_name("metal")
        .long("metal-micky")
        .required(false)
        .help("I want metal micky"),
)

I am trying to read the value like this:

let z = matches.value_of("metal");

However it is resulting in None when I print it:

println!("FLAG: {:?}", z);

It is None even when I specify the flag on the command line.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Peter Prographo
  • 1,141
  • 1
  • 10
  • 27

4 Answers4

25

Don't know if this is the "approved" method but I use Args::takes_value:

.arg(
    Arg::with_name("metal")
        .long("metal-micky")
        .required(false)
        .takes_value(false)
        .help("I want metal micky"),
)

Then check if the flag was passed with matches.is_present("metal")

Evan Carroll
  • 78,363
  • 46
  • 261
  • 468
yorodm
  • 4,359
  • 24
  • 32
  • In current Clap stable version this answer is outdated. Check out ciresh's one. To be short: replace `takes_value(false)` with `num_args(0)`. – Scolopendre Jan 26 '23 at 14:33
16

This can be done with the action attribute. If your field is a bool then by default the action selected is ArgAction::SetTrue.

This is quite nice since you don't need to set a value when you call the argument. It sets the value by default to true if used and false if not used when running the program.

use clap::Parser;

/// This is a simple program
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct Args {
   /// It just works!
   #[clap(long, short, action)]
   it_just_works: bool,
}

fn main() {
   let args = Args::parse();

    println!("It just works {}!", args.it_just_works)
}

To change the default behavior you can do this:

#[clap(long, short, action=ArgAction::SetFalse)]

Docs.

kemicofa ghost
  • 16,349
  • 8
  • 82
  • 131
12

The currently accepted answer is slightly outdated, you no longer have to specify required(false) when you specify takes_value(false). So, what you need is:

.arg(
    Arg::with_name("metal")
        .long("metal-micky")
        .takes_value(false)
        .help("I want metal mickey")

and check the presence with matches.is_present("metal").

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
Digant C Kasundra
  • 1,606
  • 2
  • 17
  • 27
6

The builder based answers are both out of date. with_name() has been replace with new() in 3.0 and takes_value() has been replace with num_args() in 4.0. Also is_present() has been replace with contains_id() in 3.2. The new version would be:

.arg(
     Arg::new("metal")
        .long("metal-micky")
        .required(false)
        .num_args(0)
        .help("I want metal micky"),
)

Check if the flag was passed with contains_id()

ciresh
  • 61
  • 1
  • 1