cmder 0.6.1

A simple, lightweight, command line argument parser for rust codebases
Documentation
use crate::ui::formatter::FormatGenerator;

use super::Argument;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CmderOption<'op> {
    pub short: &'op str,
    pub long: &'op str,
    pub arguments: Vec<Argument>,
    pub description: &'op str,
    pub required: bool,
    pub name: &'op str,
}

impl<'b> CmderOption<'b> {
    pub fn new(name: &'b str) -> Self {
        Self {
            short: "",
            name,
            arguments: vec![],
            description: "",
            long: "",
            required: false,
        }
    }

    pub fn short(mut self, val: &'b str) -> Self {
        self.short = val;
        self
    }

    pub fn long(mut self, val: &'b str) -> Self {
        self.long = val;
        self
    }

    pub fn help(mut self, val: &'b str) -> Self {
        self.description = val;
        self
    }

    pub fn is_required(mut self, v: bool) -> Self {
        self.required = v;
        self
    }

    pub fn argument(mut self, val: &'b str) -> Self {
        self.arguments.push(Argument::generate(val, None));
        self
    }

    pub fn add_argument(mut self, a: Argument) -> Self {
        self.arguments.push(a);
        self
    }

    pub(crate) fn generate(short: &'b str, long: &'b str, desc: &'b str, args: &[&str]) -> Self {
        let mut arguments = vec![];
        for a in args.iter() {
            arguments.push(Argument::generate(a, None))
        }

        Self {
            short,
            long,
            description: desc,
            arguments,
            required: false,
            name: "",
        }
    }
}

impl<'d> Default for CmderOption<'d> {
    fn default() -> Self {
        Self::generate("", "", "", &[])
    }
}

pub(crate) fn resolve_option<'o>(list: &'o [CmderOption], val: String) -> Option<CmderOption<'o>> {
    let mut flag = None;

    let val = val.as_str();
    for f in list {
        if f.short == val || f.long == val {
            flag = Some(f.clone());
        }
    }
    flag
}

impl<'f> FormatGenerator for CmderOption<'f> {
    fn generate(&self, ptrn: crate::ui::formatter::Pattern) -> (String, String) {
        use crate::ui::formatter::Pattern;
        match &ptrn {
            Pattern::Custom(ptrn) => {
                let base = &ptrn.flags_fmter;

                let mut floating = String::from("");
                let mut leading = base
                    .replace("{{short}}", self.short)
                    .replace("{{long}}", self.long);

                if base.contains("{{args}}") && !self.arguments.is_empty() {
                    let mut value = String::new();

                    for a in &self.arguments {
                        value.push_str(&(a.literal));
                        value.push(' ');
                    }

                    leading = leading.replace("{{args}}", value.trim());
                }

                if base.contains("{{description}}") {
                    leading = leading.replace("{{description}}", self.description);
                } else {
                    floating = self.description.into()
                }

                (leading, floating)
            }
            _ => {
                let short: String = if !self.short.is_empty() {
                    format!("{},", self.short)
                } else {
                    "  ".into()
                };

                let args = if !self.arguments.is_empty() {
                    let mut raw = String::new();

                    for a in &self.arguments {
                        raw.push_str(&(a.literal));
                        raw.push(' ');
                    }

                    raw
                } else {
                    "".into()
                };

                (
                    format!("{} {} {}", short, self.long, args),
                    self.description.into(),
                )
            }
        }
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn test_options_creation() {
        let o = CmderOption::generate("-p", "--port", "Port flag", &[]);

        assert_eq!(o.short, "-p");
        assert_eq!(o.long, "--port");
        assert_eq!(o.description, "Port flag");
        assert_eq!(o.required, false);
        assert_eq!(o.arguments, vec![]);
    }
}