aboutsummaryrefslogtreecommitdiff
path: root/crates/stdx/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/stdx/src')
-rw-r--r--crates/stdx/src/lib.rs85
1 files changed, 83 insertions, 2 deletions
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs
index c0356344c..08ac6f70f 100644
--- a/crates/stdx/src/lib.rs
+++ b/crates/stdx/src/lib.rs
@@ -1,5 +1,4 @@
1//! Missing batteries for standard libraries. 1//! Missing batteries for standard libraries.
2
3use std::{cell::Cell, fmt, time::Instant}; 2use std::{cell::Cell, fmt, time::Instant};
4 3
5#[inline(always)] 4#[inline(always)]
@@ -125,7 +124,89 @@ pub fn replace(buf: &mut String, from: char, to: &str) {
125 *buf = buf.replace(from, to) 124 *buf = buf.replace(from, to)
126} 125}
127 126
128pub fn split1(haystack: &str, delim: char) -> Option<(&str, &str)> { 127pub fn split_delim(haystack: &str, delim: char) -> Option<(&str, &str)> {
129 let idx = haystack.find(delim)?; 128 let idx = haystack.find(delim)?;
130 Some((&haystack[..idx], &haystack[idx + delim.len_utf8()..])) 129 Some((&haystack[..idx], &haystack[idx + delim.len_utf8()..]))
131} 130}
131
132pub 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
155pub fn lines_with_ends(text: &str) -> LinesWithEnds {
156 LinesWithEnds { text }
157}
158
159pub struct LinesWithEnds<'a> {
160 text: &'a str,
161}
162
163impl<'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)]
177mod 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}