changen 0.1.10

Helper program to manage a changelog
Documentation
use pom::parser::*;
use utils::{into_string, space};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FormattedCommit {
    pub section: String,
    pub scope: Option<String>,
    pub message: String,
}

pub fn parse_commit(input: &str) -> anyhow::Result<FormattedCommit> {
    let input = input.chars().collect::<Vec<_>>();
    let parser = commit_parser();
    let commit = parser.parse(&input)?;

    Ok(commit)
}

fn commit_parser<'a>() -> Parser<'a, char, FormattedCommit> {
    let scope = space() * sym('(') * none_of("()").repeat(1..) - sym(')');

    let parser = none_of(" :()").repeat(1..) + scope.opt() - space() * sym(':') * space()
        + any().repeat(1..);

    parser.convert(|((section, scope), message)| {
        let res = FormattedCommit {
            section: into_string(section),
            scope: scope.map(into_string),
            message: into_string(message),
        };

        Ok::<FormattedCommit, ()>(res)
    })
}

mod utils {
    use pom::parser::*;

    pub fn into_string(v: Vec<char>) -> String {
        let str = v.into_iter().collect::<String>();
        let str = str.trim();
        str.to_owned()
    }

    pub fn space<'a>() -> Parser<'a, char, ()> {
        one_of(" \t\r").repeat(0..).discard()
    }
}

#[cfg(test)]
mod test {

    use super::*;

    fn map(input: &str) -> Vec<char> {
        input.chars().collect::<Vec<_>>()
    }

    #[test]
    fn test() {
        let m = map("fix(hello): hihi");
        assert_eq!(
            commit_parser().parse(&m),
            Ok(FormattedCommit {
                section: String::from("fix"),
                scope: Some(String::from("hello")),
                message: String::from("hihi")
            })
        );

        let m = map("fix(hello: hihi");
        commit_parser().parse(&m).unwrap_err();

        let m = map("feat");
        commit_parser().parse(&m).unwrap_err();

        let m = map("improve (ignore) : hihi");
        assert_eq!(
            commit_parser().parse(&m),
            Ok(FormattedCommit {
                section: String::from("improve"),
                scope: Some(String::from("ignore")),
                message: String::from("hihi")
            })
        );
    }
}