quickstart_lib/template/
variables.rs

1//! Template variables implementation
2//!
3//! This module defines the variables available for template substitution
4//! and provides functionality to build a variables object from project configuration.
5
6use chrono::{Datelike, Local};
7use serde::Serialize;
8use std::time::{SystemTime, UNIX_EPOCH};
9
10use crate::ProjectConfig;
11use crate::ProjectType;
12
13/// Variables available for template substitution
14#[derive(Debug, Clone, Serialize)]
15pub struct TemplateVariables {
16    /// Project name
17    pub name: String,
18
19    /// Project description (optional)
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub description: Option<String>,
22
23    /// Project version
24    pub version: String,
25
26    /// Rust edition
27    pub edition: String,
28
29    /// Author information
30    pub author: Author,
31
32    /// License type
33    pub license: String,
34
35    /// Project type flags
36    pub project: ProjectFlags,
37
38    /// Git configuration
39    pub git: GitConfig,
40
41    /// Date and timestamp information
42    pub date: DateInfo,
43
44    /// Template variant flags
45    pub template: TemplateFlags,
46}
47
48/// Information about the project author
49#[derive(Debug, Clone, Serialize)]
50pub struct Author {
51    /// Author name
52    pub name: String,
53
54    /// Author email (optional)
55    #[serde(skip_serializing_if = "Option::is_none")]
56    pub email: Option<String>,
57}
58
59/// Project type flags for conditional template sections
60#[derive(Debug, Clone, Serialize)]
61pub struct ProjectFlags {
62    /// Whether the project is a binary application
63    pub is_binary: bool,
64
65    /// Whether the project is a library crate
66    pub is_library: bool,
67}
68
69/// Git configuration flags
70#[derive(Debug, Clone, Serialize)]
71pub struct GitConfig {
72    /// Whether to initialize a Git repository
73    pub initialize: bool,
74
75    /// Whether to create an initial commit
76    pub create_commit: bool,
77}
78
79/// Date and timestamp information
80#[derive(Debug, Clone, Serialize)]
81pub struct DateInfo {
82    /// Current year (YYYY)
83    pub year: u32,
84
85    /// Current date in ISO format (YYYY-MM-DD)
86    pub iso_date: String,
87
88    /// Unix timestamp
89    pub timestamp: u64,
90}
91
92/// Template variant flags
93#[derive(Debug, Clone, Serialize)]
94pub struct TemplateFlags {
95    /// Whether to use minimal templates
96    pub is_minimal: bool,
97
98    /// Whether to use extended templates
99    pub is_extended: bool,
100}
101
102impl TemplateVariables {
103    /// Create a new set of template variables from project configuration
104    pub fn from_config(config: &ProjectConfig) -> Self {
105        // Get current year and date information
106        let now = Local::now();
107        let year = now.year() as u32;
108        let iso_date = now.format("%Y-%m-%d").to_string();
109
110        // Generate timestamp
111        let timestamp = SystemTime::now()
112            .duration_since(UNIX_EPOCH)
113            .unwrap_or_default()
114            .as_secs();
115
116        // Create project type flags
117        let is_binary = matches!(config.project_type, ProjectType::Binary);
118        let is_library = matches!(config.project_type, ProjectType::Library);
119
120        // Default to extended templates
121        let is_extended = true;
122        let is_minimal = !is_extended;
123
124        // TODO: Get author information from Git config or environment
125        let author_name = "Your Name".to_string();
126        let author_email = Some("your.email@example.com".to_string());
127
128        Self {
129            name: config.name.clone(),
130            description: None, // TODO: Add description to config or prompt for it
131            version: "0.1.0".to_string(),
132            edition: config.edition.clone(),
133            author: Author {
134                name: author_name,
135                email: author_email,
136            },
137            license: config.license.clone(),
138            project: ProjectFlags {
139                is_binary,
140                is_library,
141            },
142            git: GitConfig {
143                initialize: config.git,
144                create_commit: config.git,
145            },
146            date: DateInfo {
147                year,
148                iso_date,
149                timestamp,
150            },
151            template: TemplateFlags {
152                is_minimal,
153                is_extended,
154            },
155        }
156    }
157
158    /// Create a new set of template variables with default values for testing
159    #[cfg(test)]
160    pub fn default_test_variables() -> Self {
161        // Skip getting actual time under Miri to avoid isolation issues
162        let (year, iso_date) = if cfg!(miri) {
163            (2023, "2023-04-01".to_string())
164        } else {
165            let now = Local::now();
166            (now.year() as u32, now.format("%Y-%m-%d").to_string())
167        };
168
169        Self {
170            name: "test-project".to_string(),
171            description: Some("A test project".to_string()),
172            version: "0.1.0".to_string(),
173            edition: "2021".to_string(),
174            author: Author {
175                name: "Test Author".to_string(),
176                email: Some("test@example.com".to_string()),
177            },
178            license: "MIT".to_string(),
179            project: ProjectFlags {
180                is_binary: true,
181                is_library: false,
182            },
183            git: GitConfig {
184                initialize: true,
185                create_commit: true,
186            },
187            date: DateInfo {
188                year,
189                iso_date,
190                timestamp: 1619712000, // Fixed timestamp for testing
191            },
192            template: TemplateFlags {
193                is_minimal: false,
194                is_extended: true,
195            },
196        }
197    }
198}