case_switcher/
lib.rs

1use regex::Regex;
2
3
4/// Return a version of the string in `camelCase` format.
5///
6/// # Arguments
7///
8/// * `string` - The string to get a camelCase version of.
9///
10/// # Examples
11///
12/// ```
13/// let result = case_switcher::to_camel("sample_string");
14/// assert_eq!(result, "sampleString");
15/// ```
16pub fn to_camel(string: &str) -> String {
17    let words = get_words(string);
18    let mut first_word = String::new();
19    if let Some(word) = words.first() {
20        first_word = if word.chars().next().unwrap().is_uppercase() {
21            word.to_owned()
22        } else {
23            word.to_lowercase()
24        };
25    }
26    let remaining_words = words.iter().skip(1);
27    let mut result = String::new();
28    result.push_str(&first_word);
29    result.push_str(&remaining_words.map(|s| capitalize(s)).collect::<String>());
30    result
31}
32
33
34/// Return a version of the string in `dot.case` format.
35///
36/// # Arguments
37///
38/// * `string` - The string to get a dot.case version of.
39///
40/// # Examples
41///
42/// ```
43/// let result = case_switcher::to_dot("sample_string");
44/// assert_eq!(result, "sample.string");
45/// ```
46pub fn to_dot(string: &str) -> String {
47    lower_join(string, ".")
48}
49
50
51/// Return a version of the string in `kebab-case` format.
52///
53/// # Arguments
54///
55/// * `string` - The string to get a kebab-case version of.
56///
57/// # Examples
58///
59/// ```
60/// let result = case_switcher::to_kebab("sample_string");
61/// assert_eq!(result, "sample-string");
62/// ```
63pub fn to_kebab(string: &str) -> String {
64    lower_join(string, "-")
65}
66
67
68/// Return a version of the string in `PascalCase` format.
69///
70/// # Arguments
71///
72/// * `string` - The string to get a PascalCase version of.
73///
74/// # Examples
75///
76/// ```
77/// let result = case_switcher::to_pascal("sample_string");
78/// assert_eq!(result, "SampleString");
79/// ```
80pub fn to_pascal(string: &str) -> String {
81    get_words(string)
82        .iter()
83        .map(|s| capitalize(s))
84        .collect::<String>()
85}
86
87
88/// Return a version of the string in `path/case` format.
89///
90/// # Arguments
91///
92/// * `string` - The string to get a path/case version of.
93///
94/// # Examples
95///
96/// ```
97/// let result = case_switcher::to_path("sample_string");
98/// assert_eq!(result, "sample/string");
99/// ```
100pub fn to_path(string: &str) -> String {
101    lower_join(string, "/")
102}
103
104
105/// Return a version of the string in `snake_case` format.
106///
107/// # Arguments
108///
109/// * `string` - The string to get a snake_case version of.
110///
111/// # Examples
112///
113/// ```
114/// let result = case_switcher::to_snake("sampleString");
115/// assert_eq!(result, "sample_string");
116/// ```
117pub fn to_snake(string: &str) -> String {
118    lower_join(string, "_")
119}
120
121
122/// Return a version of the string in `Title Case` format.
123///
124/// # Arguments
125///
126/// * `string` - The string to get a Title Case version of.
127///
128/// # Examples
129///
130/// ```
131/// let result = case_switcher::to_title("sample_string");
132/// assert_eq!(result, "Sample String");
133/// ```
134pub fn to_title(string: &str) -> String {
135    get_words(string)
136        .iter()
137        .map(|s| capitalize(s))
138        .collect::<Vec<String>>()
139        .join(" ")
140}
141
142
143/// Get all of the words in a string.
144///
145/// # Arguments
146///
147/// * `string` - The string to get words from.
148///
149/// # Examples
150///
151/// ```
152/// let result = case_switcher::get_words("sample_string");
153/// assert_eq!(result, vec!["sample", "string"]);
154/// ```
155pub fn get_words(string: &str) -> Vec<String> {
156    // Split on word boundaries and underscores
157    // let re = Regex::new(r"(.*?)[!@#$%^&*()\-_=+{}\[\]\\;:',.<>/?\n\t ]").unwrap();
158    let re = Regex::new(r"(.*?)[\W_]").unwrap();
159    let words = re.replace_all(string, "$1 $3");
160
161    // Split on lower then upper: "oneTwo" -> ["one", "Two"]
162    let re = Regex::new(r"([a-z])([A-Z])").unwrap();
163    let words = re.replace_all(&words, "$1 $2");
164
165    // Split on upper then upper + lower: "JSONWord" -> ["JSON", "Word"]
166    let re = Regex::new(r"([A-Z])([A-Z])([a-z])").unwrap();
167    let words = re.replace_all(&words, "$1 $2$3");
168
169    // Split on number + letter: "TO1Cat23dog" -> ["TO1", "Cat23", "dog"]
170    let re = Regex::new(r"(\d)([A-Za-z])").unwrap();
171    let words = re.replace_all(&words, "$1 $2");
172    words.split_whitespace().map(|s| s.to_string()).collect::<Vec<String>>()
173}
174
175
176/// Return a version of the string with the first letter capitalized.
177///
178/// # Arguments
179///
180/// * `string` - The string to get a capitalized version of.
181///
182/// # Examples
183///
184/// ```
185/// let result = case_switcher::capitalize("sample_string");
186/// assert_eq!(result, "Sample_string");
187/// ```
188pub fn capitalize(string: &str) -> String {
189    let mut chars = string.chars();
190    if let Some(first_char) = chars.next() {
191        let capitalized = first_char.to_uppercase().collect::<String>();
192        capitalized + chars.as_str()
193    } else {
194        String::new()
195    }
196}
197
198fn lower_join(string: &str, join_string: &str) -> String {
199    get_words(string)
200        .into_iter()
201        .map(|w| w.to_lowercase())
202        .collect::<Vec<String>>()
203        .join(join_string)
204}