liftoff 0.1.1

Get your coding project off the ground fast. See repo
Documentation
use crate::{config::Config, consts::*, error::KickError, *};
use chrono::prelude::*;
use regex::Regex;
use std::{
    borrow::Cow,
    mem,
    path::{Path, PathBuf},
};

// TODO better S, accept int and string
fn update_cow<'a, S: AsRef<str>>(input: &mut Cow<'a, str>, from: &str, to: S) {
    mem::replace(input, Cow::Owned(input.replace(from, to.as_ref())));
}

pub fn path_from_variables<'a, P: AsRef<Path>>(
    root: P,
    input: &Cow<'a, str>,
    config: &Config,
) -> Result<PathBuf, KickError> {
    let input = replace_variables(&input, &config)?;
    Ok(root.as_ref().join(input.as_ref()))
}

pub fn replace_variables<'a>(input: &Cow<'a, str>, config: &Config) -> Result<Cow<'a, str>, KickError> {
    let re = Regex::new(LIFTOFF_VARIABLES_REGEX)?;
    let local: DateTime<Local> = Local::now();
    let mut input = input.clone();

    for cap in re.captures_iter(&input.clone()) {
        match cap.get(0).unwrap().as_str() {
            "$(project)" => update_cow(&mut input, "$(project)", &config.project),
            "$(language)" => update_cow(&mut input, "$(language)", &config.language),
            "$(year)" => update_cow(&mut input, "$(year)", local.year().to_string()),
            "$(month)" => update_cow(&mut input, "$(month)", local.month().to_string()),
            "$(day)" => update_cow(&mut input, "$(day)", local.day().to_string()),
            "$(date)" => update_cow(&mut input, "$(date)", date!(local)),
            // safe to unwrap here, checked for valid author in License::build_from
            "$(author)" => update_cow(&mut input, "$(author)", &config.author.as_ref().unwrap()),
            _var => return Err(KickError::VariableNotFoundError(_var.to_owned())),
        }
    }

    Ok(input)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_replace_variables() {
        let dt: DateTime<Local> = Local::now();

        let config = Config {
            project: "test".into(),
            git: true,
            author: Some("Julian".into()),
            license: None,
            base_command: None,
            language: "rust".into(),
            directories:None,
            files: None,
            root: None,
            ci: None,
        };

        let text = {
            let orig = Cow::Borrowed("Writing a $(project) in $(language)");
            replace_variables(&orig, &config).unwrap()
        };
        assert_eq!(text, "Writing a test in rust");

        let text = {
            let orig = Cow::Borrowed("Today: $(date) Author: $(author)");
            replace_variables(&orig, &config).unwrap()
        };
        assert_eq!(text, format!("Today: {}-{}-{} Author: Julian", dt.year(), dt.month(), dt.day()).as_str());

        let text = {
            let orig = Cow::Borrowed("Today: $(year)-$(month)-$(day)");
            replace_variables(&orig, &config).unwrap()
        };
        assert_eq!(text, format!("Today: {}-{}-{}", dt.year(), dt.month(), dt.day()).as_str());

        let text = Cow::Borrowed("Writing a $(project in $language)");
        assert!(replace_variables(&text, &config).is_err());


    }
}