Skip to main content

cargo_smith/templates/
template_engine.rs

1use anyhow::Result;
2use std::path::Path;
3use tokio::fs;
4use tokio::io::AsyncWriteExt;
5use chrono::Utc;
6
7use crate::templates::types::CargoToml;
8use crate::templates::TemplateType;
9
10const CARGO_TOML: &str = include_str!("../../Cargo.toml");
11
12pub struct TemplateEngine;
13
14impl TemplateEngine {
15
16    pub async fn generate_from_template(
17        name: &str,
18        output_path: &str,
19        template_content: &str,
20        template_type: &TemplateType
21    ) -> Result<()> {
22
23        let config: CargoToml = toml::from_str(CARGO_TOML)?;
24
25        let content = template_content
26            .replace("{{name}}", name)
27            .replace("{{name_snake_case}}", &name.replace("-", "_"))
28            .replace("{{name_pascal_case}}", &to_pascal_case(&name))
29            .replace("{{now}}",  &Utc::now().format("%Y-%m-%d").to_string())
30            .replace("{{template_type}}", &template_type.to_string())
31            .replace("{{cargo_version}}", &config.package.version);
32
33        let full_output_path = format!("{}/{}", name, output_path);
34        
35        if let Some(parent) = Path::new(&full_output_path).parent() {
36            fs::create_dir_all(parent).await?;
37        }
38        
39        let mut file = fs::File::create(full_output_path).await?;
40        file.write_all(content.as_bytes()).await?;
41        
42        Ok(())
43    }
44
45    pub async fn generate_resource_template(
46        name: &str,
47        output_path: &str,
48        template_content: &str,
49    ) -> Result<()> {
50        let content = template_content
51            .replace("{{name}}", name)
52            .replace("{{name_snake_case}}", &name.replace("-", "_"))
53            .replace("{{name_pascal_case}}", &to_pascal_case(&name));
54
55        // Use output_path directly without prefixing
56        let full_output_path = output_path.to_string();
57        
58        if let Some(parent) = Path::new(&full_output_path).parent() {
59            fs::create_dir_all(parent).await?;
60        }
61        
62        let mut file = fs::File::create(full_output_path).await?;
63        file.write_all(content.as_bytes()).await?;
64        
65        Ok(())
66    }
67
68}
69
70fn to_pascal_case(s: &str) -> String {
71    let mut result = String::new();
72    let mut capitalize_next = true;
73    
74    for c in s.chars() {
75        if c == '_' || c == '-' {
76            capitalize_next = true;
77        } else if capitalize_next {
78            result.push(c.to_ascii_uppercase());
79            capitalize_next = false;
80        } else {
81            result.push(c);
82        }
83    }
84    result
85}