use structopt::StructOpt; use toml::Value; use std::collections::hash_map::DefaultHasher; use std::fs::{copy, create_dir, read_to_string, write}; use std::path::PathBuf; #[derive(StructOpt, Debug)] /// structure representing command line arguments struct Opt { #[structopt(name = "FILE")] /// The input file. /// It contains all the settings related to substitution toml: PathBuf, #[structopt(short, long, default_value = "output")] /// Output directory. output: PathBuf, #[structopt(short, long)] /// Template to be processed. /// if a directory, then all the unspecified /// files will be copied to the output as well. template: PathBuf, } /// replaces {{ value }} with actual value fn replace(mut template: String, rules: &[(String, String)]) -> String { for (x, y) in rules { let l = format!("{{{{ {} }}}}", x); template = template.replace(&l, y) } template } /// collects table into a vector of String pairs fn collect_table(table: &Value) -> Vec<(String, String)> { table.as_table() .unwrap() .keys() .map( |x| (x.clone(), String::from(table[x].as_str().unwrap())) ).collect() } fn main() { // parse command line arguments let opt = Opt::from_args(); //println!("{:?}", opt); // parse toml let mut value = read_to_string(&opt.toml).unwrap().parse::().unwrap(); //println!("{:#?}", value); // create output directory // if it doesn't exist if !opt.output.exists() { create_dir(&opt.output).unwrap(); } // read template let input = read_to_string( &[opt.template, PathBuf::from("front.html")] .iter() .collect::(), ).unwrap(); // create rules // hope to god the toml is correctly formatted // start with removing page rules let page = value.as_table_mut().unwrap().remove("page").unwrap().clone(); // collect global rules into a vec let global = collect_table(&value); // iterate over pages for (index, value) in page.as_array().unwrap().iter().enumerate() { let table = collect_table(&value); let content = replace(input.clone(), table.as_slice()); // create the files let target = format!("front-{}.html", index); println!("writing {}", target); write(&[&opt.output, &PathBuf::from(target)].iter().collect::(), content); } //println!("{:#?}", global); }