configuration is more flexible; targets can specify their base file, introduced palettes, and targets can specify & override variables

This commit is contained in:
Valerie Wolfe 2024-07-02 13:24:30 -04:00
parent 502e5a7615
commit 7fab543476
6 changed files with 58 additions and 28 deletions

View file

@ -1,6 +1,6 @@
[package] [package]
name = "oink" name = "oink"
version = "0.1.1" version = "0.2.0"
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

View file

@ -15,9 +15,10 @@ use toml::{
Value Value
}; };
use crate::error; use crate::{ error, util };
pub type Context = BTreeMap<String, ContextValue>; pub type Context = BTreeMap<String, ContextValue>;
pub type Table = toml::map::Map<String, Value>;
/// configuration struct /// configuration struct
pub struct Config { pub struct Config {
@ -55,25 +56,38 @@ impl Config {
} }
} }
/// build tera context from "vars" and "colors" config sections /// build context from "vars" and "colors" config sections
pub fn context(&self) -> Context { pub fn context(&self, target: &Table) -> Context {
let mut output = Context::new(); let mut output = Context::new();
let vars = self.inner.get("vars"); // pull global vars
if vars.is_some() { if let Some(Value::Table(vars)) = self.inner.get("vars") {
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.to_owned(), value.as_str().into());
} }
} }
let colors = self.inner.get("colors");
if colors.is_some() { // pull target values
let colors = colors.unwrap().as_table().unwrap(); for (key, value) in target.iter() {
let mut map = Context::new(); if key.to_uppercase() == *key {
for (key, value) in colors.iter() { output.insert(key.to_owned(), value.as_str().unwrap().into());
map.insert(key.to_owned(), value.as_str().unwrap().into()); }
}
// pull palette
let palette_name: Option<String> =
if let Some(Value::String(name)) = target.get("use_palette") { Some(name.clone()) }
else if let Some(Value::String(name)) = self.inner.get("use_palette") { Some(name.clone()) }
else { None };
if let Some(Value::Array(array)) = self.inner.get("palette") {
let palette = util::matches(array.to_owned(), palette_name.unwrap_or("default".to_string()));
if let Some(Value::Table(palette)) = palette {
let colors = Context::new();
for(key, value) in palette.iter() {
output.insert(key.to_owned(), value.as_str().unwrap().into());
}
output.insert("palette".to_string(), colors.into());
} }
output.insert("colors".to_owned(), map.into());
} }
output output

View file

@ -3,6 +3,11 @@ use std::{
process::exit process::exit
}; };
pub fn no_command() {
crate::help_text();
exit(1);
}
pub fn no_targets() { pub fn no_targets() {
println!("oink: configuration has no targets"); println!("oink: configuration has no targets");
exit(2); exit(2);

View file

@ -1,10 +1,10 @@
use std::process::exit;
use pico_args::Arguments; use pico_args::Arguments;
mod config; mod config;
mod error; mod error;
mod operation; mod operation;
mod util;
use crate::config::Config; use crate::config::Config;
@ -27,23 +27,18 @@ fn main() {
match operation.as_deref() { match operation.as_deref() {
Some("apply") Some("apply")
=> { => operation::apply(&targets),
operation::apply(&targets);
},
Some("build") Some("build")
=> { => operation::build(&targets, template_dir, &config),
operation::build(&targets, template_dir, &config);
},
Some("full") Some("full")
=> { => {
operation::build(&targets, template_dir, &config); operation::build(&targets, template_dir, &config);
operation::apply(&targets); operation::apply(&targets);
}, },
_
=> { _ => error::no_command()
help_text();
exit(1);
}
} }
} }

View file

@ -69,9 +69,9 @@ pub fn build(targets: &Vec<Map<String, Value>>, template_dir: String, config: &C
println!("running build:"); println!("running build:");
let engine = Engine::new(); let engine = Engine::new();
let context = config.context();
for target in targets { for target in targets {
let context = config.context(target);
// 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
@ -87,7 +87,9 @@ pub fn build(targets: &Vec<Map<String, Value>>, template_dir: String, config: &C
// compile // compile
println!(" {ITALIC}compiling{RESET}"); println!(" {ITALIC}compiling{RESET}");
let mut path = PathBuf::from(&template_dir); let mut path = PathBuf::from(&template_dir);
path.push(name); if let Some(Value::String(base)) = target.get("base") { path.push(base); }
else { path.push(name); }
let content = read_to_string(path).unwrap(); let content = read_to_string(path).unwrap();
let template = engine.compile(&content); let template = engine.compile(&content);
if template.is_err() { if template.is_err() {

14
src/util.rs Normal file
View file

@ -0,0 +1,14 @@
use toml::{ value::Array, Value };
pub fn matches(array: Array, to_match: String) -> Option<Value> {
array.iter().filter(|value| {
if let Value::Table(table) = value {
if let Some(Value::String(name)) = table.get("name") {
return *name == to_match;
}
}
return false;
}).map(|value| value.to_owned()).nth(0)
}