rust - clap - 返回 ArgMatches<'static> 时如何传递 default_value

标签 rust clap

为了减少代码行数,我移动了 clap App 到另一个文件,如下所示:

playground

use clap::{App, AppSettings, Arg, ArgMatches}; // 2.33.3
use std::path::Path;

fn main() {
    let s3m_dir = Path::new("/tmp").join(".s3m");

    let matches = get_matches(s3m_dir.display().to_string());
    println!("{:#?}", matches);
}

pub fn get_matches(home_dir: String) -> ArgMatches<'static> {
    App::new("s3m")
        .version(env!("CARGO_PKG_VERSION"))
        .setting(AppSettings::SubcommandsNegateReqs)
        .after_help(format!("foo bar: {}", home_dir).as_ref())
        .arg(
            Arg::with_name("config")
                .help("config.yml")
                .long("config")
                .short("c")
                .default_value(&format!("{}/.s3m/config.yml", home_dir))
                .required(true)
                .value_name("config.yml"),
        )
        .get_matches()
}

我遇到的问题是我不知道如何使用参数 home_dir 作为 default_value,这里:

.default_value(&format!("{}/.s3m/config.yml", home_dir))

default_value 的签名是:

pub fn default_value(self, val: &'a str) -> Self

如何传递 format!("{}/.s3m/config.yml", home_dir 以及 other 的生命周期以满足签名?

最佳答案

我没有使用过 clap,所以可能有更好的方法,但是 Rust 解决这个问题的一般方法是拥有一些拥有所需字符串的数据结构,以便 ArgMatches 可以有一个依赖于它的生命周期:

struct ArgParser {
    home_dir: PathBuf,
    default_config: OsString,
}

impl ArgParser {
    pub fn new(home_dir: &Path) -> Self {
        let default_config_path: PathBuf = home_dir.join(".s3m/config.yml");
        Self {
            home_dir: home_dir.to_owned(),
            default_config: default_config_path.as_os_str().to_owned(),
        }
    }

我还调整了配置路径以使用 Path::join 而不是字符串格式,并使用 OsString 而不是 String,它们是实际上与您的问题无关,但应该更正确。

现在我们可以修改 get_matches 来处理这个问题,作为 impl ArgParser 的一部分:


    pub fn get_matches(&self) -> ArgMatches {
        App::new("s3m")
            .version(env!("CARGO_PKG_VERSION"))
            .setting(AppSettings::SubcommandsNegateReqs)
            .after_help(format!("foo bar: {}", self.home_dir.display()).as_ref())
            .arg(
                Arg::with_name("config")
                    .help("config.yml")
                    .long("config")
                    .short("c")
                    .default_value_os(&self.default_config)
                    .required(true)
                    .value_name("config.yml"),
            )
            .get_matches()
    }
}

请注意,ArgMatches 没有给出生命周期参数。这是因为编译器会自动为我们推断生命周期,就像我们写的一样:

pub fn get_matches<'a>(&'a self) -> ArgMatches<'a> {...}

生命周期不再是'静态,但它不能'静态(除非您选择泄漏 您配置 App 所用的字符串)。相反,如果您需要一个字符串的生命周期比 ArgParser 更长,请使用 .to_owned()&'a str 转换为 String 可以独立生存。

playground

关于rust - clap - 返回 ArgMatches<'static> 时如何传递 default_value,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65303960/

相关文章:

rust - 如何使用 Clap 提供多行帮助消息?

rust - 如何使用structopt将不可能的值附加到结构上?

rust - 如何使用Clap指定 bool 命令行标志?

rust - 如何在 Fedora 26 上卸载 Rust?

java - 将枚举类型从 Rust 转换为 Java

error-handling - 将错误从 `try_into()` 转换为自定义错误

rust - 用不同大小的类型调用 transmute

rust - "where for"在 Rust 中意味着什么?

rust - 如何在不需要显式值的情况下使一个论点暗示另一个论点? (--foo,不是--foo true)

rust - 如何防止最后一个参数需要用 clap 引用?