Browse Source

Add option to pass in name=value pairs that will be moved into template

tags/0.1.0^2
Bèr Kessels 2 months ago
parent
commit
521b177266
4 changed files with 91 additions and 4 deletions
  1. 16
    0
      Cargo.lock
  2. 1
    0
      Cargo.toml
  3. 50
    3
      src/main.rs
  4. 24
    1
      tests/cli.rs

+ 16
- 0
Cargo.lock View File

@@ -39,6 +39,7 @@ version = "0.1.0"
dependencies = [
"assert_cmd",
"chrono",
"getopts",
"predicates",
"tempfile",
"tera",
@@ -193,6 +194,15 @@ dependencies = [
"typenum",
]

[[package]]
name = "getopts"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
dependencies = [
"unicode-width",
]

[[package]]
name = "getrandom"
version = "0.1.15"
@@ -709,6 +719,12 @@ dependencies = [
"unic-common",
]

[[package]]
name = "unicode-width"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"

[[package]]
name = "unicode-xid"
version = "0.2.1"

+ 1
- 0
Cargo.toml View File

@@ -9,6 +9,7 @@ edition = "2018"

[dependencies]
chrono = "0.4"
getopts = "0.2"
tera = "1.5.0"

[dev-dependencies]

+ 50
- 3
src/main.rs View File

@@ -1,12 +1,54 @@
use getopts::Options;
use std::env;
use tera::{Context, Tera};

mod basics;

fn print_usage(program: &str, opts: Options) {
let brief = format!("Usage: {} TEMPLATE_FILE [options]", program);
print!("{}", opts.usage(&brief));
}

fn main() {
let filename = std::env::args().nth(1).expect("No template given");
let args: Vec<String> = env::args().collect();
let program = args[0].clone();

let mut opts = Options::new();
opts.optmulti("v", "var", "provide name=value variable pair", "NAME=VAL");
opts.optflag("h", "help", "print this help menu");
let matches = match opts.parse(&args[1..]) {
Ok(m) => m,
Err(f) => {
panic!(f.to_string())
}
};

// print help when requested
if matches.opt_present("h") {
print_usage(&program, opts);
return;
}

// Filename is the first free option
let filename = if !matches.free.is_empty() {
matches.free[0].clone()
} else {
eprintln!("No template file given");
print_usage(&program, opts);
::std::process::exit(1);
};
let template = std::fs::read_to_string(filename).expect("No such file or directory");

let tera = match Tera::one_off(&template, &context(), true) {
// Extract name value pairs.
// TODO: avoid mut. Assign from an iter() maybe?
// TODO: investigate why the borrowchecker accepts a String but not a str
// and how and if we want to fix that?
let mut user_pairs: Vec<Vec<String>> = vec![];
for pair in &matches.opt_strs("v") {
user_pairs.push(pair.splitn(2, '=').map(|part| part.to_string()).collect());
}

let tera = match Tera::one_off(&template, &context(user_pairs), true) {
Ok(t) => t,
Err(e) => {
println!("Parsing error: {}", e);
@@ -17,8 +59,13 @@ fn main() {
println!("{}", tera);
}

fn context() -> Context {
fn context(user_pairs: Vec<Vec<String>>) -> Context {
let mut context = Context::new();

for pair in user_pairs {
context.insert(pair[0].as_str(), pair[1].as_str());
}

context.extend(basics::context());
context
}

+ 24
- 1
tests/cli.rs View File

@@ -10,7 +10,7 @@ fn missing_template_name_test() -> Result<(), Box<dyn std::error::Error>> {
let mut cmd = Command::cargo_bin("blek")?;
cmd.assert()
.failure()
.stderr(predicate::str::contains("No template given"));
.stderr(predicate::str::contains("No template file given"));

Ok(())
}
@@ -42,3 +42,26 @@ fn with_predefined_variables() -> Result<(), Box<dyn std::error::Error>> {

Ok(())
}

#[test]
fn with_argument_variables() -> Result<(), Box<dyn std::error::Error>> {
let mut file = NamedTempFile::new()?;
// We need to escape the {{, with two more {{.
writeln!(
file,
"Invoice number {{{{ number }}}}\n Total €{{{{ total }}}}"
)?;

let mut cmd = Command::cargo_bin("blek")?;
cmd.arg(file.path());
cmd.arg("--var");
cmd.arg("number=42");
cmd.arg("--var");
cmd.arg("total=13.37");

cmd.assert()
.success()
.stdout(predicate::str::contains("Invoice number 42\n Total €13.37"));

Ok(())
}

Loading…
Cancel
Save