untools/lib.rs
1use std::fs;
2
3use console::style;
4use utils::{is_camel_or_pascal_case, starts_with_digit};
5
6mod utils;
7/// Converts a camelCase or PascalCase string to snake_case.
8///
9/// If the input string is empty, returns an error message.
10/// If the input string is a digit, returns an error message.
11/// If the input string already contains underscores, returns the input string as-is.
12/// If the input string is not in camelCase format, returns an error message.
13///
14/// # Arguments
15///
16/// * `name` - A string slice that holds the variable name to be converted.
17/// * `is_constant` - A boolean flag indicating if the output should be in all caps.
18///
19/// # Returns
20///
21/// A String containing the snake_case version of the input variable name.
22///
23/// # Usage
24///
25/// This converts the the variable "testVariable" from camelcase to snakecase in all caps.
26///
27/// ```
28/// use untools::camel_to_snake;
29/// assert_eq!(camel_to_snake("testVariable", true), "TEST_VARIABLE")
30/// ```
31///
32pub fn camel_to_snake(name: &str, is_constant: bool) -> String {
33 if name.is_empty() {
34 println!(
35 "{}",
36 style("Input string is empty. Please provide a valid variable name.").color256(208)
37 );
38 return String::new();
39 }
40
41 if !starts_with_digit(name) {
42 println!("{}", style("Input string is a digit.").color256(208));
43 return String::new();
44 }
45
46 if name.contains('_') {
47 return name.to_string();
48 }
49
50 if !is_camel_or_pascal_case(name) {
51 println!(
52 "{}",
53 style("is not in camelCase format. Please provide a valid camelCase variable name.")
54 .color256(208)
55 );
56 return String::new();
57 }
58
59 let mut result = String::new();
60
61 for (i, c) in name.chars().enumerate() {
62 if i > 0 && c.is_uppercase() {
63 result.push('_');
64 }
65 result.push(c.to_lowercase().next().unwrap());
66 }
67
68 if is_constant {
69 return result.to_uppercase();
70 }
71
72 result
73}
74
75/// Batch convert variable names
76///
77/// This function reads variable name data from the specified input file, converts them to the specified naming convention (camelCase or SCREAMING_SNAKE_CASE),
78/// and then writes the converted results to the specified output file.
79///
80/// # Arguments
81/// - `ifile`: The path to the input file
82/// - `ofile`: The path to the output file
83/// - `is_constant`: Whether to convert to SCREAMING_SNAKE_CASE, `true` to convert to SCREAMING_SNAKE_CASE, `false` to convert to camelCase
84/// - `silent`: Whether to supress output
85/// # Example
86///
87/// ```rust
88/// untools::batch_convert("input.txt", "output.txt", true, false);
89/// ```
90pub fn batch_convert(ifile: &str, ofile: &str, is_constant: bool, silent: bool) {
91 let contents = fs::read_to_string(ifile).expect("Unable to read file.");
92
93 let converted_names: Vec<String> = contents
94 .lines()
95 .map(|line| camel_to_snake(line.trim(), is_constant))
96 .collect();
97
98 let output_content = converted_names.join("\n");
99 fs::write(ofile, output_content).expect("Unable to write file.");
100 if !silent {
101 println!("Batch conversion successful! Results written to {}", ofile);
102 }
103}
104
105/// Converts a snake_case string to a camelCase string.
106///
107/// # Arguments
108///
109/// * `name` - A string slice that holds the snake_case variable name to be converted.
110/// * `to_lower_camel` - A boolean indicating whether the output should be in lowerCamelCase (true) or UpperCamelCase (false).
111///
112/// # Returns
113///
114/// * A String containing the camelCase representation of the input string.
115///
116pub fn snake_to_camel(name: &str, upper_case_camel: bool) -> String {
117 let mut camel_case = String::new();
118 let mut capitalize_next = true;
119
120 let mut to_lower_camel = !upper_case_camel;
121
122 if name.is_empty() {
123 return String::from("Input string is empty. Please provide a valid variable name.");
124 }
125
126 if !starts_with_digit(name) {
127 return String::from("Input string is a digit.");
128 }
129
130 for c in name.chars() {
131 if c == '_' {
132 capitalize_next = true;
133 } else {
134 if capitalize_next {
135 if to_lower_camel {
136 camel_case.push(c.to_ascii_lowercase());
137 to_lower_camel = false; // Reset to_lower_camel for the next word
138 } else {
139 camel_case.push(c.to_ascii_uppercase());
140 }
141 capitalize_next = false;
142 } else {
143 camel_case.push(c);
144 }
145 }
146 }
147 camel_case
148}