Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/stdx/src/lib.rs')
| -rw-r--r-- | crates/stdx/src/lib.rs | 57 |
1 files changed, 51 insertions, 6 deletions
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs index 7ab26b1890..a1af4cc6be 100644 --- a/crates/stdx/src/lib.rs +++ b/crates/stdx/src/lib.rs @@ -221,12 +221,7 @@ pub fn trim_indent(mut text: &str) -> String { if text.starts_with('\n') { text = &text[1..]; } - let indent = text - .lines() - .filter(|it| !it.trim().is_empty()) - .map(|it| it.len() - it.trim_start().len()) - .min() - .unwrap_or(0); + let indent = indent_of(text); text.split_inclusive('\n') .map( |line| { @@ -236,6 +231,25 @@ pub fn trim_indent(mut text: &str) -> String { .collect() } +#[must_use] +fn indent_of(text: &str) -> usize { + text.lines() + .filter(|it| !it.trim().is_empty()) + .map(|it| it.len() - it.trim_start().len()) + .min() + .unwrap_or(0) +} + +#[must_use] +pub fn dedent_by(spaces: usize, text: &str) -> String { + text.split_inclusive('\n') + .map(|line| { + let trimmed = line.trim_start_matches(' '); + if line.len() - trimmed.len() <= spaces { trimmed } else { &line[spaces..] } + }) + .collect() +} + pub fn equal_range_by<T, F>(slice: &[T], mut key: F) -> ops::Range<usize> where F: FnMut(&T) -> Ordering, @@ -367,6 +381,37 @@ mod tests { } #[test] + fn test_dedent() { + assert_eq!(dedent_by(0, ""), ""); + assert_eq!(dedent_by(1, ""), ""); + assert_eq!(dedent_by(2, ""), ""); + assert_eq!(dedent_by(0, "foo"), "foo"); + assert_eq!(dedent_by(2, "foo"), "foo"); + assert_eq!(dedent_by(2, " foo"), "foo"); + assert_eq!(dedent_by(2, " foo"), " foo"); + assert_eq!(dedent_by(2, " foo\nbar"), " foo\nbar"); + assert_eq!(dedent_by(2, "foo\n bar"), "foo\n bar"); + assert_eq!(dedent_by(2, "foo\n\n bar"), "foo\n\n bar"); + assert_eq!(dedent_by(2, "foo\n.\n bar"), "foo\n.\n bar"); + assert_eq!(dedent_by(2, "foo\n .\n bar"), "foo\n.\n bar"); + assert_eq!(dedent_by(2, "foo\n .\n bar"), "foo\n .\n bar"); + } + + #[test] + fn test_indent_of() { + assert_eq!(indent_of(""), 0); + assert_eq!(indent_of(" "), 0); + assert_eq!(indent_of(" x"), 1); + assert_eq!(indent_of(" x\n"), 1); + assert_eq!(indent_of(" x\ny"), 0); + assert_eq!(indent_of(" x\n y"), 1); + assert_eq!(indent_of(" x\n y"), 1); + assert_eq!(indent_of(" x\n y"), 2); + assert_eq!(indent_of(" x\n y\n"), 2); + assert_eq!(indent_of(" x\n\n y\n"), 2); + } + + #[test] fn test_replace() { #[track_caller] fn test_replace(src: &str, from: char, to: &str, expected: &str) { |