herolib_rust/src/text/fix.rs
2025-04-05 09:36:54 +02:00

100 lines
3.5 KiB
Rust

pub fn name_fix(text: &str) -> String {
let mut result = String::with_capacity(text.len());
let mut last_was_underscore = false;
for c in text.chars() {
// Keep only ASCII characters
if c.is_ascii() {
// Replace specific characters with underscore
if c.is_whitespace() || c == ',' || c == '-' || c == '"' || c == '\'' ||
c == '#' || c == '!' || c == '(' || c == ')' || c == '[' || c == ']' ||
c == '=' || c == '+' || c == '<' || c == '>' || c == '@' || c == '$' ||
c == '%' || c == '^' || c == '&' || c == '*' {
// Only add underscore if the last character wasn't an underscore
if !last_was_underscore {
result.push('_');
last_was_underscore = true;
}
} else {
// Add the character as is (will be converted to lowercase later)
result.push(c);
last_was_underscore = false;
}
}
// Non-ASCII characters are simply skipped
}
// Convert to lowercase
return result.to_lowercase();
}
pub fn path_fix(text: &str) -> String {
// If path ends with '/', return as is
if text.ends_with('/') {
return text.to_string();
}
// Find the last '/' to extract the filename part
match text.rfind('/') {
Some(pos) => {
// Extract the path and filename parts
let path = &text[..=pos];
let filename = &text[pos+1..];
// Apply name_fix to the filename part only
return format!("{}{}", path, name_fix(filename));
},
None => {
// No '/' found, so the entire text is a filename
return name_fix(text);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_name_fix() {
// Test ASCII conversion and special character replacement
assert_eq!(name_fix("Hello World"), "hello_world");
assert_eq!(name_fix("File-Name.txt"), "file_name.txt");
assert_eq!(name_fix("Test!@#$%^&*()"), "test_");
assert_eq!(name_fix("Space, Tab\t, Comma,"), "space_tab_comma_");
assert_eq!(name_fix("Quotes\"'"), "quotes_");
assert_eq!(name_fix("Brackets[]<>"), "brackets_");
assert_eq!(name_fix("Operators=+-"), "operators_");
// Test non-ASCII characters removal
assert_eq!(name_fix("Café"), "caf");
assert_eq!(name_fix("Résumé"), "rsum");
assert_eq!(name_fix("Über"), "ber");
// Test lowercase conversion
assert_eq!(name_fix("UPPERCASE"), "uppercase");
assert_eq!(name_fix("MixedCase"), "mixedcase");
}
#[test]
fn test_path_fix() {
// Test path ending with /
assert_eq!(path_fix("/path/to/directory/"), "/path/to/directory/");
// Test single filename
assert_eq!(path_fix("filename.txt"), "filename.txt");
assert_eq!(path_fix("UPPER-file.md"), "upper_file.md");
// Test path with filename
assert_eq!(path_fix("/path/to/File Name.txt"), "/path/to/file_name.txt");
assert_eq!(path_fix("./relative/path/to/DOCUMENT-123.pdf"), "./relative/path/to/document_123.pdf");
assert_eq!(path_fix("/absolute/path/to/Résumé.doc"), "/absolute/path/to/rsum.doc");
// Test path with special characters in filename
assert_eq!(path_fix("/path/with/[special]<chars>.txt"), "/path/with/_special_chars_.txt");
}
}