espforge_lib/examples/
template.rs1use super::config::ConfigFile;
2use super::fs::OutputDirectory;
3use crate::cli::model::{ExampleConfig, ExportResult};
4use anyhow::{Context, Result, anyhow};
5use espforge_examples::EXAMPLES_DIR;
6use std::fs;
7use std::path::Path;
8
9pub struct ExampleExporter;
10
11impl Default for ExampleExporter {
12 fn default() -> Self {
13 Self::new()
14 }
15}
16
17impl ExampleExporter {
18 pub fn new() -> Self {
19 Self
20 }
21
22 pub fn export(&self, config: &ExampleConfig, output: &OutputDirectory) -> Result<ExportResult> {
23 let template = ExampleTemplate::find(&config.template_name)?;
24 template.extract_to(output.path())?;
25
26 let config_file = ConfigFile::locate(output.path())?;
27 config_file.update(config)?;
28
29 let final_name = config_file.rename_to(&config.project_name)?;
30
31 Ok(ExportResult {
32 project_name: config.project_name.clone(),
33 output_file: format!("{}.yaml", final_name),
34 })
35 }
36}
37
38struct ExampleTemplate {
39 dir: &'static include_dir::Dir<'static>,
40}
41
42impl ExampleTemplate {
43 fn find(name: &str) -> Result<Self> {
44 let dir = Self::search_in_catalog(name)
45 .ok_or_else(|| anyhow!("Example template '{}' not found", name))?;
46
47 Ok(Self { dir })
48 }
49
50 fn search_in_catalog(name: &str) -> Option<&'static include_dir::Dir<'static>> {
51 EXAMPLES_DIR
52 .dirs()
53 .flat_map(|category| category.dirs())
54 .find(|example| example.path().file_name().and_then(|n| n.to_str()) == Some(name))
55 }
56
57 fn extract_to(&self, target: &Path) -> Result<()> {
58 extract_recursive(self.dir, target, self.dir.path())
59 .context("Failed to extract example files to disk")
60 }
61}
62
63fn extract_recursive(
64 dir: &include_dir::Dir,
65 base_path: &Path,
66 root_prefix: &Path,
67) -> std::io::Result<()> {
68 let dir_path = dir.path();
70 let relative_dir_path = dir_path
71 .strip_prefix(root_prefix)
72 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
73
74 let dest_dir = base_path.join(relative_dir_path);
75 if !dest_dir.exists() {
76 fs::create_dir_all(&dest_dir)?;
77 }
78
79 for file in dir.files() {
80 let path = file.path();
81 let relative_path = path
82 .strip_prefix(root_prefix)
83 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
84
85 let dest_path = base_path.join(relative_path);
86
87 if let Some(parent) = dest_path.parent() {
88 fs::create_dir_all(parent)?;
89 }
90
91 fs::write(dest_path, file.contents())?;
92 }
93
94 for subdir in dir.dirs() {
95 extract_recursive(subdir, base_path, root_prefix)?;
96 }
97
98 Ok(())
99}