proplate_core/template/
interpolation.rs1use regex::Regex;
2
3use crate::gen::bootstrap::Context;
4
5const INTERPOLATION_PATTERN: &str = r"(\\*)\$([a-zA-Z_][a-zA-Z0-9_]*)\b";
6
7fn create_regex() -> Regex {
8 Regex::new(INTERPOLATION_PATTERN).unwrap()
9}
10
11pub fn interpolate(source: &str, ctx: &Context) -> String {
22 let re = create_regex();
23
24 let mut result = String::new();
25 let mut last_end = 0;
26
27 for caps in re.captures_iter(source) {
28 let escape = caps.get(1).unwrap().as_str();
29 let name = caps.get(2).unwrap().as_str();
30
31 let escape_len = escape.len();
32 let value = ctx.get(name).map(|v| v.as_str()).unwrap_or("");
33
34 let unescaped_match = &source[last_end..caps.get(0).unwrap().start()];
35 result.push_str(unescaped_match);
36
37 if escape_len % 2 != 0 {
38 result.push_str(&format!(
39 "{}${}",
40 escape[..escape_len - 1].to_string(),
41 name
42 ));
43 } else {
44 result.push_str(&format!("{}{}", escape, value));
45 }
46
47 last_end = caps.get(0).unwrap().end();
48 }
49
50 result.push_str(&source[last_end..]);
51 result
52}
53
54pub trait Interpolate {
55 fn interpolate(&self, ctx: &Context) -> Self;
56}
57
58impl Interpolate for String {
60 fn interpolate(&self, ctx: &Context) -> Self {
61 interpolate(self, ctx)
62 }
63}