use super::{iter::Iter, Template};
use crate::properties::Properties;
use failure::{format_err, Error};
use handlebars::Handlebars;
use log::debug;
use std::io;
macro_rules! template {
($path:expr) => {
($path, include_str!(concat!("../../template/", $path)))
};
}
const DEFAULT_TEMPLATE_FILES: &[(&str, &str)] = &[
template!("Cargo.toml.hbs"),
template!("README.md.hbs"),
template!("src/application.rs.hbs"),
template!("src/bin/app/main.rs.hbs"),
template!("src/commands.rs.hbs"),
template!("src/commands/start.rs.hbs"),
template!("src/commands/version.rs.hbs"),
template!("src/config.rs.hbs"),
template!("src/error.rs.hbs"),
template!("src/lib.rs.hbs"),
template!("src/prelude.rs.hbs"),
template!("tests/acceptance.rs.hbs"),
];
#[derive(Debug)]
pub struct Collection(Handlebars);
impl Default for Collection {
fn default() -> Collection {
Collection::new(
DEFAULT_TEMPLATE_FILES
.iter()
.map(|(name, contents)| (*name, *contents)),
)
.unwrap()
}
}
impl Collection {
pub fn new<'a, I>(template_files: I) -> Result<Collection, Error>
where
I: Iterator<Item = (&'a str, &'a str)>,
{
let mut hbs = Handlebars::new();
hbs.set_strict_mode(true);
hbs.register_escape_fn(handlebars::no_escape);
for (name, contents) in template_files {
debug!("registering template: {}", name);
hbs.register_template_string(name, contents)
.map_err(|e| format_err!("couldn't register template '{}': {}", name, e))?;
}
Ok(Collection(hbs))
}
pub fn iter(&self) -> Iter {
Iter::new(self.0.get_templates().iter())
}
pub fn render<W>(
&self,
template: &Template,
properties: &Properties,
output: W,
) -> Result<(), Error>
where
W: io::Write,
{
let ctx = handlebars::Context::wraps(properties)?;
let mut render_context = handlebars::RenderContext::new(template.inner.name.as_ref());
let mut output = Output::new(output);
use handlebars::Renderable;
template
.inner
.render(&self.0, &ctx, &mut render_context, &mut output)
.map_err(|e| format_err!("render error: {}", e))
}
}
struct Output<W: io::Write>(W);
impl<W: io::Write> Output<W> {
pub fn new(writeable: W) -> Output<W> {
Output(writeable)
}
}
impl<W: io::Write> handlebars::Output for Output<W> {
fn write(&mut self, seg: &str) -> Result<(), io::Error> {
self.0.write_all(seg.as_bytes())
}
}