clap - 如何在返回 ArgMatches<'static> 时传递 default_value
clap - how to pass a default_value when returning ArgMatches<'static>
为了减少代码行,我将 clap App
移动到另一个文件,内容如下:
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> {...}
生命周期不再是'static
,但是不能是'static
(除非你选择泄漏 您正在配置 App
的字符串)。相反,如果您需要一个比 ArgParser
寿命更长的字符串,请使用 .to_owned()
将 &'a str
转换为可以独立生存的 String
。
为了减少代码行,我将 clap App
移动到另一个文件,内容如下:
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> {...}
生命周期不再是'static
,但是不能是'static
(除非你选择泄漏 您正在配置 App
的字符串)。相反,如果您需要一个比 ArgParser
寿命更长的字符串,请使用 .to_owned()
将 &'a str
转换为可以独立生存的 String
。