1

我正在寻找一种方法来structopt Vec默认初始化具有多个项目的字段。我可以为单个项目做到这一点:

use structopt::StructOpt;

#[derive(Debug, StructOpt)]
pub struct Cli {
    #[structopt(default_value = "foo")]
    foo: Vec<String>,
}

fn main() {
    let cli = Cli::from_iter(Vec::<String>::new());
    assert_eq!(cli.foo, vec!["foo"]);
}

但是默认情况下如何使cli.foo相等呢?vec!["foo", "bar"]

4

2 回答 2

1

我遵循了 L. Riemer 的建议,似乎FromStr只执行以下操作就足够了:

use structopt::StructOpt;

#[derive(Debug, PartialEq)]
struct Foo(Vec<String>);

impl std::str::FromStr for Foo {
    type Err = Box<dyn std::error::Error>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Foo(s.split(",").map(|x| x.trim().to_owned()).collect()))
    }
}

#[derive(StructOpt)]
pub struct Cli {
    #[structopt(long, default_value = "foo, bar")]
    foo: Foo,
}

fn main() {
    let cli = Cli::from_iter(Vec::<String>::new());
    assert_eq!(cli.foo, Foo(vec!["foo".into(), "bar".into()]));

    let cli = Cli::from_iter(vec!["", "--foo", "foo"]);
    assert_eq!(cli.foo, Foo(vec!["foo".into()]));

    let cli = Cli::from_iter(vec!["", "--foo", "foo,bar,baz"]);
    assert_eq!(cli.foo, Foo(vec!["foo".into(), "bar".into(), "baz".into()]));
}
于 2020-08-26T08:52:38.753 回答
0

我不认为你可以这样做:虽然 StructOpt 有一些关于默认值的技巧,但我希望这仍然以在 CLI 解析中注入默认值结束,就好像它已经明确提供一样,这意味着可能没有办法提供多个默认值(尽管我肯定是错的)。

您可能希望在应用程序级别处理此问题,例如,在解析 CLI 之后,检查 arityfoo并在它为空时更新它。

于 2020-08-26T07:30:58.367 回答