Compare commits
No commits in common. "3f6e996c64d24574f71ae45ae1ba03e1bc0c7092" and "3941e77f6ad66248035758345021af5688a0a448" have entirely different histories.
3f6e996c64
...
3941e77f6a
6 changed files with 43 additions and 69 deletions
|
@ -1,15 +1,15 @@
|
||||||
[package]
|
[package]
|
||||||
name = "oink"
|
name = "oink"
|
||||||
version = "0.1.1"
|
version = "0.0.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
#copy_dir = "0.1.3"
|
||||||
pico-args = "0.5.0"
|
pico-args = "0.5.0"
|
||||||
termion = "2.0.1"
|
tera = "1.19.0"
|
||||||
toml = "0.7.6"
|
toml = "0.7.6"
|
||||||
upon = "0.7.1"
|
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = "s"
|
opt-level = "s"
|
||||||
|
|
|
@ -41,6 +41,6 @@ path = "/home/test/.config/oink/oink.toml"
|
||||||
## Libraries
|
## Libraries
|
||||||
|
|
||||||
- [pico-args](https://crates.io/crates/pico-args) — argument parsing
|
- [pico-args](https://crates.io/crates/pico-args) — argument parsing
|
||||||
- [termion](https://crates.io/crates/termion) — ANSI formatting
|
- [tera](https://crates.io/crates/tera) — template engine
|
||||||
- [toml](https://crates.io/crates/toml) — configuration parsing
|
- [toml](https://crates.io/crates/toml) — configuration parsing
|
||||||
- [upon](https://crates.io/crates/upon) — template engine
|
|
||||||
|
|
4
rust-toolchain.toml
Normal file
4
rust-toolchain.toml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
[toolchain]
|
||||||
|
channel = "nightly"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! configuration struct and implementations
|
//! configuration struct and implementations
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::{ BTreeMap, HashMap },
|
collections::HashMap,
|
||||||
env::var,
|
env::var,
|
||||||
fs::{ create_dir, read_to_string, File },
|
fs::{ create_dir, read_to_string, File },
|
||||||
io::Error,
|
io::Error,
|
||||||
|
@ -9,7 +9,7 @@ use std::{
|
||||||
process::exit
|
process::exit
|
||||||
};
|
};
|
||||||
|
|
||||||
use upon::Value as ContextValue;
|
use tera::Context;
|
||||||
use toml::{
|
use toml::{
|
||||||
map::Map,
|
map::Map,
|
||||||
Value
|
Value
|
||||||
|
@ -17,8 +17,6 @@ use toml::{
|
||||||
|
|
||||||
use crate::error;
|
use crate::error;
|
||||||
|
|
||||||
pub type Context = BTreeMap<String, ContextValue>;
|
|
||||||
|
|
||||||
/// configuration struct
|
/// configuration struct
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub dir: String,
|
pub dir: String,
|
||||||
|
@ -63,17 +61,17 @@ impl Config {
|
||||||
if vars.is_some() {
|
if vars.is_some() {
|
||||||
let vars = vars.unwrap().as_table().unwrap();
|
let vars = vars.unwrap().as_table().unwrap();
|
||||||
for (key, value) in vars.iter() {
|
for (key, value) in vars.iter() {
|
||||||
output.insert(key.to_owned(), value.as_str().into());
|
output.insert(key, value.as_str().unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let colors = self.inner.get("colors");
|
let colors = self.inner.get("colors");
|
||||||
if colors.is_some() {
|
if colors.is_some() {
|
||||||
let colors = colors.unwrap().as_table().unwrap();
|
let colors = colors.unwrap().as_table().unwrap();
|
||||||
let mut map = Context::new();
|
let mut map = HashMap::<&str, &str>::new();
|
||||||
for (key, value) in colors.iter() {
|
for (key, value) in colors.iter() {
|
||||||
map.insert(key.to_owned(), value.as_str().unwrap().into());
|
map.insert(key, value.as_str().unwrap());
|
||||||
}
|
}
|
||||||
output.insert("colors".to_owned(), map.into());
|
output.insert("colors", &map);
|
||||||
}
|
}
|
||||||
|
|
||||||
output
|
output
|
||||||
|
|
13
src/main.rs
13
src/main.rs
|
@ -1,11 +1,12 @@
|
||||||
|
#![feature(error_in_core)]
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
|
||||||
use pico_args::Arguments;
|
use pico_args::Arguments;
|
||||||
|
use tera::Tera;
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
mod error;
|
mod error;
|
||||||
mod operation;
|
mod operation;
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -19,8 +20,10 @@ fn main() {
|
||||||
// init configuration
|
// init configuration
|
||||||
let config = Config::new();
|
let config = Config::new();
|
||||||
|
|
||||||
// build template dir
|
// tera init
|
||||||
let template_dir = format!("{}/templates/", &(config.dir));
|
let context = config.context();
|
||||||
|
let template_dir = format!("{}/templates/*", &(config.dir));
|
||||||
|
let mut tera = Tera::new(&template_dir).unwrap();
|
||||||
|
|
||||||
let targets = config.targets();
|
let targets = config.targets();
|
||||||
if targets.len() == 0 { error::no_targets(); }
|
if targets.len() == 0 { error::no_targets(); }
|
||||||
|
@ -32,11 +35,11 @@ fn main() {
|
||||||
},
|
},
|
||||||
Some("build")
|
Some("build")
|
||||||
=> {
|
=> {
|
||||||
operation::build(&targets, template_dir, &config);
|
operation::build(&targets, &mut tera, &context);
|
||||||
},
|
},
|
||||||
Some("full")
|
Some("full")
|
||||||
=> {
|
=> {
|
||||||
operation::build(&targets, template_dir, &config);
|
operation::build(&targets, &mut tera, &context);
|
||||||
operation::apply(&targets);
|
operation::apply(&targets);
|
||||||
},
|
},
|
||||||
_
|
_
|
||||||
|
|
|
@ -1,27 +1,14 @@
|
||||||
//! higher-level operation functions
|
//! higher-level operation functions
|
||||||
use std::{
|
use std::{
|
||||||
env::var,
|
env::var,
|
||||||
fs::{self, read_to_string, File },
|
fs::{ self, File },
|
||||||
io::Write,
|
io::Write,
|
||||||
path::{ Path, PathBuf }
|
path::Path
|
||||||
};
|
};
|
||||||
|
use core::error::Error;
|
||||||
|
|
||||||
use termion::{
|
|
||||||
color::{ self, Fg },
|
|
||||||
style::{
|
|
||||||
Bold as BOLD,
|
|
||||||
Italic as ITALIC,
|
|
||||||
Reset as RESET
|
|
||||||
}
|
|
||||||
};
|
|
||||||
use toml::{ map::Map, Value };
|
use toml::{ map::Map, Value };
|
||||||
use upon::Engine;
|
use tera::{ Context, Tera };
|
||||||
|
|
||||||
use crate::config::Config;
|
|
||||||
|
|
||||||
static SUCCESS: Fg<color::Green> = Fg(color::Green);
|
|
||||||
static WARNING: Fg<color::Yellow> = Fg(color::Yellow);
|
|
||||||
static FAILURE: Fg<color::Red> = Fg(color::Red);
|
|
||||||
|
|
||||||
pub fn apply(targets: &Vec<Map<String, Value>>) {
|
pub fn apply(targets: &Vec<Map<String, Value>>) {
|
||||||
let home = var("HOME").unwrap();
|
let home = var("HOME").unwrap();
|
||||||
|
@ -35,12 +22,12 @@ pub fn apply(targets: &Vec<Map<String, Value>>) {
|
||||||
if path.is_none() {
|
if path.is_none() {
|
||||||
if i_name.is_some() {
|
if i_name.is_some() {
|
||||||
let name = i_name.unwrap().as_str().unwrap();
|
let name = i_name.unwrap().as_str().unwrap();
|
||||||
println!(" {WARNING}\"{name}\" is missing its path property; skipping{RESET}");
|
println!(" \"{name}\" is missing its path property; skipping");
|
||||||
} else { println!(" {WARNING}skipping empty target{RESET}"); }
|
} else { println!(" skipping empty target"); }
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if i_name.is_none() {
|
if i_name.is_none() {
|
||||||
println!(" {WARNING}target missing name; skipping{RESET}");
|
println!(" target missing name; skipping");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,28 +42,20 @@ pub fn apply(targets: &Vec<Map<String, Value>>) {
|
||||||
|
|
||||||
// copy and print
|
// copy and print
|
||||||
let result = fs::copy(source, destination);
|
let result = fs::copy(source, destination);
|
||||||
if result.is_err() {
|
if result.is_err() { println!(" failed to copy!"); }
|
||||||
println!(" {BOLD}{FAILURE}failed to copy{RESET}");
|
else { println!(" completed successfully"); }
|
||||||
}
|
|
||||||
else {
|
|
||||||
println!(" {BOLD}{SUCCESS}completed{RESET}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(targets: &Vec<Map<String, Value>>, template_dir: String, config: &Config) {
|
pub fn build(targets: &Vec<Map<String, Value>>, tera: &mut Tera, context: &Context) {
|
||||||
let home = var("HOME").unwrap();
|
let home = var("HOME").unwrap();
|
||||||
println!("running build:");
|
println!("running build:");
|
||||||
|
|
||||||
let engine = Engine::new();
|
|
||||||
let context = config.context();
|
|
||||||
|
|
||||||
for target in targets {
|
for target in targets {
|
||||||
// get name property
|
// get name property
|
||||||
let i_name = target.get("name");
|
let i_name = target.get("name");
|
||||||
// handle empty names gracefully
|
// handle empty names gracefully
|
||||||
if i_name.is_none() {
|
if i_name.is_none() {
|
||||||
println!(" {WARNING}target missing name; skipping{RESET}");
|
println!(" target missing name; skipping");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,24 +63,14 @@ pub fn build(targets: &Vec<Map<String, Value>>, template_dir: String, config: &C
|
||||||
let name = i_name.unwrap().as_str().unwrap();
|
let name = i_name.unwrap().as_str().unwrap();
|
||||||
println!(" building \"{name}\":");
|
println!(" building \"{name}\":");
|
||||||
|
|
||||||
// compile
|
// render template
|
||||||
println!(" {ITALIC}compiling{RESET}");
|
let render = tera.render(name, context);
|
||||||
let mut path = PathBuf::from(&template_dir);
|
// handle rendering errors gracefully
|
||||||
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!(" {BOLD}{FAILURE}failed to compile template:{RESET}\n {FAILURE}{error}\n {BOLD}skipping{RESET}");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// render
|
|
||||||
println!(" {ITALIC}rendering{RESET}");
|
|
||||||
let render = template.unwrap().render(&context).to_string();
|
|
||||||
if render.is_err() {
|
if render.is_err() {
|
||||||
let error = render.err().unwrap();
|
let error = render.err().unwrap();
|
||||||
println!(" {BOLD}{FAILURE}failed to render template:{RESET}\n {FAILURE}{error}\n {BOLD}skipping{RESET}");
|
let message = error.source().unwrap();
|
||||||
|
|
||||||
|
println!(" failed to render template:\n {message}");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,14 +80,14 @@ pub fn build(targets: &Vec<Map<String, Value>>, template_dir: String, config: &C
|
||||||
let path = Path::new(&destination);
|
let path = Path::new(&destination);
|
||||||
let i_file = File::create(path);
|
let i_file = File::create(path);
|
||||||
if i_file.is_err() {
|
if i_file.is_err() {
|
||||||
println!(" {BOLD}{FAILURE}failed to create destination file at {path:?}{RESET}");
|
println!(" failed to create destination file at {path:?}");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let mut file = i_file.unwrap();
|
let mut file = i_file.unwrap();
|
||||||
// write to destination file
|
// write to destination file
|
||||||
let written = write!(&mut file, "{output}");
|
let written = write!(&mut file, "{output}");
|
||||||
if written.is_err() { println!(" {FAILURE}failed to write to destination file at {path:?}{RESET}"); }
|
if written.is_err() { println!(" failed to write to destination file at {path:?}"); }
|
||||||
else { println!(" {BOLD}{SUCCESS}completed{RESET}"); }
|
else { println!(" completed successfully"); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue