Skip to main content

python_cleaner/
lib.rs

1/* ---------- Cleaning Modes ---------- */
2
3pub 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
27/* ---------- Core Cleaning Functions ---------- */
28
29pub 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    // ---------- Core Function Tests ----------
81
82    #[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    // ---------- Wrapper / Combined Function Tests ----------
118
119    #[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    // ---------- Edge Case Tests ----------
148
149    #[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}