diff --git a/Cargo.lock b/Cargo.lock index e74b78e..f1c0217 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -236,6 +236,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -287,6 +296,29 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.101", + "unicode-xid", +] + [[package]] name = "dirs" version = "6.0.0" @@ -1083,6 +1115,7 @@ dependencies = [ "clap", "clap-markdown", "ctrlc", + "derive_more", "dirs", "inquire", "open", @@ -1093,6 +1126,7 @@ dependencies = [ "strum 0.27.1", "strum_macros 0.27.1", "tempfile", + "thiserror", ] [[package]] @@ -1263,6 +1297,15 @@ version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "1.0.7" @@ -1359,6 +1402,12 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + [[package]] name = "serde" version = "1.0.219" @@ -1797,6 +1846,12 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "untrusted" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index 6992872..9ceea66 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ chrono = { version = "0.4.41", features = ["serde"] } clap = { version = "4.5.38", features = ["derive"] } clap-markdown = "0.1.5" ctrlc = "3.4.7" +derive_more = { version = "2.1.1", features = ["full"] } dirs = "6.0.0" inquire = "0.7.5" open = "5.3.3" @@ -30,3 +31,4 @@ spinners = "4.2.0" strum = "0.27.1" strum_macros = "0.27.1" tempfile = "3.20.0" +thiserror = "2.0.20" diff --git a/scripts/test-init.sh b/scripts/test-init.sh index fb5dd8b..879e8a3 100755 --- a/scripts/test-init.sh +++ b/scripts/test-init.sh @@ -16,7 +16,7 @@ pwd --title ExampleProject \ --tags "economics, ComPuterScience" \ --color red \ - --template HTML \ + --template Markdown \ --description "This is an example project" \ --license "gPl-2.0" diff --git a/src/cmd/init.rs b/src/cmd/init.rs index 7fc6ec0..ffa005d 100644 --- a/src/cmd/init.rs +++ b/src/cmd/init.rs @@ -1,15 +1,13 @@ -use std::{ - error::Error, - fs::{self}, - process::Command, - str::FromStr, -}; +use std::{collections::HashMap, error::Error, process::Command, str::FromStr}; use clap::Args; use spinners::{Spinner, Spinners}; use strum::IntoEnumIterator; -use crate::{config, template::Template}; +use crate::{ + config, + templates::{templater::Templater, CLITemplate, Renderer}, +}; /// Options for the `oseda init` command #[derive(Args, Debug)] @@ -41,26 +39,6 @@ pub struct InitOptions { pub description: Option, } -// embed all the static markdown template files into binary -const MD_VITE_CONFIG_JS: &str = include_str!("../static/md-templates/vite.config.js"); -const MD_INDEX_HTML: &str = include_str!("../static/md-templates/index.html"); -const MD_MAIN_JS: &str = include_str!("../static/md-templates/main.js"); -const MD_SLIDES: &str = include_str!("../static/md-templates/slides.md"); -const MD_CUSTOM_CSS: &str = include_str!("../static/md-templates/custom.css"); -const MD_FERRIS: &[u8] = include_bytes!("../static/md-templates/ferris.png"); -const MD_GITIGNORE: &str = include_str!("../static/md-templates/.gitignore"); -const MD_FAVICON: &[u8] = include_bytes!("../static/md-templates/favicon.png"); - -// do the same with the html templates -const HTML_VITE_CONFIG_JS: &str = include_str!("../static/html-templates/vite.config.js"); -const HTML_INDEX_HTML: &str = include_str!("../static/html-templates/index.html"); -const HTML_MAIN_JS: &str = include_str!("../static/html-templates/main.js"); -const HTML_SLIDES: &str = include_str!("../static/html-templates/slides.html"); -const HTML_CUSTOM_CSS: &str = include_str!("../static/html-templates/custom.css"); -const HTML_FERRIS: &[u8] = include_bytes!("../static/html-templates/ferris.png"); -const HTML_GITIGNORE: &str = include_str!("../static/html-templates/.gitignore"); -const HTML_FAVICON: &[u8] = include_bytes!("../static/html-templates/favicon.png"); - /// Initialize an Oseda project with the provided options /// /// This command will: @@ -77,7 +55,7 @@ const HTML_FAVICON: &[u8] = include_bytes!("../static/html-templates/favicon.png pub fn init(opts: InitOptions) -> Result<(), Box> { let template = match opts.template { Some(ref arg_template) => { - Template::from_str(arg_template).map_err(|_| "Invalid template".to_string())? + CLITemplate::from_str(arg_template).map_err(|_| "Invalid template".to_string())? } None => prompt_template()?, }; @@ -132,56 +110,18 @@ pub fn init(opts: InitOptions) -> Result<(), Box> { config::write_config(&conf.title, &conf)?; - // 99% sure we'll only ever have to maintain these two template schemas - match template { - Template::Markdown => { - // fs::write(format!("{}/package.json", &conf.title), MD_PACKAGE_JSON)?; - fs::write(format!("{}/vite.config.js", &conf.title), MD_VITE_CONFIG_JS)?; - fs::write(format!("{}/index.html", &conf.title), MD_INDEX_HTML)?; - fs::write(format!("{}/.gitignore", &conf.title), MD_GITIGNORE)?; - - std::fs::create_dir_all(format!("{}/src", &conf.title))?; - fs::write(format!("{}/src/main.js", &conf.title), MD_MAIN_JS)?; - - std::fs::create_dir_all(format!("{}/slides", &conf.title))?; - fs::write(format!("{}/slides/slides.md", &conf.title), MD_SLIDES)?; + // empty hashmap for now + let mut params: HashMap = HashMap::new(); + params.insert(String::from("TITLE"), conf.title.clone()); - std::fs::create_dir_all(format!("{}/css", &conf.title))?; - fs::write(format!("{}/css/custom.css", &conf.title), MD_CUSTOM_CSS)?; - - std::fs::create_dir_all(format!("{}/public", &conf.title))?; - fs::write(format!("{}/public/ferris.png", &conf.title), MD_FERRIS)?; - fs::write(format!("{}/public/favicon.png", &conf.title), MD_FAVICON)?; - } - Template::HTML => { - // fs::write(format!("{}/package.json", &conf.title), HTML_PACKAGE_JSON)?; - fs::write( - format!("{}/vite.config.js", &conf.title), - HTML_VITE_CONFIG_JS, - )?; - fs::write(format!("{}/index.html", &conf.title), HTML_INDEX_HTML)?; - fs::write(format!("{}/.gitignore", &conf.title), HTML_GITIGNORE)?; - - std::fs::create_dir_all(format!("{}/src", &conf.title))?; - fs::write(format!("{}/src/main.js", &conf.title), HTML_MAIN_JS)?; - - std::fs::create_dir_all(format!("{}/slides", &conf.title))?; - fs::write(format!("{}/slides/slides.html", &conf.title), HTML_SLIDES)?; - - std::fs::create_dir_all(format!("{}/css", &conf.title))?; - fs::write(format!("{}/css/custom.css", &conf.title), HTML_CUSTOM_CSS)?; - - std::fs::create_dir_all(format!("{}/public", &conf.title))?; - fs::write(format!("{}/public/ferris.png", &conf.title), HTML_FERRIS)?; - fs::write(format!("{}/public/favicon.png", &conf.title), HTML_FAVICON)?; - } - } + let templater = Templater::new(template, params); + templater.write_to_fs(&conf.title)?; Ok(()) } -fn prompt_template() -> Result> { - let template_opts: Vec