1use crate::{
7 interface::replace_placeholders, macro_generate_from_csv,
8 macro_generate_from_ini, macro_generate_from_json,
9 macro_generate_from_toml, macro_generate_from_yaml,
10 models::model_params::FileGenerationParams,
11 utils::create_directory,
12};
13use std::{fs, io, path::PathBuf};
14
15pub fn create_template_folder() -> io::Result<()> {
27 let current_dir = std::env::current_dir()?;
28 let template_dir_path = current_dir.join("template");
30 create_directory(&template_dir_path)?;
32 let url = "https://raw.githubusercontent.com/sebastienrousseau/libmake/main/template/";
33 let files = [
34 "AUTHORS.tpl",
35 "build.tpl",
36 "Cargo.tpl",
37 "ci.tpl",
38 "CONTRIBUTING.tpl",
39 "criterion.tpl",
40 "deepsource.tpl",
41 "deny.tpl",
42 "example.tpl",
43 "gitignore.tpl",
44 "lib.tpl",
45 "macros.tpl",
46 "main.tpl",
47 "README.tpl",
48 "rustfmt.tpl",
49 "TEMPLATE.tpl",
50 "test.tpl",
51 ];
52 for file in &files {
53 let file_path = template_dir_path.join(file);
54 if !file_path.exists() {
56 let file_url = format!("{url}{file}");
57 let response =
58 reqwest::blocking::get(&file_url).map_err(|e| {
59 io::Error::new(
60 io::ErrorKind::Other,
61 format!(
62 "Failed to download template file: {e}"
63 ),
64 )
65 })?;
66
67 let file_contents = response.text().map_err(|e| {
68 io::Error::new(
69 io::ErrorKind::Other,
70 format!("Failed to read response body: {e}"),
71 )
72 })?;
73
74 fs::write(
76 &file_path,
77 file_contents
78 .trim_start_matches('\n')
79 .trim_end_matches('\n'),
80 )?;
81 }
82 }
83 Ok(())
84}
85
86#[allow(unused_results)]
105pub fn copy_and_replace_template(
106 template_file: &str,
107 dest_file: &str,
108 project_directory: &PathBuf,
109 params: &FileGenerationParams,
110) -> io::Result<()> {
111 let mut tpl_file = PathBuf::new();
112 tpl_file.push("template");
113 tpl_file.push(template_file);
114
115 let mut dest_path = PathBuf::new();
116 dest_path.push(project_directory);
117 dest_path.push(dest_file);
118
119 fs::copy(&tpl_file, &dest_path)?;
120
121 replace_placeholders(&tpl_file, &dest_path, params)?;
122
123 Ok(())
124}
125
126pub fn generate_files(params: FileGenerationParams) -> io::Result<()> {
141 let Some(ref output) = params.output else {
142 return Err(io::Error::new(
143 io::ErrorKind::Other,
144 "Output directory is not specified",
145 ));
146 };
147
148 let project_directory =
151 PathBuf::from(output.clone().trim_matches('\"'));
152
153 create_directory(&project_directory)?;
155
156 create_template_folder()?;
158
159 let subdirectories = [
161 "src",
162 "benches",
163 "examples",
164 "tests",
165 ".github/",
166 ".github/workflows",
167 ];
168
169 for subdir in &subdirectories {
171 let dir_path = project_directory.join(subdir);
172 create_directory(&dir_path)?;
173 }
174
175 let templates = [
177 ("github/workflows/audit.tpl", ".github/workflows/audit.yml"),
180 ("github/workflows/check.tpl", ".github/workflows/check.yml"),
182 (
184 "github/workflows/coverage.tpl",
185 ".github/workflows/coverage.yml",
186 ),
187 (
189 "github/workflows/document.tpl",
190 ".github/workflows/document.yml",
191 ),
192 ("github/workflows/lint.tpl", ".github/workflows/lint.yml"),
194 (
196 "github/workflows/release.tpl",
197 ".github/workflows/release.yml",
198 ),
199 ("github/workflows/test.tpl", ".github/workflows/test.yml"),
201 ("AUTHORS.tpl", "AUTHORS.md"),
204 ("build.tpl", "build.rs"),
206 ("Cargo.tpl", "Cargo.toml"),
208 ("CONTRIBUTING.tpl", "CONTRIBUTING.md"),
210 ("criterion.tpl", "benches/criterion.rs"),
212 ("deepsource.tpl", ".deepsource.toml"),
214 ("deny.tpl", "deny.toml"),
216 ("example.tpl", "examples/example.rs"),
218 ("gitignore.tpl", ".gitignore"),
220 ("lib.tpl", "src/lib.rs"),
222 ("macros.tpl", "src/macros.rs"),
224 ("main.tpl", "src/main.rs"),
226 ("README.tpl", "README.md"),
228 ("rustfmt.tpl", "rustfmt.toml"),
230 ("TEMPLATE.tpl", "TEMPLATE.md"),
232 ("test_test.tpl", "tests/test_test.rs"),
234 ];
235
236 for (template, target) in templates {
237 copy_and_replace_template(
238 template,
239 target,
240 &project_directory,
241 ¶ms,
242 )?;
243 }
244
245 println!("{:<15}Value", "Argument");
247 println!("{:<15}{}", "author", params.author.unwrap_or_default());
248 println!("{:<15}{}", "build", params.build.unwrap_or_default());
249 println!(
250 "{:<15}{}",
251 "categories",
252 params.categories.unwrap_or_default()
253 );
254 println!(
255 "{:<15}{}",
256 "description",
257 params.description.unwrap_or_default()
258 );
259 println!(
260 "{:<15}{}",
261 "documentation",
262 params.documentation.unwrap_or_default()
263 );
264 println!("{:<15}{}", "edition", params.edition.unwrap_or_default());
265 println!("{:<15}{}", "email", params.email.unwrap_or_default());
266 println!(
267 "{:<15}{}",
268 "homepage",
269 params.homepage.unwrap_or_default()
270 );
271 println!(
272 "{:<15}{}",
273 "keywords",
274 params.keywords.unwrap_or_default()
275 );
276 println!("{:<15}{}", "license", params.license.unwrap_or_default());
277 println!("{:<15}{}", "name", params.name.unwrap_or_default());
278 println!("{:<15}{}", "output", output.clone());
279 println!("{:<15}{}", "readme", params.readme.unwrap_or_default());
280 println!(
281 "{:<15}{}",
282 "repository",
283 params.repository.unwrap_or_default()
284 );
285 println!(
286 "{:<15}{}",
287 "rustversion",
288 params.rustversion.unwrap_or_default()
289 );
290 println!("{:<15}{}", "version", params.version.unwrap_or_default());
291 println!("{:<15}{}", "website", params.website.unwrap_or_default());
292
293 Ok(())
294}
295
296pub fn generate_from_config(
312 path: &str,
313 file_type: &str,
314) -> Result<(), String> {
315 match file_type {
316 "csv" => macro_generate_from_csv!(path)?,
317 "ini" => macro_generate_from_ini!(path)?,
318 "json" => macro_generate_from_json!(path)?,
319 "yaml" => macro_generate_from_yaml!(path)?,
320 "toml" => macro_generate_from_toml!(path)?,
321 _ => {
322 return Err(format!(
323 "Unsupported configuration file type: {}",
324 file_type
325 ))
326 }
327 }
328 Ok(())
329}