use crate::{fold, name, name_with_limit};
use alloc::string::String;
fn pat(c: char) -> bool {
c.is_ascii_punctuation() || c.is_whitespace()
}
pub fn kebab_case<T: AsRef<str>>(t: T) -> String {
name(t)
.split(pat)
.filter(|t| !t.is_empty())
.map(str::to_lowercase)
.fold(String::new(), fold_kebab_case)
}
pub fn kebab_case_with_limit<T: AsRef<str>>(t: T, limit: usize) -> String {
name_with_limit(t, limit)
.split(pat)
.filter(|t| !t.is_empty())
.map(str::to_lowercase)
.fold(String::new(), fold_kebab_case)
}
pub fn screaming_kebab_case<T: AsRef<str>>(t: T) -> String {
name(t)
.split(pat)
.filter(|t| !t.is_empty())
.map(str::to_uppercase)
.fold(String::new(), fold_kebab_case)
}
pub fn screaming_kebab_case_with_limit<T: AsRef<str>>(t: T, limit: usize) -> String {
name_with_limit(t, limit)
.split(pat)
.filter(|t| !t.is_empty())
.map(str::to_uppercase)
.fold(String::new(), fold_kebab_case)
}
pub fn snake_case<T: AsRef<str>>(t: T) -> String {
name(t)
.split(pat)
.filter(|t| !t.is_empty())
.map(str::to_lowercase)
.fold(String::new(), fold_snake_case)
}
pub fn snake_case_with_limit<T: AsRef<str>>(t: T, limit: usize) -> String {
name_with_limit(t, limit)
.split(pat)
.filter(|t| !t.is_empty())
.map(str::to_lowercase)
.fold(String::new(), fold_snake_case)
}
pub fn screaming_snake_case<T: AsRef<str>>(t: T) -> String {
name(t)
.split(pat)
.filter(|t| !t.is_empty())
.map(str::to_uppercase)
.fold(String::new(), fold_snake_case)
}
pub fn screaming_snake_case_with_limit<T: AsRef<str>>(t: T, limit: usize) -> String {
name_with_limit(t, limit)
.split(pat)
.filter(|t| !t.is_empty())
.map(str::to_uppercase)
.fold(String::new(), fold_snake_case)
}
pub fn camel_case<T: AsRef<str>>(t: T) -> String {
name(t)
.split(pat)
.filter(|t| !t.is_empty())
.enumerate()
.map(|(i, word)| to_camel_case(word, i != 0))
.fold(String::new(), fold_camel_case)
}
pub fn camel_case_with_limit<T: AsRef<str>>(t: T, limit: usize) -> String {
name_with_limit(t, limit)
.split(pat)
.filter(|t| !t.is_empty())
.enumerate()
.map(|(i, word)| to_camel_case(word, i != 0))
.fold(String::new(), fold_camel_case)
}
pub fn pascal_case<T: AsRef<str>>(t: T) -> String {
name(t)
.split(pat)
.filter(|t| !t.is_empty())
.map(|word| to_camel_case(word, true))
.fold(String::new(), fold_camel_case)
}
pub fn pascal_case_with_limit<T: AsRef<str>>(t: T, limit: usize) -> String {
name_with_limit(t, limit)
.split(pat)
.filter(|t| !t.is_empty())
.map(|word| to_camel_case(word, true))
.fold(String::new(), fold_camel_case)
}
fn to_camel_case(word: &str, mut upper: bool) -> String {
let mut cc = String::new();
let mut prev_is_lowercase = false;
for c in word.chars() {
if upper {
cc.extend(c.to_uppercase());
} else {
cc.extend(c.to_lowercase());
}
upper = prev_is_lowercase && c.is_uppercase();
prev_is_lowercase = c.is_lowercase();
}
cc
}
fn fold_kebab_case(acc: String, w: String) -> String {
fold(acc, &w, '-')
}
fn fold_snake_case(acc: String, w: String) -> String {
fold(acc, &w, '_')
}
fn fold_camel_case(mut acc: String, w: String) -> String {
let start_is_num = matches!(w.chars().next(), Some(c) if c.is_numeric());
let end_is_num = matches!(acc.chars().last(), Some(c) if c.is_numeric());
if start_is_num && end_is_num {
acc.push('_');
}
acc.push_str(&w);
acc
}