Functional templating
This commit is contained in:
84
src/context.rs
Normal file
84
src/context.rs
Normal file
@@ -0,0 +1,84 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::manifest::{FileDefinition, Manifest, Source, Transform, Params};
|
||||
use eyre::Result;
|
||||
use tracing::instrument;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Context {
|
||||
manifest: Manifest,
|
||||
root: Source,
|
||||
params: Params,
|
||||
}
|
||||
|
||||
impl Context {
|
||||
#[instrument(ret)]
|
||||
pub fn load(source: Source, params: Params) -> Result<Self> {
|
||||
let params = Params::load_user()?.merge(params);
|
||||
Ok(Context {
|
||||
manifest: load_manifest(&source)?,
|
||||
root: source.parent().ok_or_else(|| eyre::eyre!("Expect manifest to have a parent"))?,
|
||||
params,
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
pub fn generate(self, dest: PathBuf) -> Result<()> {
|
||||
std::fs::create_dir(&dest)?;
|
||||
|
||||
for (path, def) in &self.manifest.files {
|
||||
self.generate_file(&dest, path, def)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
fn generate_file(&self, dest: &Path, path: &PathBuf, def: &FileDefinition) -> Result<()> {
|
||||
std::fs::create_dir_all(dest.join(path).parent().expect("`dest` should be an absolute path with a parent"))?;
|
||||
let mut input = self
|
||||
.root
|
||||
.join(
|
||||
&def.src
|
||||
.clone()
|
||||
.unwrap_or_else(|| Source::Path(path.to_owned())),
|
||||
)
|
||||
.load()?;
|
||||
|
||||
for transform in &def.transforms {
|
||||
input = self.run_transform(transform, input)?;
|
||||
}
|
||||
std::fs::write(dest.join(path), input)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(skip(input))]
|
||||
fn run_transform(&self, transform: &Transform, input: Vec<u8>) -> Result<Vec<u8>> {
|
||||
match transform.r#type.as_str() {
|
||||
"template" => run_template(&transform.args, &self.params, input),
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(ret)]
|
||||
fn load_manifest(src: &Source) -> Result<Manifest> {
|
||||
Ok(toml::from_str(std::str::from_utf8(&src.load()?)?)?)
|
||||
}
|
||||
|
||||
|
||||
#[instrument(skip(input))]
|
||||
fn run_template(
|
||||
args: &Params,
|
||||
params: &Params,
|
||||
input: Vec<u8>,
|
||||
) -> Result<Vec<u8>> {
|
||||
let engine = upon::Engine::new();
|
||||
let context = args.clone().merge(params.clone());
|
||||
Ok(engine
|
||||
.compile(std::str::from_utf8(&input)?)?
|
||||
.render(context)
|
||||
.to_string()?
|
||||
.into_bytes())
|
||||
}
|
||||
Reference in New Issue
Block a user