diff options
Diffstat (limited to 'utils/string_proc/src')
| -rw-r--r-- | utils/string_proc/src/format_path.rs | 78 | ||||
| -rw-r--r-- | utils/string_proc/src/format_processer.rs | 110 | ||||
| -rw-r--r-- | utils/string_proc/src/lib.rs | 46 | ||||
| -rw-r--r-- | utils/string_proc/src/macros.rs | 64 |
4 files changed, 219 insertions, 79 deletions
diff --git a/utils/string_proc/src/format_path.rs b/utils/string_proc/src/format_path.rs index 35689b8..8750db6 100644 --- a/utils/string_proc/src/format_path.rs +++ b/utils/string_proc/src/format_path.rs @@ -1,6 +1,41 @@ use std::path::{Path, PathBuf}; -/// Format path str +/// Normalize an input path string into a canonical, platform‑agnostic form. +/// +/// This function removes ANSI escape sequences, unifies separators to `/`, +/// collapses duplicate slashes, strips unfriendly characters (`*`, `?`, `"`, `<`, `>`, `|`), +/// resolves simple `..` components, and preserves a trailing slash when present. +/// +/// See examples below for the exact normalization behavior. +/// +/// # Examples +/// +/// ``` +/// # use string_proc::format_path::format_path_str; +/// use std::io::Error; +/// +/// # fn main() -> Result<(), Error> { +/// assert_eq!(format_path_str("C:\\Users\\\\test")?, "C:/Users/test"); +/// assert_eq!( +/// format_path_str("/path/with/*unfriendly?chars")?, +/// "/path/with/unfriendlychars" +/// ); +/// assert_eq!(format_path_str("\x1b[31m/path\x1b[0m")?, "/path"); +/// assert_eq!(format_path_str("/home/user/dir/")?, "/home/user/dir/"); +/// assert_eq!( +/// format_path_str("/home/user/file.txt")?, +/// "/home/user/file.txt" +/// ); +/// assert_eq!( +/// format_path_str("/home/my_user/DOCS/JVCS_TEST/Workspace/../Vault/")?, +/// "/home/my_user/DOCS/JVCS_TEST/Vault/" +/// ); +/// assert_eq!(format_path_str("./home/file.txt")?, "home/file.txt"); +/// assert_eq!(format_path_str("./home/path/")?, "home/path/"); +/// assert_eq!(format_path_str("./")?, ""); +/// # Ok(()) +/// # } +/// ``` pub fn format_path_str(path: impl Into<String>) -> Result<String, std::io::Error> { let path_str = path.into(); let ends_with_slash = path_str.ends_with('/'); @@ -73,39 +108,16 @@ fn normalize_path(path: &Path) -> PathBuf { } } +/// Format a [`PathBuf`] into its canonical string form and convert it back. +/// +/// This is a convenience wrapper around [`format_path_str`], preserving +/// the semantics of [`PathBuf`] while applying the same normalization rules: +/// - normalize separators to `/` +/// - remove duplicated separators +/// - strip ANSI escape sequences +/// - remove unfriendly characters (`*`, `?`, etc.) +/// - resolve simple `..` segments pub fn format_path(path: impl Into<PathBuf>) -> Result<PathBuf, std::io::Error> { let path_str = format_path_str(path.into().display().to_string())?; Ok(PathBuf::from(path_str)) } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_format_path() -> Result<(), std::io::Error> { - assert_eq!(format_path_str("C:\\Users\\\\test")?, "C:/Users/test"); - - assert_eq!( - format_path_str("/path/with/*unfriendly?chars")?, - "/path/with/unfriendlychars" - ); - - assert_eq!(format_path_str("\x1b[31m/path\x1b[0m")?, "/path"); - assert_eq!(format_path_str("/home/user/dir/")?, "/home/user/dir/"); - assert_eq!( - format_path_str("/home/user/file.txt")?, - "/home/user/file.txt" - ); - assert_eq!( - format_path_str("/home/my_user/DOCS/JVCS_TEST/Workspace/../Vault/")?, - "/home/my_user/DOCS/JVCS_TEST/Vault/" - ); - - assert_eq!(format_path_str("./home/file.txt")?, "home/file.txt"); - assert_eq!(format_path_str("./home/path/")?, "home/path/"); - assert_eq!(format_path_str("./")?, ""); - - Ok(()) - } -} diff --git a/utils/string_proc/src/format_processer.rs b/utils/string_proc/src/format_processer.rs index 8d0a770..bac84c0 100644 --- a/utils/string_proc/src/format_processer.rs +++ b/utils/string_proc/src/format_processer.rs @@ -61,6 +61,14 @@ impl FormatProcesser { } /// Convert to camelCase format (brewCoffee) + /// + /// # Examples + /// + /// ``` + /// # use string_proc::format_processer::FormatProcesser; + /// let processor = FormatProcesser::from("brew_coffee"); + /// assert_eq!(processor.to_camel_case(), "brewCoffee"); + /// ``` pub fn to_camel_case(&self) -> String { let mut result = String::new(); for (i, word) in self.content.iter().enumerate() { @@ -78,6 +86,14 @@ impl FormatProcesser { } /// Convert to PascalCase format (BrewCoffee) + /// + /// # Examples + /// + /// ``` + /// # use string_proc::format_processer::FormatProcesser; + /// let processor = FormatProcesser::from("brew_coffee"); + /// assert_eq!(processor.to_pascal_case(), "BrewCoffee"); + /// ``` pub fn to_pascal_case(&self) -> String { let mut result = String::new(); for word in &self.content { @@ -91,21 +107,53 @@ impl FormatProcesser { } /// Convert to kebab-case format (brew-coffee) + /// + /// # Examples + /// + /// ``` + /// # use string_proc::format_processer::FormatProcesser; + /// let processor = FormatProcesser::from("brew_coffee"); + /// assert_eq!(processor.to_kebab_case(), "brew-coffee"); + /// ``` pub fn to_kebab_case(&self) -> String { self.content.join("-").to_lowercase() } /// Convert to snake_case format (brew_coffee) + /// + /// # Examples + /// + /// ``` + /// # use string_proc::format_processer::FormatProcesser; + /// let processor = FormatProcesser::from("brewCoffee"); + /// assert_eq!(processor.to_snake_case(), "brew_coffee"); + /// ``` pub fn to_snake_case(&self) -> String { self.content.join("_").to_lowercase() } /// Convert to dot.case format (brew.coffee) + /// + /// # Examples + /// + /// ``` + /// # use string_proc::format_processer::FormatProcesser; + /// let processor = FormatProcesser::from("brew_coffee"); + /// assert_eq!(processor.to_dot_case(), "brew.coffee"); + /// ``` pub fn to_dot_case(&self) -> String { self.content.join(".").to_lowercase() } /// Convert to Title Case format (Brew Coffee) + /// + /// # Examples + /// + /// ``` + /// # use string_proc::format_processer::FormatProcesser; + /// let processor = FormatProcesser::from("brew_coffee"); + /// assert_eq!(processor.to_title_case(), "Brew Coffee"); + /// ``` pub fn to_title_case(&self) -> String { let mut result = String::new(); for word in &self.content { @@ -121,12 +169,74 @@ impl FormatProcesser { } /// Convert to lower case format (brew coffee) + /// + /// # Examples + /// + /// ``` + /// # use string_proc::format_processer::FormatProcesser; + /// let processor = FormatProcesser::from("BREW COFFEE"); + /// assert_eq!(processor.to_lower_case(), "brew coffee"); + /// ``` pub fn to_lower_case(&self) -> String { self.content.join(" ").to_lowercase() } /// Convert to UPPER CASE format (BREW COFFEE) + /// + /// # Examples + /// + /// ``` + /// # use string_proc::format_processer::FormatProcesser; + /// let processor = FormatProcesser::from("brew coffee"); + /// assert_eq!(processor.to_upper_case(), "BREW COFFEE"); + /// ``` pub fn to_upper_case(&self) -> String { self.content.join(" ").to_uppercase() } } + +#[cfg(test)] +mod tests { + use crate::format_processer::FormatProcesser; + + #[test] + fn test_processer() { + let test_cases = vec![ + ("brew_coffee", "brewCoffee"), + ("brew, coffee", "brewCoffee"), + ("brew-coffee", "brewCoffee"), + ("Brew.Coffee", "brewCoffee"), + ("bRewCofFee", "bRewCofFee"), + ("brewCoffee", "brewCoffee"), + ("b&rewCoffee", "brewCoffee"), + ("BrewCoffee", "brewCoffee"), + ("brew.coffee", "brewCoffee"), + ("Brew_Coffee", "brewCoffee"), + ("BREW COFFEE", "brewCoffee"), + ]; + + for (input, expected) in test_cases { + let processor = FormatProcesser::from(input); + assert_eq!( + processor.to_camel_case(), + expected, + "Failed for input: '{}'", + input + ); + } + } + + #[test] + fn test_conversions() { + let processor = FormatProcesser::from("brewCoffee"); + + assert_eq!(processor.to_upper_case(), "BREW COFFEE"); + assert_eq!(processor.to_lower_case(), "brew coffee"); + assert_eq!(processor.to_title_case(), "Brew Coffee"); + assert_eq!(processor.to_dot_case(), "brew.coffee"); + assert_eq!(processor.to_snake_case(), "brew_coffee"); + assert_eq!(processor.to_kebab_case(), "brew-coffee"); + assert_eq!(processor.to_pascal_case(), "BrewCoffee"); + assert_eq!(processor.to_camel_case(), "brewCoffee"); + } +} diff --git a/utils/string_proc/src/lib.rs b/utils/string_proc/src/lib.rs index 76588c1..a5b2040 100644 --- a/utils/string_proc/src/lib.rs +++ b/utils/string_proc/src/lib.rs @@ -2,49 +2,3 @@ pub mod format_path; pub mod format_processer; pub mod macros; pub mod simple_processer; - -#[cfg(test)] -mod tests { - use crate::format_processer::FormatProcesser; - - #[test] - fn test_processer() { - let test_cases = vec![ - ("brew_coffee", "brewCoffee"), - ("brew, coffee", "brewCoffee"), - ("brew-coffee", "brewCoffee"), - ("Brew.Coffee", "brewCoffee"), - ("bRewCofFee", "bRewCofFee"), - ("brewCoffee", "brewCoffee"), - ("b&rewCoffee", "brewCoffee"), - ("BrewCoffee", "brewCoffee"), - ("brew.coffee", "brewCoffee"), - ("Brew_Coffee", "brewCoffee"), - ("BREW COFFEE", "brewCoffee"), - ]; - - for (input, expected) in test_cases { - let processor = FormatProcesser::from(input); - assert_eq!( - processor.to_camel_case(), - expected, - "Failed for input: '{}'", - input - ); - } - } - - #[test] - fn test_conversions() { - let processor = FormatProcesser::from("brewCoffee"); - - assert_eq!(processor.to_upper_case(), "BREW COFFEE"); - assert_eq!(processor.to_lower_case(), "brew coffee"); - assert_eq!(processor.to_title_case(), "Brew Coffee"); - assert_eq!(processor.to_dot_case(), "brew.coffee"); - assert_eq!(processor.to_snake_case(), "brew_coffee"); - assert_eq!(processor.to_kebab_case(), "brew-coffee"); - assert_eq!(processor.to_pascal_case(), "BrewCoffee"); - assert_eq!(processor.to_camel_case(), "brewCoffee"); - } -} diff --git a/utils/string_proc/src/macros.rs b/utils/string_proc/src/macros.rs index 135268e..414baf0 100644 --- a/utils/string_proc/src/macros.rs +++ b/utils/string_proc/src/macros.rs @@ -1,3 +1,11 @@ +/// Convert to camelCase format (brewCoffee) +/// +/// # Examples +/// +/// ``` +/// # use string_proc::camel_case; +/// assert_eq!(camel_case!("brew_coffee"), "brewCoffee"); +/// ``` #[macro_export] macro_rules! camel_case { ($input:expr) => {{ @@ -6,6 +14,14 @@ macro_rules! camel_case { }}; } +/// Convert to UPPER CASE format (BREW COFFEE) +/// +/// # Examples +/// +/// ``` +/// # use string_proc::upper_case; +/// assert_eq!(upper_case!("brew coffee"), "BREW COFFEE"); +/// ``` #[macro_export] macro_rules! upper_case { ($input:expr) => {{ @@ -14,6 +30,14 @@ macro_rules! upper_case { }}; } +/// Convert to lower case format (brew coffee) +/// +/// # Examples +/// +/// ``` +/// # use string_proc::lower_case; +/// assert_eq!(lower_case!("BREW COFFEE"), "brew coffee"); +/// ``` #[macro_export] macro_rules! lower_case { ($input:expr) => {{ @@ -22,6 +46,14 @@ macro_rules! lower_case { }}; } +/// Convert to Title Case format (Brew Coffee) +/// +/// # Examples +/// +/// ``` +/// # use string_proc::title_case; +/// assert_eq!(title_case!("brew_coffee"), "Brew Coffee"); +/// ``` #[macro_export] macro_rules! title_case { ($input:expr) => {{ @@ -30,6 +62,14 @@ macro_rules! title_case { }}; } +/// Convert to dot.case format (brew.coffee) +/// +/// # Examples +/// +/// ``` +/// # use string_proc::dot_case; +/// assert_eq!(dot_case!("brew_coffee"), "brew.coffee"); +/// ``` #[macro_export] macro_rules! dot_case { ($input:expr) => {{ @@ -38,6 +78,14 @@ macro_rules! dot_case { }}; } +/// Convert to snake_case format (brew_coffee) +/// +/// # Examples +/// +/// ``` +/// # use string_proc::snake_case; +/// assert_eq!(snake_case!("brewCoffee"), "brew_coffee"); +/// ``` #[macro_export] macro_rules! snake_case { ($input:expr) => {{ @@ -46,6 +94,14 @@ macro_rules! snake_case { }}; } +/// Convert to kebab-case format (brew-coffee) +/// +/// # Examples +/// +/// ``` +/// # use string_proc::kebab_case; +/// assert_eq!(kebab_case!("brew_coffee"), "brew-coffee"); +/// ``` #[macro_export] macro_rules! kebab_case { ($input:expr) => {{ @@ -54,6 +110,14 @@ macro_rules! kebab_case { }}; } +/// Convert to PascalCase format (BrewCoffee) +/// +/// # Examples +/// +/// ``` +/// # use string_proc::pascal_case; +/// assert_eq!(pascal_case!("brew_coffee"), "BrewCoffee"); +/// ``` #[macro_export] macro_rules! pascal_case { ($input:expr) => {{ |
