1use crate::config::{EspforgeConfiguration, PlatformConfig};
2use crate::template_utils::{copy_verbatim, find_template_path, get_templates, write_template};
3use anyhow::{Context, Result, anyhow};
4use std::path::Path;
5
6pub struct ExportOptions {
7 pub example_name: String,
8 pub override_project_name: Option<String>,
9 pub override_platform: Option<String>,
10}
11
12pub fn export_example(options: ExportOptions, target_dir: &Path) -> Result<String> {
13 let root = get_templates();
14
15 let template_path_str = find_template_path(&options.example_name)
16 .ok_or_else(|| anyhow!("Example '{}' not found", options.example_name))?;
17
18 let template_dir = root.get_dir(&template_path_str).ok_or_else(|| {
19 anyhow!(
20 "Template directory structure error for '{}'",
21 options.example_name
22 )
23 })?;
24
25 let example_file = template_dir.path().join("example.yaml");
26 let yaml_file = root
28 .get_file(&example_file)
29 .ok_or_else(|| anyhow!("Template is missing example.yaml"))?;
30
31 let raw_yaml = yaml_file
32 .contents_utf8()
33 .context("Invalid UTF-8 in example.yaml")?;
34
35 let mut config: EspforgeConfiguration = serde_yaml_ng::from_str(raw_yaml)
36 .context("Failed to parse example.yaml into configuration")?;
37
38 if let Some(name) = options.override_project_name {
39 config.espforge.name = name;
40 }
41
42 if let Some(platform_str) = options.override_platform {
43 let platform_enum: PlatformConfig = serde_yaml_ng::from_str(&platform_str)
44 .map_err(|_| anyhow!("Invalid platform: {}", platform_str))?;
45 config.espforge.platform = platform_enum;
46 }
47
48 let project_name = config.get_name().to_string();
49
50 let yaml_filename = format!("{}.yaml", project_name);
51 let yaml_dest = target_dir.join(&yaml_filename);
52
53 let modified_yaml = serde_yaml_ng::to_string(&config)?;
54 write_template(&yaml_dest, &modified_yaml)?;
55 println!("Created config: {}", yaml_filename);
56
57 let project_path_str = target_dir.to_string_lossy();
58 let template_root_path = template_dir.path();
59
60 for entry in template_dir.find("**/*")? {
62 if let Some(file) = entry.as_file() {
63 let file_path = file.path();
64 let file_name = file_path.file_name().and_then(|n| n.to_str()).unwrap_or("");
65
66 if file_name == "example.yaml" {
68 continue;
69 }
70
71 if file_path
72 .components()
73 .any(|c| c.as_os_str() == ".zig-cache" || c.as_os_str() == "zig-out")
74 {
75 continue;
76 }
77
78 copy_verbatim(file, template_root_path, &project_path_str)?;
88
89 let relative_path = file_path
91 .strip_prefix(template_root_path)
92 .unwrap_or(file_path);
93 println!("Created file: {}", relative_path.display());
94 }
95 }
96
97 Ok(project_name)
98}