Search code examples
rustclap

clap default value - how to use it


Playing with Rusts clap crate for the first time. And I wonder how to use the default value of a command line option, when the option was not specified at the command line.

Given I specified a default_value in the yaml file (see snippet below), I expected the matches.value_of("VERBOSE") to return the default value if there is no other value given in the command line.

Instead, I get:

thread 'main' panicked at 'called Option::unwrap() on a None value', src/main.rs:18:6

I was googling for a while but it seems, no one really gives a canonical example of how it is supposed to work.

...
args:
  - config:
      short: c
      long: config
      value_name: CONFIG
      help: Specifies the config file to use.
      takes_value: true
      default_value: ""
  - verbose:
      short: v
      long: verbose
      value_name: VERBOSE
      help: Sets verbosity. 0 = silent, > 0 = verbose.
      takes_value: true
      default_value: "1"

Here, my feeble attempt... compiling but not working (panics if empty command line is used).

// ...
    let yaml = load_yaml!("cli.yml");
    let matches = App::from_yaml(yaml).get_matches();
    let verbosity =
    matches.value_of("VERBOSE")
    .and_then(|s| s.parse::<u8>().ok())
    .unwrap();

As this obviously does not use the default values, my simple question is: How do I do it right?


Solution

  • The problem is you either have a small misconception about what value_name (which is used only for the CLI help option) is, or you missed, that the argument names are case sensitive.

    You have two options to make this work as expected:

    1. Use the lowercase argument name as specified in the YAML (change .rs):

    YAML:

    ...
    args:
      - config:
          short: c
          long: config
          value_name: CONFIG
          help: Specifies the config file to use.
          takes_value: true
          default_value: "1"
      - verbose:
          short: v
          long: verbose
          value_name: VERBOSE
          help: Sets verbosity. 0 = silent, > 0 = verbose.
          takes_value: true
          default_value: "1"
    

    Rust:

    use clap::{load_yaml, App};
    
    fn main() {
        let yaml = load_yaml!("cli.yml");
        let matches = App::from_yaml(yaml).get_matches();
        let verbosity =
        matches.value_of("verbose")
        .and_then(|s| s.parse::<u8>().ok())
        .unwrap();
        println!("{}", verbosity);
    }
    
    1. Use the uppercase name as specified in the Code (change .yaml): YAML:
    ...
    args:
      - config:
          short: c
          long: config
          value_name: CONFIG
          help: Specifies the config file to use.
          takes_value: true
          default_value: "1"
      - VERBOSE:
          short: v
          long: verbose
          value_name: VERBOSE
          help: Sets verbosity. 0 = silent, > 0 = verbose.
          takes_value: true
          default_value: "1"
    

    Rust

    use clap::{load_yaml, App};
    
    fn main() {
        let yaml = load_yaml!("cli.yml");
        let matches = App::from_yaml(yaml).get_matches();
        let verbosity =
        matches.value_of("VERBOSE")
        .and_then(|s| s.parse::<u8>().ok())
        .unwrap();
        println!("{}", verbosity);
    }