Skip to main content

yog_codegen/
case.rs

1//! Names in each language's case, from one splitting into words.
2
3use crate::consts::{SNAKE_JOIN, WORD_SEPARATORS};
4
5/// The words of a name: split at separators (`_ - / . space`) and before
6/// each capital (`statBar`, `StatBar`, `stat_bar`, `stat-bar` → `stat`, `bar`
7/// as written: `stat`, `Bar`).
8pub fn words(name: &str) -> Vec<&str> {
9    let mut out = Vec::new();
10    for part in name.split(WORD_SEPARATORS).filter(|p| !p.is_empty()) {
11        let mut start = 0;
12        for (i, c) in part.char_indices().skip(1) {
13            if c.is_uppercase() {
14                out.push(&part[start..i]);
15                start = i;
16            }
17        }
18        out.push(&part[start..]);
19    }
20    out
21}
22
23/// A word with its first letter a capital.
24fn capitalized(word: &str) -> String {
25    let mut chars = word.chars();
26    chars
27        .next()
28        .map(|first| first.to_uppercase().collect::<String>() + chars.as_str())
29        .unwrap_or_default()
30}
31
32/// `stat_bar` / `stat-bar` / `statBar` → `StatBar`.
33pub fn pascal(name: &str) -> String {
34    words(name).into_iter().map(capitalized).collect()
35}
36
37/// `stat_bar` / `StatBar` → `statBar`.
38pub fn camel(name: &str) -> String {
39    let pascal = pascal(name);
40    let mut chars = pascal.chars();
41    chars
42        .next()
43        .map(|first| first.to_lowercase().collect::<String>() + chars.as_str())
44        .unwrap_or_default()
45}
46
47/// `StatBar` / `stat-bar` → `stat_bar`.
48pub fn snake(name: &str) -> String {
49    joined_lower(name).join(SNAKE_JOIN)
50}
51
52/// `statBar` / `stat_bar` → `STAT_BAR`.
53pub fn screaming(name: &str) -> String {
54    snake(name).to_uppercase()
55}
56
57fn joined_lower(name: &str) -> Vec<String> {
58    words(name).into_iter().map(str::to_lowercase).collect()
59}
60
61#[cfg(test)]
62mod tests;