secunit_core/wisp/
scaffold.rs1use std::fs;
4
5use anyhow::{Context, Result};
6
7use super::{template, Format, InitOptions, InitReport};
8
9pub fn init(opts: &InitOptions) -> Result<InitReport> {
13 let partials = template::bundled(opts.format)?;
14
15 fs::create_dir_all(&opts.dir)
16 .with_context(|| format!("create template dir {}", opts.dir.display()))?;
17
18 let mut written = Vec::new();
19 let mut skipped = Vec::new();
20
21 for &(name, body) in partials {
22 let dest = opts.dir.join(name);
23 if dest.exists() && !opts.force {
24 skipped.push(name.to_string());
25 continue;
26 }
27 fs::write(&dest, body).with_context(|| format!("write {}", dest.display()))?;
28 written.push(name.to_string());
29 }
30
31 match &opts.logo {
34 Some(src) => {
35 let ext = src
36 .extension()
37 .and_then(|e| e.to_str())
38 .unwrap_or("svg")
39 .to_ascii_lowercase();
40 let dest = opts.dir.join(format!("logo.{ext}"));
41 if dest.exists() && !opts.force {
42 skipped.push(format!("logo.{ext}"));
43 } else {
44 fs::copy(src, &dest).with_context(|| {
45 format!("copy logo {} -> {}", src.display(), dest.display())
46 })?;
47 written.push(format!("logo.{ext}"));
48 }
49 }
50 None => {
51 let dest = opts.dir.join("logo.svg");
52 if dest.exists() && !opts.force {
53 skipped.push("logo.svg".to_string());
54 } else {
55 fs::write(&dest, template::LOGO_SVG)
56 .with_context(|| format!("write {}", dest.display()))?;
57 written.push("logo.svg".to_string());
58 }
59 }
60 }
61
62 Ok(InitReport {
63 dir: opts.dir.clone(),
64 format: opts.format,
65 written,
66 skipped,
67 })
68}
69
70pub fn init_default(dir: impl Into<std::path::PathBuf>) -> Result<InitReport> {
72 init(&InitOptions {
73 dir: dir.into(),
74 format: Format::Typst,
75 logo: None,
76 force: false,
77 })
78}