正确解析Clap ArgMatches的惯用锈方法

时间:2019-10-14 06:26:50

标签: rust clap

我正在学习rust并尝试进行类似实用程序的查找(是的,是另一种方法),即时通讯使用clap并尝试支持命令行和配置文件作为程序参数(与clap yml文件无关)

我正在尝试解析命令,如果没有命令传递给应用程序,我将尝试从配置文件中加载它们。 现在我不知道该怎么做。

fn main() {
    let matches = App::new("findx")
        .version(crate_version!())
        .author(crate_authors!())
        .about("find + directory operations utility")
        .arg(
            Arg::with_name("paths")
               ...
        )
        .arg(
            Arg::with_name("patterns")
              ...
        )
        .arg(
            Arg::with_name("operation")
            ...
        )
        .get_matches();
    let paths;
    let patterns;
    let operation;
    if matches.is_present("patterns") && matches.is_present("operation") {
        patterns = matches.values_of("patterns").unwrap().collect();
        paths = matches.values_of("paths").unwrap_or(clap::Values<&str>{"./"}).collect(); // this doesn't work
        operation = match matches.value_of("operation").unwrap() { // I dont like this
            "Append" => Operation::Append,
            "Prepend" => Operation::Prepend,
            "Rename" => Operation::Rename,
            _ => {
                print!("Operation unsupported");
                process::exit(1);
            }
        };
    }else if Path::new("findx.yml").is_file(){
        //TODO: try load from config file
    }else{
        eprintln!("Command line parameters or findx.yml file must be provided");
        process::exit(1);
    }


    if let Err(e) = findx::run(Config {
        paths: paths,
        patterns: patterns,
        operation: operation,
    }) {
        eprintln!("Application error: {}", e);
        process::exit(1);
    }
}

有一种惯用的方法可以将OptionResult类型的值提取到相同的范围,我的意思是我已阅读的所有示例都使用matchif let Some(x)在模式匹配的范围内消耗x值,但是我需要将该值分配给变量。

有人可以帮我这个忙,或者为我指明正确的方向吗?

最好的问候

1 个答案:

答案 0 :(得分:1)

我个人认为使用match语句并将其折叠或放置在其他函数中没有任何问题。但是,如果要删除它,则有很多选择。

可以使用.default_value_if()impl的{​​{1}}方法,并根据匹配的匹配臂使用不同的默认值。

clap documentation

clap::Arg

此外,您可以在//sets value of arg "other" to "default" if value of "--opt" is "special" let m = App::new("prog") .arg(Arg::with_name("opt") .takes_value(true) .long("opt")) .arg(Arg::with_name("other") .long("other") .default_value_if("opt", Some("special"), "default")) .get_matches_from(vec![ "prog", "--opt", "special" ]); assert_eq!(m.value_of("other"), Some("default")); 中添加验证器,或将有效的操作值转换为标志。

这是一个将您的匹配臂值转换为单独标志的示例(为清楚起见,此示例较小)。

operation

我希望这会有所帮助!

编辑:

您也可以将Subcommands用于特定的操作。这完全取决于您想要的界面风格。

extern crate clap;

use clap::{Arg,App};

fn command_line_interface<'a>() -> clap::ArgMatches<'a> {
    //Sets the command line interface of the program.
    App::new("something")
            .version("0.1")
            .arg(Arg::with_name("rename")
                 .help("renames something")
                 .short("r")
                 .long("rename"))
            .arg(Arg::with_name("prepend")
                 .help("prepends something")
                 .short("p")
                 .long("prepend"))
            .arg(Arg::with_name("append")
                 .help("appends something")
                 .short("a")
                 .long("append"))
            .get_matches()
}

#[derive(Debug)]
enum Operation {
    Rename,
    Append,
    Prepend,
}


fn main() {
    let matches  = command_line_interface();

    let operation = if matches.is_present("rename") {
        Operation::Rename
    } else if matches.is_present("prepend"){
        Operation::Prepend
    } else {
        //DEFAULT
        Operation::Append
    };
    println!("Value of operation is {:?}",operation);
}