ferrous_forge/
templates.rs

1//! Template system for Ferrous Forge
2//!
3//! This module manages project templates and configuration files that get
4//! injected into new Rust projects to enforce standards.
5
6use crate::{Result, Error};
7use handlebars::Handlebars;
8use serde_json::json;
9use std::path::Path;
10
11/// Template manager for Ferrous Forge
12pub struct TemplateManager {
13    handlebars: Handlebars<'static>,
14}
15
16impl TemplateManager {
17    /// Create a new template manager
18    pub fn new() -> Result<Self> {
19        let mut handlebars = Handlebars::new();
20        
21        // Register built-in templates
22        handlebars.register_template_string("cargo_toml", include_str!("../templates/Cargo.toml.hbs"))
23            .map_err(|e| Error::template(format!("Failed to register Cargo.toml template: {}", e)))?;
24            
25        handlebars.register_template_string("main_rs", include_str!("../templates/main.rs.hbs"))
26            .map_err(|e| Error::template(format!("Failed to register main.rs template: {}", e)))?;
27            
28        handlebars.register_template_string("lib_rs", include_str!("../templates/lib.rs.hbs"))
29            .map_err(|e| Error::template(format!("Failed to register lib.rs template: {}", e)))?;
30            
31        handlebars.register_template_string("github_workflow", include_str!("../templates/ci.yml.hbs"))
32            .map_err(|e| Error::template(format!("Failed to register GitHub workflow template: {}", e)))?;
33            
34        Ok(Self { handlebars })
35    }
36
37    /// Generate a Cargo.toml file with Ferrous Forge standards
38    pub fn generate_cargo_toml(&self, project_name: &str, is_lib: bool) -> Result<String> {
39        let data = json!({
40            "project_name": project_name,
41            "is_lib": is_lib,
42            "version": "0.1.0",
43            "edition": "2024",
44            "rust_version": "1.85",
45        });
46
47        self.handlebars.render("cargo_toml", &data)
48            .map_err(|e| Error::template(format!("Failed to render Cargo.toml: {}", e)))
49    }
50
51    /// Generate a main.rs file with Ferrous Forge standards
52    pub fn generate_main_rs(&self, project_name: &str) -> Result<String> {
53        let data = json!({
54            "project_name": project_name,
55        });
56
57        self.handlebars.render("main_rs", &data)
58            .map_err(|e| Error::template(format!("Failed to render main.rs: {}", e)))
59    }
60
61    /// Generate a lib.rs file with Ferrous Forge standards
62    pub fn generate_lib_rs(&self, project_name: &str) -> Result<String> {
63        let data = json!({
64            "project_name": project_name,
65        });
66
67        self.handlebars.render("lib_rs", &data)
68            .map_err(|e| Error::template(format!("Failed to render lib.rs: {}", e)))
69    }
70
71    /// Generate GitHub Actions CI workflow
72    pub fn generate_github_workflow(&self, project_name: &str) -> Result<String> {
73        let data = json!({
74            "project_name": project_name,
75        });
76
77        self.handlebars.render("github_workflow", &data)
78            .map_err(|e| Error::template(format!("Failed to render GitHub workflow: {}", e)))
79    }
80
81    /// Apply templates to an existing project
82    pub async fn apply_to_project(&self, project_path: &Path) -> Result<()> {
83        // This would be used to retrofit existing projects with Ferrous Forge standards
84        // For now, just create a placeholder
85        tracing::info!("Applying Ferrous Forge templates to project: {}", project_path.display());
86        
87        // TODO: Implement project retrofitting
88        // - Backup existing files
89        // - Update Cargo.toml with Edition 2024
90        // - Add strict clippy configuration
91        // - Add GitHub Actions if .git exists
92        // - Update main.rs/lib.rs with documentation requirements
93        
94        Ok(())
95    }
96}
97
98impl Default for TemplateManager {
99    fn default() -> Self {
100        Self::new().unwrap_or_else(|_| {
101            // Fallback to a basic template manager if initialization fails
102            TemplateManager {
103                handlebars: Handlebars::new(),
104            }
105        })
106    }
107}
108
109/// Information about a project template
110#[derive(Debug, Clone)]
111pub struct ProjectTemplate {
112    /// Name of the template
113    pub name: String,
114    /// Description of what this template provides
115    pub description: String,
116    /// Files that this template will create/modify
117    pub files: Vec<String>,
118}
119
120/// Get available project templates
121pub fn available_templates() -> Vec<ProjectTemplate> {
122    vec![
123        ProjectTemplate {
124            name: "basic".to_string(),
125            description: "Basic Rust project with Ferrous Forge standards".to_string(),
126            files: vec![
127                "Cargo.toml".to_string(),
128                "src/main.rs".to_string(),
129                ".github/workflows/ci.yml".to_string(),
130            ],
131        },
132        ProjectTemplate {
133            name: "library".to_string(),
134            description: "Rust library project with Ferrous Forge standards".to_string(),
135            files: vec![
136                "Cargo.toml".to_string(),
137                "src/lib.rs".to_string(),
138                ".github/workflows/ci.yml".to_string(),
139            ],
140        },
141    ]
142}