generated from emilk/eframe_template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
dfd4dd0
commit a70728c
Showing
2 changed files
with
123 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,4 +12,5 @@ pub use error::Error; | |
pub mod pest; | ||
|
||
mod plugins; | ||
mod template; | ||
mod utils; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
use std::collections::HashMap; | ||
Check failure on line 1 in src/template.rs
|
||
|
||
use rhai::Dynamic; | ||
|
||
/// Holds the template parts (Static and Dynamic). | ||
/// | ||
/// Renders the template with the provided values. | ||
#[derive(Debug, Clone, PartialEq)] | ||
pub struct Template { | ||
pub(crate) parts: Vec<TemplatePart>, | ||
} | ||
|
||
/// Represents a part of the template. | ||
/// | ||
/// Static parts are just strings. | ||
/// Dynamic parts are placeholders that will be replaced with values. | ||
#[derive(Debug, Clone, PartialEq)] | ||
pub enum TemplatePart { | ||
Static(String), | ||
Check failure on line 19 in src/template.rs
|
||
Dynamic(String), | ||
} | ||
|
||
impl Template { | ||
/// Create a new Template from the provided string. | ||
pub(crate) fn new(template: &str) -> Self { | ||
Check failure on line 25 in src/template.rs
|
||
let mut parts = Vec::new(); | ||
let mut current = String::new(); | ||
|
||
let mut chars = template.chars().peekable(); | ||
while let Some(ch) = chars.next() { | ||
if ch == '{' && chars.peek() == Some(&'{') { | ||
chars.next(); // consume second '{' | ||
if !current.is_empty() { | ||
parts.push(TemplatePart::Static(current)); | ||
current = String::new(); | ||
} | ||
while let Some(ch) = chars.next() { | ||
if ch == '}' && chars.peek() == Some(&'}') { | ||
chars.next(); // consume second '}' | ||
break; | ||
} | ||
current.push(ch); | ||
} | ||
parts.push(TemplatePart::Dynamic(current.trim().to_string())); | ||
current = String::new(); | ||
} else { | ||
current.push(ch); | ||
} | ||
} | ||
|
||
if !current.is_empty() { | ||
parts.push(TemplatePart::Static(current)); | ||
} | ||
|
||
Template { parts } | ||
} | ||
|
||
/// Render the template with the provided values. | ||
/// | ||
/// Pass it an object that implements Iterator so it can perform lookups on the values given | ||
/// the key. | ||
pub(crate) fn render<'a>( | ||
&self, | ||
mut values: impl Iterator<Item = (&'a str, bool, &'a Dynamic)>, | ||
) -> String { | ||
let mut result = String::new(); | ||
for part in &self.parts { | ||
match part { | ||
TemplatePart::Static(s) => result.push_str(s), | ||
TemplatePart::Dynamic(key) => { | ||
if let Some(value) = | ||
values.find_map( | ||
|(k, _, v)| { | ||
if k == key { | ||
Some(v.to_string()) | ||
} else { | ||
None | ||
} | ||
}, | ||
) | ||
{ | ||
result.push_str(&value); | ||
} else { | ||
result.push_str(&format!("{{{{{}}}}}", key)); | ||
} | ||
} | ||
} | ||
} | ||
result | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use std::str::FromStr as _; | ||
|
||
use super::*; | ||
|
||
#[test] | ||
fn test_template() { | ||
let template = Template::new("This {{word_var}} is replaced with {{a_value}}"); | ||
let mut values = HashMap::new(); | ||
values.insert( | ||
"word_var".to_string(), | ||
Dynamic::from_str("template").unwrap(), | ||
); | ||
values.insert("a_value".to_string(), Dynamic::from_str("content").unwrap()); | ||
|
||
let result = template.render(values.iter().map(|(k, v)| (k.as_str(), false, v))); | ||
assert_eq!(result, "This template is replaced with content"); | ||
} | ||
|
||
// handle the case where a placeholder in the template doesn't have a corresponding value in the provided HashMap. | ||
#[test] | ||
fn test_missing_value() { | ||
let template = Template::new("This {{word_var}} is replaced with {{a_value}}"); | ||
let values: HashMap<_, Dynamic> = HashMap::<String, rhai::Dynamic>::new(); | ||
|
||
let result = template.render(values.iter().map(|(k, v)| (k.as_str(), false, v))); | ||
assert_eq!(result, "This {{word_var}} is replaced with {{a_value}}"); | ||
} | ||
} |