cote 0.17.1

Quickly build your command line utils
Documentation
use std::ffi::OsStr;

use aopt::prelude::AFwdParser;
use cote::prelude::*;
use regex::Regex;

#[derive(Debug, CoteVal, CoteOpt, PartialEq)]
#[coteval(mapstr = Meal::new)]
pub enum Meal {
    BreakFast,

    Lunch,

    Dinner,
}

impl Meal {
    pub fn new(value: &str) -> cote::Result<Self> {
        match value {
            "breakfast" => Ok(Self::BreakFast),
            "lunch" => Ok(Self::Lunch),
            "dinner" => Ok(Self::Dinner),
            name => {
                panic!("Unknow {name} for Meal")
            }
        }
    }
}

#[derive(Debug, PartialEq, Eq, CoteOpt, CoteVal)]
#[coteval(mapraw = Point::new)]
pub struct Point {
    x: i32,
    y: i32,
}

impl Point {
    pub fn new(raw: Option<&OsStr>, _: &Ctx) -> cote::Result<Self> {
        let regex = Regex::new(r"[\{\[\(]\s*(\d+)\s*\,\s*(\d+)\s*[\}\]\)]").unwrap();
        if let Some(captures) = regex.captures(raw2str(raw)?) {
            let mut x = 0;
            let mut y = 0;

            if let Some(mat) = captures.get(1) {
                x = mat
                    .as_str()
                    .parse::<i32>()
                    .map_err(|_| error!("Point.x must be a valid number: `{}`", mat.as_str()))?;
            }
            if let Some(mat) = captures.get(2) {
                y = mat
                    .as_str()
                    .parse::<i32>()
                    .map_err(|_| error!("Point.y must be a valid number: `{}`", mat.as_str()))?;
            }
            return Ok(Point { x, y });
        }
        panic!("Can not parsing value of Point")
    }
}

#[test]
fn map() {
    assert!(map_impl().is_ok());
}

fn map_impl() -> color_eyre::Result<()> {
    color_eyre::install()?;
    let mut parser = AFwdParser::default();

    parser.add_opt("-p;--point".infer::<Point>())?;
    parser.add_opt("--meal".infer::<Meal>())?;
    parser.parse(Args::from(["app", "-p={42,2}", "--meal=lunch"]))?;

    assert_eq!(
        Point::fetch("--point", parser.optset_mut())?,
        Point { x: 42, y: 2 }
    );
    assert_eq!(Meal::fetch("--meal", parser.optset_mut())?, Meal::Lunch);
    Ok(())
}