diff --git a/Cargo.toml b/Cargo.toml index 92ab545..7547e7e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "oink" -version = "0.0.2" +version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -8,8 +8,8 @@ edition = "2021" [dependencies] #copy_dir = "0.1.3" pico-args = "0.5.0" -tera = "1.19.0" toml = "0.7.6" +upon = "0.7.1" [profile.release] opt-level = "s" diff --git a/README.md b/README.md index 3698ca1..647338e 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,5 @@ path = "/home/test/.config/oink/oink.toml" ## Libraries - [pico-args](https://crates.io/crates/pico-args) — argument parsing -- [tera](https://crates.io/crates/tera) — template engine - [toml](https://crates.io/crates/toml) — configuration parsing - +- [upon](https://crates.io/crates/upon) — template engine diff --git a/rust-toolchain.toml b/rust-toolchain.toml deleted file mode 100644 index 8fdd405..0000000 --- a/rust-toolchain.toml +++ /dev/null @@ -1,4 +0,0 @@ - -[toolchain] -channel = "nightly" - diff --git a/src/config.rs b/src/config.rs index 097e83a..130f9c5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,7 +1,7 @@ //! configuration struct and implementations use std::{ - collections::HashMap, + collections::{ BTreeMap, HashMap }, env::var, fs::{ create_dir, read_to_string, File }, io::Error, @@ -9,7 +9,7 @@ use std::{ process::exit }; -use tera::Context; +use upon::Value as ContextValue; use toml::{ map::Map, Value @@ -17,6 +17,8 @@ use toml::{ use crate::error; +pub type Context = BTreeMap; + /// configuration struct pub struct Config { pub dir: String, @@ -61,17 +63,17 @@ impl Config { if vars.is_some() { let vars = vars.unwrap().as_table().unwrap(); for (key, value) in vars.iter() { - output.insert(key, value.as_str().unwrap()); + output.insert(key.to_owned(), value.as_str().into()); } } let colors = self.inner.get("colors"); if colors.is_some() { let colors = colors.unwrap().as_table().unwrap(); - let mut map = HashMap::<&str, &str>::new(); + let mut map = Context::new(); for (key, value) in colors.iter() { - map.insert(key, value.as_str().unwrap()); + map.insert(key.to_owned(), value.as_str().unwrap().into()); } - output.insert("colors", &map); + output.insert("colors".to_owned(), map.into()); } output diff --git a/src/main.rs b/src/main.rs index f21206b..b7fba16 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,11 @@ -#![feature(error_in_core)] use std::process::exit; use pico_args::Arguments; -use tera::Tera; mod config; mod error; mod operation; + use crate::config::Config; fn main() { @@ -20,10 +19,8 @@ fn main() { // init configuration let config = Config::new(); - // tera init - let context = config.context(); - let template_dir = format!("{}/templates/*", &(config.dir)); - let mut tera = Tera::new(&template_dir).unwrap(); + // build template dir + let template_dir = format!("{}/templates/", &(config.dir)); let targets = config.targets(); if targets.len() == 0 { error::no_targets(); } @@ -35,11 +32,11 @@ fn main() { }, Some("build") => { - operation::build(&targets, &mut tera, &context); + operation::build(&targets, template_dir, &config); }, Some("full") => { - operation::build(&targets, &mut tera, &context); + operation::build(&targets, template_dir, &config); operation::apply(&targets); }, _ diff --git a/src/operation.rs b/src/operation.rs index 4db59bd..4df09dd 100644 --- a/src/operation.rs +++ b/src/operation.rs @@ -1,14 +1,15 @@ //! higher-level operation functions use std::{ env::var, - fs::{ self, File }, + fs::{self, read_to_string, File }, io::Write, - path::Path + path::{ Path, PathBuf } }; -use core::error::Error; use toml::{ map::Map, Value }; -use tera::{ Context, Tera }; +use upon::Engine; + +use crate::config::Config; pub fn apply(targets: &Vec>) { let home = var("HOME").unwrap(); @@ -47,9 +48,13 @@ pub fn apply(targets: &Vec>) { } } -pub fn build(targets: &Vec>, tera: &mut Tera, context: &Context) { +pub fn build(targets: &Vec>, template_dir: String, config: &Config) { let home = var("HOME").unwrap(); println!("running build:"); + + let engine = Engine::new(); + let context = config.context(); + for target in targets { // get name property let i_name = target.get("name"); @@ -63,14 +68,24 @@ pub fn build(targets: &Vec>, tera: &mut Tera, context: &Conte let name = i_name.unwrap().as_str().unwrap(); println!(" building \"{name}\":"); - // render template - let render = tera.render(name, context); - // handle rendering errors gracefully + // compile + println!(" compiling"); + let mut path = PathBuf::from(&template_dir); + path.push(name); + let content = read_to_string(path).unwrap(); + let template = engine.compile(&content); + if template.is_err() { + let error = template.err().unwrap(); + println!(" failed to compile template:\n {error}\n skipping"); + continue; + } + + // render + println!(" rendering"); + let render = template.unwrap().render(&context).to_string(); if render.is_err() { let error = render.err().unwrap(); - let message = error.source().unwrap(); - - println!(" failed to render template:\n {message}"); + println!(" failed to render template:\n {error}\n skipping"); continue; } @@ -87,7 +102,7 @@ pub fn build(targets: &Vec>, tera: &mut Tera, context: &Conte // write to destination file let written = write!(&mut file, "{output}"); if written.is_err() { println!(" failed to write to destination file at {path:?}"); } - else { println!(" completed successfully"); } + else { println!(" completed"); } } }