argster 0.1.1

A simple parser for command line arguments
Documentation
pub use argster_macros::command;
pub use prettytable;
use std::collections::HashMap;
pub mod term {
    pub use term::{color, stderr, Attr};
}

pub mod from_args;

#[derive(Debug, PartialEq)]
pub enum ArgsItem {
    String(String),
    Many(Vec<String>),
    Present,
    PresentTimes(usize),
}

pub fn parse_args(iter: impl Iterator<Item = String>) -> HashMap<String, ArgsItem> {
    let mut iter = iter.peekable();
    let mut collection = HashMap::new();

    while let Some(item) = iter.next() {
        let (key, value) = if let Some(key) = item.strip_prefix("--") {
            (key.to_string(), {
                let temp = iter
                    .peek()
                    .filter(|item| !item.starts_with('-'))
                    .map(ToString::to_string);
                if temp.is_some() {
                    iter.next();
                }
                temp
            })
        } else if let Some(item) = item.strip_prefix('-') {
            if item.is_empty() {
                continue;
            } else if item.len() == 1 {
                (item.to_string(), {
                    let temp = iter
                        .peek()
                        .filter(|item| !item.starts_with('-'))
                        .map(ToString::to_string);
                    if temp.is_some() {
                        iter.next();
                    }
                    temp
                })
            } else {
                (
                    item.get(0..1).unwrap().to_string(),
                    item.get(1..).map(ToString::to_string),
                )
            }
        } else {
            ("".into(), Some(item))
        };

        collection
            .entry(key.to_string())
            .and_modify(|z| match z {
                ArgsItem::Many(vec) => {
                    vec.push(match value.as_ref() {
                        Some(val) => val.into(),
                        None => "".into(),
                    });
                }
                ArgsItem::String(previous_value) => {
                    *z = ArgsItem::Many(vec![
                        previous_value.clone(),
                        match value.as_ref() {
                            Some(val) => val.into(),
                            None => "".into(),
                        },
                    ])
                }
                ArgsItem::Present => match value.as_ref() {
                    Some(value) => *z = ArgsItem::Many(vec!["".into(), value.clone()]),
                    None => *z = ArgsItem::PresentTimes(2),
                },
                ArgsItem::PresentTimes(n) => match value.as_ref() {
                    Some(value) => {
                        *z = ArgsItem::Many({
                            let mut temp = vec!["".to_string(); *n];
                            temp.push(value.clone());
                            temp
                        })
                    }
                    None => *n += 1,
                },
            })
            .or_insert(match value {
                Some(value) => ArgsItem::String(value),
                None => ArgsItem::Present,
            });
    }

    collection
}

#[cfg(test)]
mod test {
    use std::collections::HashMap;

    use super::*;

    #[test]
    fn test_parse_args() {
        let args = vec!["--hello".into()];

        let parsed = parse_args(args.into_iter());

        assert_eq!(
            parsed,
            HashMap::from_iter([("hello".into(), ArgsItem::Present)])
        );
    }

    #[test]
    fn test_parse_args_with_value() {
        let args = vec!["--hello".into(), "world".into()];

        let parsed = parse_args(args.into_iter());

        assert_eq!(
            parsed,
            HashMap::from_iter([("hello".into(), ArgsItem::String("world".into()))])
        );
    }

    #[test]
    fn test_parsed_vales() {
        let args = vec!["hello".into(), "world".into()];

        let parsed = parse_args(args.into_iter());

        assert_eq!(
            parsed,
            HashMap::from_iter([(
                "".into(),
                ArgsItem::Many(vec!["hello".into(), "world".into()])
            )])
        );
    }

    #[test]
    fn short_value() {
        let args = vec![
            "-hworld".into(),
            "yes".into(),
            "-v".into(),
            "-p".into(),
            "other".into(),
        ];

        let parsed = parse_args(args.into_iter());

        assert_eq!(
            parsed,
            HashMap::from_iter([
                ("h".into(), ArgsItem::String("world".into())),
                ("p".into(), ArgsItem::String("other".into())),
                ("v".into(), ArgsItem::Present),
                ("".into(), ArgsItem::String("yes".into()))
            ])
        );
    }
}