From ebc18e92a648650f3f4781ab3b015b987cf262b8 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Fri, 27 May 2022 00:42:12 +0100 Subject: feat: add maximum recursion depth on code generation --- src/main.rs | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/main.rs b/src/main.rs index 23789b6..ea4e4f7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,7 +17,11 @@ type Blocks<'a> = HashMap>; #[derive(Parser, Debug)] #[clap(author, version, about, long_about = None)] struct Config { - /// Base output directory (default: './code') + /// Maximum substitution depth + #[clap(short, long, default_value_t = 10)] + depth: u32, + + /// Base output directory [default: './code'] #[clap(short, long)] output: Option, @@ -91,23 +95,28 @@ fn indent<'a>(input: Cow<'a,str>, indent: usize) -> Cow<'a,str> { * of the borrowed value `text`. Moreover `text` takes ownership of `new_text: String` using * the `Cow::from()` function. No heap allocation is performed, and the string is not copied. */ -fn build(base: &Option, blocks: &Blocks) { +fn build(base: &Option, blocks: &Blocks, depth: u32) { lazy_static! { static ref PATH: Regex = Regex::new(r"^(?:[[:word:]\.-]+/)*[[:word:]\.-]+\.[[:alpha:]]+$").unwrap(); static ref MACRO: Regex = Regex::new(r"(?m)^([[:blank:]]*)<<([^>\s]+)>>").unwrap(); } blocks.iter().for_each(|(k,v)| if PATH.is_match(k) { + let mut d = 0; let mut code = v.clone(); // No clone is happening because the value is a `Borrowed` // Here `replace_all` returns a `Owned` value only when a replacement takes place. // We can use it to recursively build blocks of code until no more substitutions are // necessary (i.e., `replace_all` returns a `Borrowed`). while let Cow::Owned(step) = MACRO.replace_all(&code, |caps: &Captures| { - indent( - blocks.get(&caps[2]).expect("Block not present").clone(), - caps[1].len() - ) + let block = if d < depth { + blocks.get(&caps[2]).expect("Block not present").clone() + } else { + eprintln!("Reached maximum depth, output might be truncated. Increase `--depth` accordingly."); + Cow::Owned(String::from("")) + }; + indent(block, caps[1].len()) }) { code = Cow::from(step); + d += 1; } write_to_file(base, k, &code).expect("Unable to write to file"); }) @@ -153,7 +162,7 @@ fn main() -> Result<()> { } } ); - build(&config.output, &blocks); + build(&config.output, &blocks, config.depth); pandoc })); pandoc.execute().unwrap(); -- cgit v1.2.3