oink/src/config.rs

134 lines
3.3 KiB
Rust
Raw Normal View History

//! configuration struct and implementations
use std::{
2023-08-26 00:02:28 -04:00
collections::BTreeMap,
env::var,
fs::{ create_dir, read_to_string, File },
io::Error,
path::PathBuf,
process::exit
};
2023-08-25 23:48:43 -04:00
use upon::Value as ContextValue;
use toml::{
map::Map,
Value
};
use crate::{ error, util };
2023-08-25 23:48:43 -04:00
pub type Context = BTreeMap<String, ContextValue>;
pub type Table = toml::map::Map<String, Value>;
2023-08-25 23:48:43 -04:00
/// configuration struct
pub struct Config {
pub dir: String,
inner: Map<String, Value>
}
impl Config {
/// create a new Config using the file at '$HOME/.config/oink/oink.toml'
pub fn new() -> Config {
// get base config dir
let home = var("HOME").unwrap();
let mut dir = PathBuf::from(&home);
dir.push(".config/oink");
if !dir.exists() {
println!("missing directory at {dir:?}, creating...");
let setup = setup_dirs(&dir);
if setup.is_err() { error::setup_dirs(&dir); }
println!("created configuration directory, exiting...");
exit(0);
}
// read toml file
let mut toml_path = dir.clone();
toml_path.push("oink.toml");
let raw = read_to_string(toml_path).unwrap();
let toml_conf: Value = toml::from_str(&raw).unwrap();
let inner = toml_conf.as_table().unwrap();
// return struct
Config {
dir: dir.to_string_lossy().to_string(),
inner: inner.to_owned()
}
}
/// build context from "vars" and "colors" config sections
pub fn context(&self, target: &Table) -> Context {
let mut output = Context::new();
// pull global vars
if let Some(Value::Table(vars)) = self.inner.get("vars") {
for (key, value) in vars.iter() {
2023-08-25 23:48:43 -04:00
output.insert(key.to_owned(), value.as_str().into());
}
}
// pull target values
for (key, value) in target.iter() {
if key.to_uppercase() == *key {
output.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
}
/// build array of targets from "target" array
pub fn targets(&self) -> Vec<Map<String, Value>> {
let mut output = Vec::new();
let target_array: Option<&Value> = self.inner.get("target");
if target_array.is_some() {
let target_array = target_array.unwrap().as_array().unwrap().to_owned();
for target in target_array {
output.push(target.as_table().unwrap().to_owned());
}
}
output
}
}
fn setup_dirs(path: &PathBuf) -> Result<(), Error> {
// create main directory
create_dir(path)?;
// create template directory
let mut templates = path.clone();
templates.push("templates/");
create_dir(templates)?;
// create generated directory
let mut generated = path.clone();
generated.push("generated/");
create_dir(generated)?;
// create main toml
let mut toml = path.clone();
toml.push("oink.toml");
File::create(toml)?;
Ok(())
}