diff --git a/Cargo.toml b/Cargo.toml index 6bba8bd..9bce240 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ license = "MIT OR Apache-2.0" clippy = [] [dependencies] +regex = "1.10.4" smallvec = "1.11.2" textwrap = "0.16.0" unicode-width = "0.1.11" diff --git a/src/lib.rs b/src/lib.rs index 8b84307..d60f0ba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +use regex::Regex; use smallvec::*; use std::io::{Result, Write}; use textwrap::fill; @@ -84,8 +85,11 @@ where // Final output is stored here let mut write_buffer = SmallVec::<[u8; BUFSIZE]>::new(); + // Pre process to merge continuous whitespaces into one space character + let input = merge_white_spaces(input); + // Let textwrap work its magic - let wrapped = fill(input, max_width); + let wrapped = fill(input.as_str(), max_width); let lines: Vec<&str> = wrapped.lines().collect(); @@ -147,3 +151,9 @@ fn longest_line(lines: &[&str]) -> usize { .max() .unwrap_or(0) } + +/// Merge continues white spaces into one space character while preserving newline characters. +fn merge_white_spaces(input: &str) -> String { + let re = Regex::new(r"([^\S\r\n])+").unwrap(); + re.replace_all(input, " ").to_string() +} diff --git a/tests/integration_test.rs b/tests/integration_test.rs index cdf5fd0..b648227 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -253,3 +253,58 @@ fn multibyte_string() -> Result<(), ()> { assert_eq!(&expected[1..], actual); Ok(()) } + +#[test] +fn string_with_continues_white_spaces() -> Result<(), ()> { + #[cfg(not(feature = "clippy"))] + let expected = r#" + __________________________________ +/ A string with many white spaces \ +| | +| | +\ And many newline characters / + ---------------------------------- + \ + \ + _~^~^~_ + \) / o o \ (/ + '_ - _' + / '-----' \ +"#; + #[cfg(feature = "clippy")] + let expected = r#" + __________________________________ +/ A string with many white spaces \ +| | +| | +\ And many newline characters / + ---------------------------------- + \ + \ + __ + / \ + | | + @ @ + | | + || |/ + || || + |\_/| + \___/ +"#; + + let input = " A string with many white spaces + + + And many newline characters"; + let width = DEFAULT_WIDTH; + + let mut vec = Vec::new(); + + say(input, width, &mut vec).unwrap(); + + let actual = std::str::from_utf8(&vec).unwrap(); + + assert_eq!(&expected[1..], actual); + + Ok(()) +}