Add len and split methods to the default methods

This commit is contained in:
Olivier 'reivilibre' 2024-05-02 21:20:56 +01:00
parent 00e67d34d9
commit f29573d9ad
3 changed files with 65 additions and 3 deletions

View File

@ -9,7 +9,12 @@ use super::TemplateAccessibleMethod;
const DEFAULT_TEMPLATE_ACCESSIBLE_METHODS: &'static [(
&'static str,
fn(Value, Vec<Value>) -> Result<Value, String>,
)] = &[("leftpad", leftpad), ("urlencode", urlencode)];
)] = &[
("leftpad", leftpad),
("urlencode", urlencode),
("len", len),
("split", split),
];
/// Return a map of the default suggested template-accessible methods.
pub fn default_template_accessible_methods() -> BTreeMap<String, TemplateAccessibleMethod> {
@ -24,6 +29,9 @@ pub fn default_template_accessible_methods() -> BTreeMap<String, TemplateAccessi
.collect()
}
/// Left-pads a string to a given length using a given padding character.
///
/// `<Str>.leftpad(<Int>, <Str>) -> Str`
pub fn leftpad(obj: Value, args: Vec<Value>) -> Result<Value, String> {
let Value::Str(string_to_pad) = obj else {
return Err(format!("{obj:?} is not a string: can't leftpad!"));
@ -60,6 +68,9 @@ pub fn leftpad(obj: Value, args: Vec<Value>) -> Result<Value, String> {
Ok(Value::Str(Arc::new(result)))
}
/// URL-encodes sensitive characters in a string.
///
/// `<Str>.urlencode() -> Str`
pub fn urlencode(obj: Value, args: Vec<Value>) -> Result<Value, String> {
let Value::Str(string_to_encode) = obj else {
return Err(format!("{obj:?} is not a string: can't urlencode!"));
@ -72,3 +83,47 @@ pub fn urlencode(obj: Value, args: Vec<Value>) -> Result<Value, String> {
percent_encoding::utf8_percent_encode(&string_to_encode, NON_ALPHANUMERIC).to_string(),
)))
}
/// Returns the length of a given string or list.
///
/// - `<Str>.len() -> Int`
/// - `<List>.len() -> Int`
pub fn len(obj: Value, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 0 {
return Err(format!("len takes 0 args, not {}", args.len()));
}
match obj {
Value::Str(string) => Ok(Value::Int(string.len() as i64)),
Value::List(list) => Ok(Value::Int(list.len() as i64)),
_ => {
return Err(format!(
"{obj:?} is not a string or list: can't get length!"
));
}
}
}
/// Splits a string by given delimiters.
///
/// `<Str>.split(<Str>) -> List of Str`
pub fn split(obj: Value, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("split takes 1 arg, not {}", args.len()));
}
let Value::Str(string_to_split) = obj else {
return Err(format!("{obj:?} is not a string: can't split!"));
};
let Value::Str(delimiter) = &args[0] else {
return Err(format!("first arg is not a string: can't split!"));
};
let result = string_to_split
.split(delimiter.as_str())
.map(|segment| Value::Str(Arc::new(segment.to_owned())))
.collect();
Ok(Value::List(result))
}

View File

@ -75,6 +75,13 @@ br
"padded to 15: ${$sts.carrot.leftpad(15, 'M')}"
br
"urlencoded: ${$sts.carrot.urlencode()}"
br
"length: ${$sts.carrot.len()}"
br
"split on A: "
for $part in $sts.carrot.split("A")
"($part)"
br
"#
))
}

View File

@ -1,5 +1,5 @@
---
source: hornbeam_interpreter/tests/snapshots.rs
expression: "simple_render(r#\"\n\"unpadded: ${$sts.carrot}\"\nbr\n\"padded to 15: ${$sts.carrot.leftpad(15, 'M')}\"\nbr\n\"urlencoded: ${$sts.carrot.urlencode()}\"\n \"#)"
expression: "simple_render(r#\"\n\"unpadded: ${$sts.carrot}\"\nbr\n\"padded to 15: ${$sts.carrot.leftpad(15, 'M')}\"\nbr\n\"urlencoded: ${$sts.carrot.urlencode()}\"\nbr\n\"length: ${$sts.carrot.len()}\"\nbr\n\"split on A: \"\nfor $part in $sts.carrot.split(\"A\")\n \"($part)\"\n br\n \"#)"
---
unpadded: mmm CARROT!<br>padded to 15: MMMMmmm CARROT!<br>urlencoded: mmm%20CARROT%21
unpadded: mmm CARROT!<br>padded to 15: MMMMmmm CARROT!<br>urlencoded: mmm%20CARROT%21<br>length: 11<br>split on A: (mmm C)<br>(RROT!)<br>