camel_cli/template/
embedded.rs1use include_dir::{Dir, DirEntry, include_dir};
2
3use super::{TemplateContext, TemplateFile, TemplateProvider};
4
5static BASIC_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates/basic");
6
7pub struct EmbeddedTemplate {
8 name: &'static str,
9 dir: &'static Dir<'static>,
10}
11
12impl EmbeddedTemplate {
13 pub fn basic() -> Self {
14 Self {
15 name: "basic",
16 dir: &BASIC_DIR,
17 }
18 }
19}
20
21fn collect_files(
22 dir: &Dir<'_>,
23 files: &mut Vec<TemplateFile>,
24) -> Result<(), Box<dyn std::error::Error>> {
25 for entry in dir.entries() {
26 match entry {
27 DirEntry::Dir(subdir) => {
28 collect_files(subdir, files)?;
29 }
30 DirEntry::File(f) => {
31 let path = f.path().to_str().unwrap_or("");
32 if path.starts_with("Camel.toml.") || path == "README.md.tpl" {
33 continue;
34 }
35 let content = f
36 .contents_utf8()
37 .ok_or_else(|| format!("file is not valid UTF-8: {path}"))?;
38 files.push(TemplateFile {
39 path: path.to_string(),
40 content: content.to_string(),
41 });
42 }
43 }
44 }
45 Ok(())
46}
47
48impl TemplateProvider for EmbeddedTemplate {
49 fn name(&self) -> &str {
50 self.name
51 }
52
53 fn files(
54 &self,
55 ctx: &TemplateContext,
56 ) -> Result<Vec<TemplateFile>, Box<dyn std::error::Error>> {
57 let mut files = Vec::new();
58
59 let camel_toml_name = match ctx.profile_layout {
60 super::ProfileLayout::Simple => "Camel.toml.simple",
61 super::ProfileLayout::Env => "Camel.toml.env",
62 };
63 let camel_content = self
64 .dir
65 .get_file(camel_toml_name)
66 .ok_or_else(|| format!("{camel_toml_name} template not found"))?
67 .contents_utf8()
68 .ok_or_else(|| format!("{camel_toml_name} template is not valid UTF-8"))?;
69 files.push(TemplateFile {
70 path: "Camel.toml".to_string(),
71 content: camel_content.to_string(),
72 });
73
74 collect_files(self.dir, &mut files)?;
75
76 let readme_template = self
77 .dir
78 .get_file("README.md.tpl")
79 .ok_or("README.md.tpl not found")?
80 .contents_utf8()
81 .ok_or("README.md.tpl is not valid UTF-8")?;
82 let display_name = std::path::Path::new(&ctx.project_name)
84 .file_name()
85 .and_then(|n| n.to_str())
86 .unwrap_or(&ctx.project_name);
87 files.push(TemplateFile {
88 path: "README.md".to_string(),
89 content: readme_template.replace("<name>", display_name),
90 });
91
92 Ok(files)
93 }
94}