bulloak_syntax/utils.rs
1//! Various-string manipulation utilities.
2
3use unicode_xid::UnicodeXID;
4
5/// Capitalizes the first letter of a given string.
6///
7/// This function takes a string slice and returns a new `String` with the first
8/// letter capitalized. If the string is empty, it returns an empty string.
9///
10/// # Arguments
11///
12/// * `s` - A string slice that holds the input string
13///
14/// # Returns
15///
16/// A `String` with the first letter capitalized
17///
18/// # Examples
19///
20/// ```
21/// # use bulloak_syntax::utils::upper_first_letter;
22/// let result = upper_first_letter("hello");
23/// assert_eq!(result, "Hello");
24/// ```
25pub fn upper_first_letter(s: &str) -> String {
26 let mut c = s.chars();
27 c.next()
28 .map(char::to_uppercase)
29 .map(|first| first.to_string() + c.as_str())
30 .unwrap_or_default()
31}
32
33/// Converts the first letter of a given string to lowercase.
34///
35/// This function takes a string slice and returns a new `String` with the first
36/// letter in lowercase. If the string is empty, it returns an empty string.
37///
38/// # Arguments
39///
40/// * `s` - A string slice that holds the input string
41///
42/// # Returns
43///
44/// A `String` with the first letter in lowercase
45///
46/// # Examples
47///
48/// ```
49/// # use bulloak_syntax::utils::lower_first_letter;
50/// let result = lower_first_letter("Hello");
51/// assert_eq!(result, "hello");
52/// ```
53pub fn lower_first_letter(s: &str) -> String {
54 let mut c = s.chars();
55 c.next()
56 .map(char::to_lowercase)
57 .map(|first| first.to_string() + c.as_str())
58 .unwrap_or_default()
59}
60
61/// Sanitizes a string to make it a valid identifier.
62///
63/// This function replaces hyphens with underscores and removes any characters
64/// that are not valid in an identifier according to the Unicode Standard Annex
65/// #31.
66///
67/// # Arguments
68///
69/// * `identifier` - A string slice that holds the input identifier
70///
71/// # Returns
72///
73/// A `String` containing the sanitized identifier
74///
75/// # Examples
76///
77/// ```
78/// # use bulloak_syntax::utils::sanitize;
79/// let result = sanitize("my-variable@123");
80/// assert_eq!(result, "my_variable123");
81/// ```
82pub fn sanitize(identifier: &str) -> String {
83 identifier
84 .replace('-', "_")
85 .replace(|c: char| !c.is_xid_continue() && c != ' ', "")
86}
87
88/// Converts a sentence to pascal case.
89///
90/// The conversion is done by capitalizing the first letter of each word
91/// in the title and removing the spaces. For example, the sentence
92/// `when only owner` is converted to the `WhenOnlyOwner` string.
93///
94/// # Arguments
95///
96/// * `sentence` - A string slice that holds the input sentence
97///
98/// # Returns
99///
100/// A `String` in pascal case
101///
102/// # Examples
103///
104/// ```
105/// # use bulloak_syntax::utils::to_pascal_case;
106/// let result = to_pascal_case("when only owner");
107/// assert_eq!(result, "WhenOnlyOwner");
108/// ```
109pub fn to_pascal_case(sentence: &str) -> String {
110 sentence.split_whitespace().map(upper_first_letter).collect::<String>()
111}
112
113/// Repeats a given string a specified number of times.
114///
115/// # Arguments
116///
117/// * `s` - A string slice to be repeated
118/// * `n` - The number of times to repeat the string
119///
120/// # Returns
121///
122/// A `String` containing the repeated string
123///
124/// # Examples
125///
126/// ```
127/// # use bulloak_syntax::utils::repeat_str;
128/// let result = repeat_str("abc", 3);
129/// assert_eq!(result, "abcabcabc");
130/// ```
131pub fn repeat_str(s: &str, n: usize) -> String {
132 s.repeat(n)
133}
134
135/// Returns the singular or plural form of a word based on the count.
136///
137/// # Arguments
138///
139/// * `count` - The count to determine which form to use
140/// * `singular` - The singular form of the word
141/// * `plural` - The plural form of the word
142///
143/// # Returns
144///
145/// A string slice containing either the singular or plural form
146///
147/// # Examples
148///
149/// ```
150/// # use bulloak_syntax::utils::pluralize;
151/// assert_eq!(pluralize(1, "apple", "apples"), "apple");
152/// assert_eq!(pluralize(2, "apple", "apples"), "apples");
153/// ```
154pub fn pluralize<'a>(
155 count: usize,
156 singular: &'a str,
157 plural: &'a str,
158) -> &'a str {
159 if count == 1 {
160 singular
161 } else {
162 plural
163 }
164}
165
166#[cfg(test)]
167mod tests {
168 use super::to_pascal_case;
169
170 #[test]
171 fn to_modifier() {
172 assert_eq!(to_pascal_case("when only owner"), "WhenOnlyOwner");
173 assert_eq!(to_pascal_case("when"), "When");
174 assert_eq!(to_pascal_case(""), "");
175 }
176}