commit 3ca35ba0aebecd4d4e9bf40e958eb13c5d64c7b1
parent 0354ed712923d3d18e9cc317ca36d8a5bf3d6ea5
Author: triesap <triesap@radroots.dev>
Date: Mon, 19 Jan 2026 06:49:34 +0000
app-utils: add str_cap_words helper
- add str_cap_words helper for title casing
- skip empty segments in split input
- export str_cap_words from utils text module
- add unit tests for word capitalization
Diffstat:
2 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs
@@ -6,5 +6,5 @@ pub mod text;
pub mod types;
pub use errors::{err_msg, handle_err, throw_err, ERR_PREFIX_APP, ERR_PREFIX_UTILS};
-pub use text::{str_cap, text_dec, text_enc, ROOT_SYMBOL};
+pub use text::{str_cap, str_cap_words, text_dec, text_enc, ROOT_SYMBOL};
pub use types::{resolve_err, resolve_ok, ResolveError, ResultPass};
diff --git a/crates/utils/src/text/mod.rs b/crates/utils/src/text/mod.rs
@@ -23,9 +23,26 @@ pub fn str_cap(value: Option<&str>) -> String {
output
}
+pub fn str_cap_words(value: Option<&str>) -> String {
+ let Some(value) = value else {
+ return String::new();
+ };
+ let mut words = Vec::new();
+ for word in value.split(' ') {
+ if word.is_empty() {
+ continue;
+ }
+ let capped = str_cap(Some(word));
+ if !capped.is_empty() {
+ words.push(capped);
+ }
+ }
+ words.join(" ")
+}
+
#[cfg(test)]
mod tests {
- use super::{str_cap, text_dec, text_enc, ROOT_SYMBOL};
+ use super::{str_cap, str_cap_words, text_dec, text_enc, ROOT_SYMBOL};
#[test]
fn root_symbol_matches_spec() {
@@ -49,4 +66,19 @@ mod tests {
fn str_cap_uppercases_first_letter() {
assert_eq!(str_cap(Some("radroots")), "Radroots");
}
+
+ #[test]
+ fn str_cap_words_handles_none() {
+ assert_eq!(str_cap_words(None), "");
+ }
+
+ #[test]
+ fn str_cap_words_caps_each_word() {
+ assert_eq!(str_cap_words(Some("rad roots")), "Rad Roots");
+ }
+
+ #[test]
+ fn str_cap_words_skips_empty_words() {
+ assert_eq!(str_cap_words(Some("rad roots")), "Rad Roots");
+ }
}