1pub fn clean_all(input: &str) -> String {
4 let step1 = tabs_to_spaces(input);
5 let step2 = remove_trailing_spaces(&step1);
6 let step3 = fix_backslash_space(&step2);
7 let step4 = normalize_blank_lines(&step3);
8 normalize_line_endings(&step4)
9}
10
11pub fn clean_syntax(input: &str) -> String {
12 let step1 = tabs_to_spaces(input);
13 let step2 = fix_backslash_space(&step1);
14 normalize_line_endings(&step2)
15}
16
17pub fn clean_git(input: &str) -> String {
18 let step1 = remove_trailing_spaces(input);
19 normalize_blank_lines(&step1)
20}
21
22pub fn clean_size(input: &str) -> String {
23 let step1 = remove_trailing_spaces(input);
24 normalize_blank_lines(&step1)
25}
26
27pub fn tabs_to_spaces(input: &str) -> String {
30 input.replace("\t", " ")
31}
32
33pub fn remove_trailing_spaces(input: &str) -> String {
34 input.lines()
35 .map(|line| line.trim_end())
36 .collect::<Vec<_>>()
37 .join("\n")
38}
39
40pub fn fix_backslash_space(input: &str) -> String {
41 input.lines()
42 .map(|line| {
43 if line.trim_end().ends_with("\\") {
44 line.trim_end().to_string()
45 } else {
46 line.to_string()
47 }
48 })
49 .collect::<Vec<_>>()
50 .join("\n")
51}
52
53pub fn normalize_blank_lines(input: &str) -> String {
54 let mut result = Vec::new();
55 let mut last_blank = false;
56
57 for line in input.lines() {
58 let is_blank = line.trim().is_empty();
59 if is_blank {
60 if !last_blank {
61 result.push("");
62 }
63 } else {
64 result.push(line);
65 }
66 last_blank = is_blank;
67 }
68
69 result.join("\n")
70}
71
72pub fn normalize_line_endings(input: &str) -> String {
73 input.replace("\r\n", "\n")
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 #[test]
83 fn test_tabs_to_spaces() {
84 let input = "\tprint('hello')";
85 let expected = " print('hello')";
86 assert_eq!(tabs_to_spaces(input), expected);
87 }
88
89 #[test]
90 fn test_remove_trailing_spaces() {
91 let input = "hello \nworld ";
92 let expected = "hello\nworld";
93 assert_eq!(remove_trailing_spaces(input), expected);
94 }
95
96 #[test]
97 fn test_fix_backslash_space() {
98 let input = "print('hi') \\ \nnext";
99 let expected = "print('hi') \\\nnext";
100 assert_eq!(fix_backslash_space(input), expected);
101 }
102
103 #[test]
104 fn test_normalize_blank_lines() {
105 let input = "line1\n\n\nline2\n\n";
106 let expected = "line1\n\nline2\n";
107 assert_eq!(normalize_blank_lines(input), expected);
108 }
109
110 #[test]
111 fn test_normalize_line_endings() {
112 let input = "line1\r\nline2\r\n";
113 let expected = "line1\nline2\n";
114 assert_eq!(normalize_line_endings(input), expected);
115 }
116
117 #[test]
120 fn test_clean_all() {
121 let input = "\tprint('hi') \\ \r\n\r\n";
122 let expected = " print('hi') \\";
123 assert_eq!(clean_all(input), expected);
124 }
125
126 #[test]
127 fn test_clean_syntax() {
128 let input = "\tprint('hi') \\ \r\n";
129 let expected = " print('hi') \\";
130 assert_eq!(clean_syntax(input), expected);
131 }
132
133 #[test]
134 fn test_clean_git() {
135 let input = "line with spaces \n\n\nline2";
136 let expected = "line with spaces\n\nline2";
137 assert_eq!(clean_git(input), expected);
138 }
139
140 #[test]
141 fn test_clean_size() {
142 let input = "line with spaces \n\n\nline2";
143 let expected = "line with spaces\n\nline2";
144 assert_eq!(clean_size(input), expected);
145 }
146
147 #[test]
150 fn test_empty_input() {
151 let input = "";
152 let expected = "";
153 assert_eq!(clean_all(input), expected);
154 }
155
156 #[test]
157 fn test_only_blank_lines() {
158 let input = "\n\n\n";
159 let expected = "";
160 assert_eq!(clean_all(input), expected);
161 }
162
163 #[test]
164 fn test_tabs_and_trailing_spaces() {
165 let input = "\tline1 \n\tline2 ";
166 let expected = " line1\n line2";
167 assert_eq!(clean_all(input), expected);
168 }
169
170 #[test]
171 fn test_backslash_at_end() {
172 let input = "line with backslash \\ ";
173 let expected = "line with backslash \\";
174 assert_eq!(clean_all(input), expected);
175 }
176}