3

我正在使用clap编写 CLI来解析我的参数。我想为选项提供默认值,但如果有一个配置文件,配置文件应该战胜默认值。

将命令行参数优先于默认值很容易,但我想要以下优先顺序:

  1. 命令行参数
  2. 配置文件
  3. 默认值

如果配置文件不是由命令行选项设置的,那么设置它也很容易,只需在运行之前解析配置文件parse_args,并将解析的配置文件中的值提供到default_value. 问题是,如果在命令行中指定配置文件,则在解析之后才能更改默认值。

我能想到的唯一方法是不设置 adefault_value然后手动匹配"". value_of问题是,在这种情况下,clap 将无法构建有用的--help.

有没有办法让拍手读取配置文件本身?

4

1 回答 1

4

来自 clap 的文档default_value

注意:如果用户在运行时不使用这个参数,ArgMatches::is_present仍然会返回 true。如果您希望确定参数是否在运行时使用,请考虑如果在运行时未使用参数ArgMatches::occurrences_of,将返回哪个0

https://docs.rs/clap/2.32.0/clap/struct.Arg.html#method.default_value

这可用于获取您描述的行为:

extern crate clap;
use clap::{App, Arg};
use std::fs::File;
use std::io::prelude::*;

fn main() {
    let matches = App::new("MyApp")
        .version("0.1.0")
        .about("Example for StackOverflow")
        .arg(
            Arg::with_name("config")
                .short("c")
                .long("config")
                .value_name("FILE")
                .help("Sets a custom config file"),
        )
        .arg(
            Arg::with_name("example")
                .short("e")
                .long("example")
                .help("Sets an example parameter")
                .default_value("default_value")
                .takes_value(true),
        )
        .get_matches();

    let mut value = String::new();

    if let Some(c) = matches.value_of("config") {
        let file = File::open(c);
        match file {
            Ok(mut f) => {
                // Note: I have a file `config.txt` that has contents `file_value`
                f.read_to_string(&mut value).expect("Error reading value");
            }
            Err(_) => println!("Error reading file"),
        }

        // Note: this lets us override the config file value with the
        // cli argument, if provided
        if matches.occurrences_of("example") > 0 {
            value = matches.value_of("example").unwrap().to_string();
        }
    } else {
        value = matches.value_of("example").unwrap().to_string();
    }

    println!("Value for config: {}", value);
}

// Code above licensed CC0
// https://creativecommons.org/share-your-work/public-domain/cc0/ 

导致行为:

./target/debug/example
Value for config: default_value
./target/debug/example --example cli_value
Value for config: cli_value
./target/debug/example --config config.txt
Value for config: file_value
./target/debug/example --example cli_value --config config.txt
Value for config: cli_value
于 2019-03-13T04:20:19.677 回答