When using structopt, how to test if the user provided an option or if it comes from the default value?

431 Views Asked by At

I'm using the structopt crate and I have the following struct:

#[derive(Clone, StructOpt, Debug)]
#[structopt(name = "test")]
pub struct CommandlineOptions {
    #[structopt(
    long = "length",
    help = "The length of the the string to generate",
    default_value = "50",
    index = 1
    )]
    pub length: usize,
}


let options = CommandlineOptions::from_args();

If options.length is 50, how can I know it comes from the default value 50, or the user provided a value of 50?

1

There are 1 best solutions below

0
On BEST ANSWER

I don't think it is possible to do this with structopt. The idiomatic way to solve this problem is to instead use an Option<usize> instead of usize (as documented here):

use structopt::StructOpt;

#[derive(Clone, StructOpt, Debug)]
#[structopt(name = "test")]
pub struct CommandlineOptions {
    #[structopt(
    long = "length",
    help = "The length of the the string to generate",
    index = 1
    )]
    pub length: Option<usize>,
}

fn main() {
    let options = CommandlineOptions::from_args();
    println!("Length parameter was supplied: {}, length (with respect to default): {}", options.length.is_some(), options.length.unwrap_or(50));
}

If this does not work in your case somehow, you could also directly work with the clap::ArgMatches struct (structopt is little more than macro magic around clap) to check the number of occurrences of length with ArgMatches::occurrences_of. However, this wouldn't be very idiomatic.

use structopt::StructOpt;

#[derive(Clone, StructOpt, Debug)]
#[structopt(name = "test")]
pub struct CommandlineOptions {
    #[structopt(
    long = "length",
    help = "The length of the the string to generate",
    default_value = "50",
    index = 1
    )]
    pub length: usize,
}

fn main() {
    let matches = CommandlineOptions::clap().get_matches();
    let options = CommandlineOptions::from_clap(&matches);
    
    let length_was_supplied = match matches.occurrences_of("length") {
        0 => false,
        1 => true,
        other => panic!("Number of occurrences is neither 0 nor 1, but {}. This should never happen.", other)
    };
    
    println!("Length parameter was supplied: {}, length (with respect to default): {}", length_was_supplied, options.length);
}