forehead_core/template.rs
1// بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيم
2// This file is part of forehead.
3//
4// Copyright (C) 2026-Present Afsall Inc.
5// SPDX-License-Identifier: Apache-2.0 OR MIT
6//
7// Licensed under the Apache License, Version 2.0 (the "License");
8// you may not use this file except in compliance with the License.
9// You may obtain a copy of the License at
10//
11// http://www.apache.org/licenses/LICENSE-2.0
12//
13// Unless required by applicable law or agreed to in writing, software
14// distributed under the License is distributed on an "AS IS" BASIS,
15// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16// See the License for the specific language governing permissions and
17// limitations under the License.
18//
19// Alternatively, this file is available under the MIT License:
20// Permission is hereby granted, free of charge, to any person obtaining a copy
21// of this software and associated documentation files (the "Software"), to deal
22// in the Software without restriction, including without limitation the rights
23// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24// copies of the Software, and to permit persons to whom the Software is
25// furnished to do so, subject to the following conditions:
26//
27// The above copyright notice and this permission notice shall be included in all
28// copies or substantial portions of the Software.
29//
30// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36// SOFTWARE.
37
38use crate::{config::Substitution, error::ForeheadError};
39use std::{fs, path::Path};
40
41#[derive(Debug, Clone)]
42pub struct HeaderTemplate {
43 pub content: String,
44 pub lines: Vec<String>,
45}
46
47impl HeaderTemplate {
48 pub fn from_file(path: &Path) -> Result<Self, ForeheadError> {
49 let content = fs::read_to_string(path).map_err(|e| {
50 ForeheadError::Template(format!("failed to read {}: {e}", path.display()))
51 })?;
52 let lines: Vec<String> = content.lines().map(|l| l.to_string()).collect();
53 Ok(HeaderTemplate { content, lines })
54 }
55
56 pub fn new(content: &str) -> Self {
57 let lines: Vec<String> = content.lines().map(|l| l.to_string()).collect();
58 HeaderTemplate {
59 content: content.to_string(),
60 lines,
61 }
62 }
63
64 pub fn substitute(&self, subst: &Substitution) -> String {
65 let mut result = String::new();
66 for line in &self.lines {
67 let rendered = line
68 .replace("{project}", &subst.project)
69 .replace("{author}", &subst.author)
70 .replace("{year}", &subst.year)
71 .replace("{year_span}", &subst.year_span)
72 .replace("{license}", &subst.license)
73 .replace("{repository}", &subst.repository)
74 .replace("{description}", &subst.description)
75 .replace("{file}", &subst.file);
76 result.push_str(&rendered);
77 result.push('\n');
78 }
79 result
80 }
81
82 /// Returns the template as a list of comment lines with the given comment style.
83 /// Each line has the comment prefix applied.
84 pub fn as_comment_lines(&self, comment_prefix: &str, subst: &Substitution) -> Vec<String> {
85 let mut result = Vec::new();
86 for line in &self.lines {
87 let rendered = line
88 .replace("{project}", &subst.project)
89 .replace("{author}", &subst.author)
90 .replace("{year}", &subst.year)
91 .replace("{year_span}", &subst.year_span)
92 .replace("{license}", &subst.license)
93 .replace("{repository}", &subst.repository)
94 .replace("{description}", &subst.description)
95 .replace("{file}", &subst.file);
96 if rendered.trim().is_empty() {
97 result.push(comment_prefix.to_string());
98 } else {
99 result.push(format!("{} {}", comment_prefix, rendered.trim()));
100 }
101 }
102 result
103 }
104}