J'aimerais que StructOpt
fonctionne avec des énumérations de telle sorte que chaque fois qu'un utilisateur passe -d dimanche
, il soit analysé comme un Day :: Sunday
:
fn parse_day(day: &str) -> Result<Day, ParseError> { match day { "sunday" => Ok(Day::Sunday), _ => Ok(Day::Monday) } Err("Could not parse a day") }
Ma meilleure solution actuelle consiste à utiliser Option
comme type et à passer un parse_day ()
:
#[macro_use] extern crate structopt; use std::path::PathBuf; use structopt::StructOpt; // My enum enum Day { Sunday, Monday } #[derive(Debug, StructOpt)] #[structopt(name = "example", about = "An example of StructOpt usage.")] struct Opt { /// Set speed #[structopt(short = "s", long = "speed", default_value = "42")] speed: f64, /// Input file #[structopt(parse(from_os_str))] input: PathBuf, /// Day of the week #[structopt(short = "d", long = "day", default_value = Day::Monday)] day: Day, } fn main() { let opt = Opt::from_args(); println!("{:?}", opt); }
3 Réponses :
Struct-opt accepte tout type qui implémente FromStr code>
, qui n'est pas loin de votre fonction parse_day
:
#[structopt(short = "d", long = "day", default_value = "monday")] day: Day,
De plus, la default_value
doit être une chaîne , qui sera interprété en un Jour
en utilisant from_str
.
use std::str::FromStr; impl FromStr for Day { type Err = ParseError; fn from_str(day: &str) -> Result<Self, Self::Err> { match day { "sunday" => Ok(Day::Sunday), "monday" => Ok(Day::Monday), _ => Err("Could not parse a day"), } } }
Au moins avec Rust 1.46, ParseError
ne semble pas exister (?).
Le message d'erreur est:
/// Day of the week #[structopt(short = "d", long = "day", parse(try_from_str = "parse_day"), default_value = "monday")] day: Day,
Vous pouvez résoudre ce problème en implémentant FromStr
pour Day
(voir réponse de kennytm ), comme le suggère le message, ou en définissant une fonction d'analyse pour Day
:
fn parse_day(src: &str) -> Result<Day, String> { match src { "sunday" => Ok(Day::Sunday), "monday" => Ok(Day::Monday), _ => Err(format!("Invalid day: {}", src)) } }
Et en le spécifiant avec l'attribut try_from_str
:
error[E0277]: the trait bound `Day: std::str::FromStr` is not satisfied --> src/main.rs:22:17 | 22 | #[derive(Debug, StructOpt)] | ^^^^^^^^^ the trait `std::str::FromStr` is not implemented for `Day` | = note: required by `std::str::FromStr::from_str`
La meilleure réponse de toutes! Manque juste insensible à la casse :)
L'insensibilité à la casse @decades n'a pas été mentionnée dans la question et ce n'est qu'un attribut supplémentaire pour l'activer.
Je l'ai résolu comme ceci: match src.to_lowercase (). As_ref () {...
l'approche de @ kennytm fonctionne, mais la macro arg_enum!
est une manière plus concise de le faire, comme démontré dans cet exemple de structopt
:
arg_enum! { #[derive(Debug)] enum Day { Sunday, Monday } } #[derive(StructOpt, Debug)] struct Opt { /// Important argument. #[structopt(possible_values = &Day::variants(), case_insensitive = true)] i: Day, } fn main() { let opt = Opt::from_args(); println!("{:?}", opt); }
Cela vous permettra d'analyser les jours de la semaine comme dimanche
ou dimanche
.