Repository: mgeisler/textwrap (language: rust)

Issue:
Take newlines into account when wrapping
```rust
println!("{}",fill("1 3 5 7
1 3 5 7",11));

/*
Expected:
1 3 5 7
1 3 5 7

Actual output:
1 3 5 7
1 3
5 7
*/
```

Currently, it seems that `fill` considers line breaks like any other whitespace character. It would be nice if the function could take line breaks into account when computing the wrapping!


Discussion / hints:

Fix patch:
diff --git a/src/lib.rs b/src/lib.rs
index ef14d551..73480134 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -585,7 +585,25 @@ impl<'a> WrapIterImpl<'a> {
         while let Some((idx, ch)) = self.char_indices.next() {
             let char_width = ch.width().unwrap_or(0);
             let char_len = ch.len_utf8();
-            if is_whitespace(ch) {
+
+            if ch == '\n' {
+                self.split = idx;
+                self.split_len = char_len;
+                self.line_width_at_split = self.line_width;
+                self.in_whitespace = false;
+
+                // If this is not the final line, return the current line. Otherwise,
+                // we will return the line with its line break after exiting the loop
+                if self.split + self.split_len < self.source.len() {
+                    let mut line = self.create_result_line(wrapper);
+                    line += &self.source[self.start..self.split];
+
+                    self.start = self.split + self.split_len;
+                    self.line_width = wrapper.subsequent_indent.width();
+
+                    return Some(line);
+                }
+            } else if is_whitespace(ch) {
                 // Extend the previous split or create a new one.
                 if self.in_whitespace {
                     self.split_len += char_len;
@@ -1135,6 +1153,24 @@ mod tests {
         assert_eq!(wrap("foobar", 0), vec!["f", "o", "o", "b", "a", "r"]);
     }
 
+    #[test]
+    fn break_words_line_breaks() {
+        assert_eq!(fill("ab\ncdefghijkl", 5), "ab\ncdefg\nhijkl");
+        assert_eq!(fill("abcdefgh\nijkl", 5), "abcde\nfgh\nijkl");
+    }
+
+    #[test]
+    fn preserve_line_breaks() {
+        assert_eq!(fill("test\n", 11), "test\n");
+        assert_eq!(fill("test\n\na\n\n", 11), "test\n\na\n\n");
+        assert_eq!(fill("1 3 5 7\n1 3 5 7", 7), "1 3 5 7\n1 3 5 7");
+    }
+
+    #[test]
+    fn wrap_preserve_line_breaks() {
+        assert_eq!(fill("1 3 5 7\n1 3 5 7", 5), "1 3 5\n7\n1 3 5\n7");
+    }
+
     #[test]
     fn non_breaking_space() {
         let wrapper = Wrapper::new(5).break_words(false);


Test patch: