use anyhow::{Result, anyhow};
use handlebars::{Handlebars, no_escape};
use regex::Regex;
use serde::{Deserialize, Serialize};
use std::io::Write;
pub fn handlebars_setup(template_str: &str, template_name: &str) -> Result<Handlebars<'static>> {
let mut handlebars = Handlebars::new();
handlebars.register_escape_fn(no_escape);
handlebars
.register_template_string(template_name, template_str)
.map_err(|e| anyhow!("Failed to register template: {}", e))?;
Ok(handlebars)
}
pub fn extract_undefined_variables(template: &str) -> Vec<String> {
let registered_identifiers = ["path", "code", "git_diff"];
let re = Regex::new(r"\{\{\s*(?P<var>[a-zA-Z_][a-zA-Z_0-9]*)\s*\}\}").unwrap();
re.captures_iter(template)
.map(|cap| cap["var"].to_string())
.filter(|var| !registered_identifiers.contains(&var.as_str()))
.collect()
}
pub fn render_template<T: Serialize>(
handlebars: &Handlebars,
template_name: &str,
data: &T,
) -> Result<String> {
let rendered = handlebars
.render(template_name, data)
.map_err(|e| anyhow!("Failed to render template: {}", e))?;
Ok(rendered.trim().to_string())
}
pub fn write_to_file(output_path: &str, rendered: &str) -> Result<()> {
let file = std::fs::File::create(output_path)?;
let mut writer = std::io::BufWriter::new(file);
write!(writer, "{}", rendered)?;
Ok(())
}
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum OutputFormat {
#[default]
Markdown,
Json,
Xml,
}
impl std::fmt::Display for OutputFormat {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
OutputFormat::Markdown => write!(f, "markdown"),
OutputFormat::Json => write!(f, "json"),
OutputFormat::Xml => write!(f, "xml"),
}
}
}