use crate::{config::Substitution, error::ForeheadError};
use std::{fs, path::Path};
#[derive(Debug, Clone)]
pub struct HeaderTemplate {
pub content: String,
pub lines: Vec<String>,
}
impl HeaderTemplate {
pub fn from_file(path: &Path) -> Result<Self, ForeheadError> {
let content = fs::read_to_string(path).map_err(|e| {
ForeheadError::Template(format!("failed to read {}: {e}", path.display()))
})?;
let lines: Vec<String> = content.lines().map(|l| l.to_string()).collect();
Ok(HeaderTemplate { content, lines })
}
pub fn new(content: &str) -> Self {
let lines: Vec<String> = content.lines().map(|l| l.to_string()).collect();
HeaderTemplate {
content: content.to_string(),
lines,
}
}
pub fn substitute(&self, subst: &Substitution) -> String {
let mut result = String::new();
for line in &self.lines {
let rendered = line
.replace("{project}", &subst.project)
.replace("{author}", &subst.author)
.replace("{year}", &subst.year)
.replace("{year_span}", &subst.year_span)
.replace("{license}", &subst.license)
.replace("{repository}", &subst.repository)
.replace("{description}", &subst.description)
.replace("{file}", &subst.file);
result.push_str(&rendered);
result.push('\n');
}
result
}
pub fn as_comment_lines(&self, comment_prefix: &str, subst: &Substitution) -> Vec<String> {
let mut result = Vec::new();
for line in &self.lines {
let rendered = line
.replace("{project}", &subst.project)
.replace("{author}", &subst.author)
.replace("{year}", &subst.year)
.replace("{year_span}", &subst.year_span)
.replace("{license}", &subst.license)
.replace("{repository}", &subst.repository)
.replace("{description}", &subst.description)
.replace("{file}", &subst.file);
if rendered.trim().is_empty() {
result.push(comment_prefix.to_string());
} else {
result.push(format!("{} {}", comment_prefix, rendered.trim()));
}
}
result
}
}