use crate::*;
#[derive(Default)]
pub struct OwningTemplateExpander<'s> {
ops: Vec<FillingOperation<'s>>,
default_value: Option<String>,
}
#[derive(Default)]
pub struct OwningSubTemplateExpander<'s> {
ops: Vec<SubFillingOperation<'s>>,
}
enum FillingOperation<'s> {
Set {
name: &'s str,
value: String,
},
SetMD {
name: &'s str,
value: String,
},
SetLines {
name: &'s str,
value: String,
},
SetLinesMD {
name: &'s str,
value: String,
},
Sub {
name: &'s str,
sub_expander: OwningSubTemplateExpander<'s>,
},
}
enum SubFillingOperation<'s> {
Set { name: &'s str, value: String },
SetMD { name: &'s str, value: String },
}
impl<'s> OwningTemplateExpander<'s> {
pub fn new() -> Self {
Self::default()
}
pub fn set_default<S: Into<String>>(
&mut self,
value: S,
) -> &mut Self {
self.default_value = Some(value.into());
self
}
pub fn set<S: std::fmt::Display>(
&mut self,
name: &'s str,
value: S,
) -> &mut Self {
self.ops.push(FillingOperation::Set {
name,
value: value.to_string(),
});
self
}
pub fn set_md<S: Into<String>>(
&mut self,
name: &'s str,
value: S,
) -> &mut Self {
self.ops.push(FillingOperation::SetMD {
name,
value: value.into(),
});
self
}
pub fn sub(
&mut self,
name: &'s str,
) -> &mut OwningSubTemplateExpander<'s> {
let idx = self.ops.len();
self.ops.push(FillingOperation::Sub {
name,
sub_expander: OwningSubTemplateExpander::new(),
});
match &mut self.ops[idx] {
FillingOperation::Sub {
name: _,
sub_expander,
} => sub_expander,
_ => unreachable!(),
}
}
pub fn set_lines<S: Into<String>>(
&mut self,
name: &'s str,
raw_lines: S,
) -> &mut Self {
self.ops.push(FillingOperation::SetLines {
name,
value: raw_lines.into(),
});
self
}
pub fn set_lines_md<S: Into<String>>(
&mut self,
name: &'s str,
md: S,
) -> &mut Self {
self.ops.push(FillingOperation::SetLinesMD {
name,
value: md.into(),
});
self
}
pub fn expand<'t>(
&'s self,
template: &'t TextTemplate<'s>,
) -> Text<'s> {
let mut expander = template.expander();
if let Some(s) = &self.default_value {
expander.set_all(s);
}
for op in &self.ops {
match op {
FillingOperation::Set { name, value } => {
expander.set(name, value);
}
FillingOperation::SetMD { name, value } => {
expander.set_md(name, value);
}
FillingOperation::SetLines { name, value } => {
expander.set_lines(name, value);
}
FillingOperation::SetLinesMD { name, value } => {
expander.set_lines_md(name, value);
}
FillingOperation::Sub { name, sub_expander } => {
let sub = expander.sub(name);
for op in &sub_expander.ops {
match op {
SubFillingOperation::Set { name, value } => {
sub.set(name, value);
}
SubFillingOperation::SetMD { name, value } => {
sub.set_md(name, value);
}
}
}
}
}
}
expander.expand()
}
}
impl<'s> OwningSubTemplateExpander<'s> {
pub fn new() -> Self {
Self { ops: Vec::new() }
}
pub fn set<S: std::fmt::Display>(
&mut self,
name: &'s str,
value: S,
) -> &mut Self {
self.ops.push(SubFillingOperation::Set {
name,
value: value.to_string(),
});
self
}
pub fn set_option<S: std::fmt::Display>(
&mut self,
name: &'s str,
value: Option<S>,
) -> &mut Self {
if let Some(value) = value {
self.ops.push(SubFillingOperation::Set {
name,
value: value.to_string(),
});
}
self
}
pub fn set_md<S: Into<String>>(
&mut self,
name: &'s str,
value: S,
) -> &mut Self {
self.ops.push(SubFillingOperation::SetMD {
name,
value: value.into(),
});
self
}
}