Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 6 additions & 46 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ edition = "2018"

[dependencies]
structopt = "0.3"
handlebars = "2.0" # "3.0.0-beta.4"
handlebars = "3.0.1"
serde = "1.0"
serde_yaml = "0.8"
glob = "0.3"
65 changes: 65 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#[derive(Debug)]
pub struct HelperDecl {
pub name: String,
pub file: String,
}
impl HelperDecl {
fn new() -> HelperDecl{
HelperDecl {
name: String::new(),
file: String::new(),
}
}
pub fn from_str(inp: &str) -> HelperDecl {
let xs: Vec<&str> = inp.split(":").collect();

let mut helper = HelperDecl::new();
let def_len = xs.len();
if 0 < def_len && def_len <= 2 && xs[0].len() > 0 {
helper.name.push_str(xs[ 0 ]);
helper.file.push_str(xs[ def_len - 1 ]);
} else {
panic!("Helper must be provided in one of two formats: <name>:<file> or <file>. (There is {} items)", def_len);
}

helper
}
}


#[test]
fn test_single() {
let input = "helper";
let h = HelperDecl::from_str(input);
assert!(h.name == "helper");
assert!(h.file == "helper");
}

#[test]
fn test_named_one() {
let input = "nas:numfmt";
let h = HelperDecl::from_str(input);
assert!(h.name == "nas");
assert!(h.file == "numfmt");
}

#[test]
#[should_panic]
fn test_empty() {
let input = "";
HelperDecl::from_str(input);
}

#[test]
#[should_panic]
fn test_too_many_params() {
let input = "y:nas:numfmt";
HelperDecl::from_str(input);
}

#[test]
#[should_panic]
fn test_too_many_seps() {
let input = ":nas:";
HelperDecl::from_str(input);
}
78 changes: 69 additions & 9 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,26 @@ use std::error::Error;
use std::fs;
use std::fs::File;
use std::path::Path;
use std::path::PathBuf;
use std::str::from_utf8;
use std::process::Command;


extern crate structopt;
extern crate handlebars;
extern crate serde_yaml;
#[macro_use] extern crate handlebars;

use structopt::StructOpt;
use std::path::PathBuf;

use serde_yaml::Value;

//use handlebars as hbs;
use handlebars::Handlebars;
use handlebars::Helper;
use handlebars::RenderError;
use handlebars::Output;
use handlebars::Context;
use handlebars::RenderContext;
use handlebars::HelperResult;

use glob::glob;

#[derive(Debug, StructOpt)]
Expand Down Expand Up @@ -42,25 +53,50 @@ struct Opt {
/// Make error output verobse
verbose: bool,

#[structopt(short = "h", long = "helper")]
/// Register helper
helpers: Vec<String>,

#[structopt(short = "E", long)]
/// Use environment variables as data source
env: bool,
}

fn main() -> Result<(), Box<dyn Error>> {

let opt = Opt::from_args();

if opt.verbose { eprintln!("{:?}", opt); }

let mut reg = Handlebars::new();

match opt.register_glob {
Some(pattern) => {
if opt.verbose {
eprintln!( "Registring templates matching to {:?}", pattern );
}
register_templates_from_pattern(&mut reg, pattern)?;
reg = register_templates_from_pattern(&mut reg, pattern)?;
}
None => if opt.verbose {
eprintln!("No glob provided for templates registration.");
}
};

for helper_opt in opt.helpers {
let helper = hbs_cli::HelperDecl::from_str(&helper_opt);
reg = import_command_as_helper(
&mut reg,
String::from(helper.name),
String::from(helper.file),
)?;
}

// try helpers:
handlebars_helper!(hex: |v: i64| format!("0x{:x}", v));
reg.register_helper("hex", Box::new(hex));
// end


let propsfile = File::open(opt.propsfile)?;
let data: Value = serde_yaml::from_reader(propsfile)?;
let template = fs::read_to_string(opt.template)?;
Expand All @@ -74,10 +110,34 @@ fn main() -> Result<(), Box<dyn Error>> {
Ok(())
}

fn register_templates_from_pattern(
hbs: &mut Handlebars,
/// Leverages the command to be a handlebars helper. Command must be in the PATH
fn import_command_as_helper<'a>(
hbs: &'a mut Handlebars<'a>,
helper_name: String,
command_name: String,
) -> Result<Handlebars<'a>, Box<dyn Error>> {
hbs.register_helper(&helper_name,
Box::new(move
| h: &Helper, _r: &Handlebars, _: &Context, _rc: &mut RenderContext,
out: &mut dyn Output | -> HelperResult {
let param = h.param(0).ok_or(RenderError::new("param not found"))?;
let param = param.value().as_str().unwrap_or("");

let proc = Command::new(&command_name)
.args(&[ param ])
.output()
.expect("Failed to execute process");
out.write(from_utf8(&proc.stdout).unwrap())?;

Ok(())
}));
Ok(*hbs)
}

fn register_templates_from_pattern<'a>(
hbs: &'a mut Handlebars<'a>,
pattern: String
) -> Result<(), Box<dyn Error>> {
) -> Result<Handlebars<'a>, Box<dyn Error>> {
for entry in glob( &pattern ).expect( "Failed to read glob pattern" ) {
match entry {
Ok( path ) => {
Expand All @@ -94,5 +154,5 @@ fn register_templates_from_pattern(
Err(e) => eprintln!("{:?}", e)
}
}
Ok(())
Ok(*hbs)
}