Skip to content

Commit 2093a0b

Browse files
committed
added truncate function
1 parent 6dd69e6 commit 2093a0b

4 files changed

Lines changed: 57 additions & 0 deletions

File tree

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
* 0.2.9
2+
* New function: truncate
23
* New border style: "rounded"
34
* Hex and Color can now be serialized / deserialized if the `serde` feature
45
is enabled.

anathema-value-resolver/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ repository = "https://github.com/togglebyte/anathema"
1212
anathema-state = { workspace = true }
1313
anathema-templates = { workspace = true }
1414
anathema-store = { workspace = true }
15+
unicode-width = { workspace = true }
1516

1617
[lints]
1718
workspace = true

anathema-value-resolver/src/functions/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ impl FunctionTable {
5757
let mut inner = HashMap::new();
5858
inner.insert("to_upper".into(), Function::from(string::to_upper));
5959
inner.insert("to_lower".into(), Function::from(string::to_lower));
60+
inner.insert("truncate".into(), Function::from(string::truncate));
6061
inner.insert("to_str".into(), Function::from(string::to_str));
6162
inner.insert("to_int".into(), Function::from(number::to_int));
6263
inner.insert("to_float".into(), Function::from(number::to_float));

anathema-value-resolver/src/functions/string.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
2+
13
use crate::ValueKind;
24

35
pub(super) fn to_upper<'bp>(args: &[ValueKind<'bp>]) -> ValueKind<'bp> {
@@ -40,6 +42,37 @@ pub(super) fn to_str<'bp>(args: &[ValueKind<'bp>]) -> ValueKind<'bp> {
4042
ValueKind::Str(buffer.into())
4143
}
4244

45+
pub(super) fn truncate<'bp>(args: &[ValueKind<'bp>]) -> ValueKind<'bp> {
46+
if args.len() != 2 {
47+
return ValueKind::Null;
48+
}
49+
50+
let Some(mut remainder) = args[1].as_int() else { return ValueKind::Null };
51+
52+
let mut buffer = String::new();
53+
args[0].strings(|s| {
54+
let width = s.width() as i64;
55+
56+
if width < remainder {
57+
remainder = remainder.saturating_sub(width);
58+
buffer.push_str(s);
59+
} else {
60+
let mut chars = s.chars();
61+
while remainder > 0 {
62+
let Some(c) = chars.next() else { break };
63+
let width = c.width().unwrap_or(0) as i64;
64+
if width > remainder {
65+
break;
66+
};
67+
buffer.push(c);
68+
remainder = remainder.saturating_sub(width);
69+
}
70+
}
71+
true
72+
});
73+
ValueKind::Str(buffer.into())
74+
}
75+
4376
#[cfg(test)]
4477
mod test {
4578
use super::*;
@@ -86,4 +119,25 @@ mod test {
86119
let val = to_str(&[val]);
87120
assert_eq!(val, value("123"));
88121
}
122+
123+
#[test]
124+
fn truncate_long_string() {
125+
let val = value("this is a longer string");
126+
let val = truncate(&[val, value(4)]);
127+
assert_eq!(val, value("this"));
128+
}
129+
130+
#[test]
131+
fn truncate_short_string() {
132+
let val = value("hi");
133+
let val = truncate(&[val, value(4)]);
134+
assert_eq!(val, value("hi"));
135+
}
136+
137+
#[test]
138+
fn truncate_wide_cells() {
139+
let val = value("🐇🐇");
140+
let val = truncate(&[val, value(3)]);
141+
assert_eq!(val, value("🐇"));
142+
}
89143
}

0 commit comments

Comments
 (0)