diff options
author | Aleksey Kladov <[email protected]> | 2020-06-23 21:27:24 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-06-23 22:33:41 +0100 |
commit | aa69757a01c26cfad12498053c55cbc3d66a4bdb (patch) | |
tree | 0337d53010edd2d5d09ab3ceffb0945b8eb4ae55 /crates/stdx/src | |
parent | f2f69e75c84014a6173798e95af0baa48df2607e (diff) |
More principled indentation trimming in fixtures
Diffstat (limited to 'crates/stdx/src')
-rw-r--r-- | crates/stdx/src/lib.rs | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs index 100db9d5d..08ac6f70f 100644 --- a/crates/stdx/src/lib.rs +++ b/crates/stdx/src/lib.rs | |||
@@ -128,3 +128,85 @@ pub fn split_delim(haystack: &str, delim: char) -> Option<(&str, &str)> { | |||
128 | let idx = haystack.find(delim)?; | 128 | let idx = haystack.find(delim)?; |
129 | Some((&haystack[..idx], &haystack[idx + delim.len_utf8()..])) | 129 | Some((&haystack[..idx], &haystack[idx + delim.len_utf8()..])) |
130 | } | 130 | } |
131 | |||
132 | pub fn trim_indent(mut text: &str) -> String { | ||
133 | if text.starts_with('\n') { | ||
134 | text = &text[1..]; | ||
135 | } | ||
136 | let indent = text | ||
137 | .lines() | ||
138 | .filter(|it| !it.trim().is_empty()) | ||
139 | .map(|it| it.len() - it.trim_start().len()) | ||
140 | .min() | ||
141 | .unwrap_or(0); | ||
142 | lines_with_ends(text) | ||
143 | .map( | ||
144 | |line| { | ||
145 | if line.len() <= indent { | ||
146 | line.trim_start_matches(' ') | ||
147 | } else { | ||
148 | &line[indent..] | ||
149 | } | ||
150 | }, | ||
151 | ) | ||
152 | .collect() | ||
153 | } | ||
154 | |||
155 | pub fn lines_with_ends(text: &str) -> LinesWithEnds { | ||
156 | LinesWithEnds { text } | ||
157 | } | ||
158 | |||
159 | pub struct LinesWithEnds<'a> { | ||
160 | text: &'a str, | ||
161 | } | ||
162 | |||
163 | impl<'a> Iterator for LinesWithEnds<'a> { | ||
164 | type Item = &'a str; | ||
165 | fn next(&mut self) -> Option<&'a str> { | ||
166 | if self.text.is_empty() { | ||
167 | return None; | ||
168 | } | ||
169 | let idx = self.text.find('\n').map_or(self.text.len(), |it| it + 1); | ||
170 | let (res, next) = self.text.split_at(idx); | ||
171 | self.text = next; | ||
172 | Some(res) | ||
173 | } | ||
174 | } | ||
175 | |||
176 | #[cfg(test)] | ||
177 | mod tests { | ||
178 | use super::*; | ||
179 | |||
180 | #[test] | ||
181 | fn test_trim_indent() { | ||
182 | assert_eq!(trim_indent(""), ""); | ||
183 | assert_eq!( | ||
184 | trim_indent( | ||
185 | " | ||
186 | hello | ||
187 | world | ||
188 | " | ||
189 | ), | ||
190 | "hello\nworld\n" | ||
191 | ); | ||
192 | assert_eq!( | ||
193 | trim_indent( | ||
194 | " | ||
195 | hello | ||
196 | world" | ||
197 | ), | ||
198 | "hello\nworld" | ||
199 | ); | ||
200 | assert_eq!(trim_indent(" hello\n world\n"), "hello\nworld\n"); | ||
201 | assert_eq!( | ||
202 | trim_indent( | ||
203 | " | ||
204 | fn main() { | ||
205 | return 92; | ||
206 | } | ||
207 | " | ||
208 | ), | ||
209 | "fn main() {\n return 92;\n}\n" | ||
210 | ); | ||
211 | } | ||
212 | } | ||