use std::collections::HashMap;
use lazy_static::lazy_static;
use regex::Regex;
use tera::{self, from_value, to_value, Context, Tera, Value};
use thiserror::Error as ThisError;
use which::which;
use super::facts::Facts;
lazy_static! {
static ref DIR_EXPRESSION_RE: Regex = Regex::new(r"_dir\s*\}\}").unwrap();
}
#[derive(Debug, ThisError)]
pub(crate) enum Error {
#[error("template error: {}", source)]
Tera {
#[from]
source: tera::Error,
},
}
pub(crate) type Result<T> = std::result::Result<T, Error>;
pub(crate) fn make_tera(facts: &Facts) -> Result<(Tera, Context)> {
let context = Context::from_serialize(facts)?;
let template_glob = facts
.main_file
.parent()
.expect("main.toml file has no parent directory")
.join("*.toml");
let mut t = Tera::new(template_glob.as_str()).expect("unable to prepare template system");
t.register_function("has_executable", template_function_has_executable);
Ok((t, context))
}
fn template_function_has_executable(args: &HashMap<String, Value>) -> tera::Result<Value> {
match args.get("exe") {
Some(val) => match from_value::<String>(val.clone()) {
Ok(v) => Ok(to_value(which(v).is_ok()).unwrap()),
Err(_) => Err(tera::Error::from(r#""exe" must be a string"#)),
},
None => Err(tera::Error::from(r#"missing "exe" argument"#)),
}
}
#[cfg(test)]
mod tests {
use crate::facts::Facts;
use super::*;
#[test]
fn make_tera_ok() {
let facts = Facts::default();
let got = make_tera(&facts);
assert!(got.is_ok());
}
}