]> git.lizzy.rs Git - rust.git/commitdiff
rewrite_string: retain blank lines that are trailing
authorStéphane Campinas <stephane.campinas@gmail.com>
Sun, 7 Oct 2018 20:53:48 +0000 (22:53 +0200)
committerStéphane Campinas <stephane.campinas@gmail.com>
Mon, 8 Oct 2018 12:48:15 +0000 (14:48 +0200)
src/string.rs

index dcedeed111427d22ecdf3797c48d82dd7008f46b..daca59e87021bf181866a6ee5d2eb200e2c10159 100644 (file)
@@ -100,36 +100,20 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option<String>
     loop {
         // All the input starting at cur_start fits on the current line
         if graphemes.len() - cur_start <= cur_max_chars {
-            // trim trailing whitespaces
-            let graphemes_minus_ws = if !fmt.trim_end {
-                &graphemes[cur_start..]
-            } else {
-                match graphemes[cur_start..]
-                    .iter()
-                    .rposition(|grapheme| !is_whitespace(grapheme))
-                {
-                    Some(index) => &graphemes[cur_start..=cur_start + index],
-                    None => &graphemes[cur_start..],
-                }
-            };
-            if is_bareline_ok {
-                // new lines don't need to start with line_start
-                result.push_str(&graphemes_minus_ws.join(""));
-            } else {
-                // new lines need to be indented and prefixed with line_start
-                for grapheme in graphemes_minus_ws {
-                    if is_line_feed(grapheme) {
-                        // take care of blank lines
-                        if fmt.trim_end && result.ends_with(' ') {
-                            result = result.trim_right().to_string();
-                        }
-                        result.push_str(&indent_with_newline);
+            for (i, grapheme) in graphemes[cur_start..].iter().enumerate() {
+                if is_line_feed(grapheme) {
+                    // take care of blank lines
+                    result = trim_right_but_line_feed(fmt.trim_end, result);
+                    result.push_str("\n");
+                    if !is_bareline_ok && cur_start + i + 1 < graphemes.len() {
+                        result.push_str(&indent_without_newline);
                         result.push_str(fmt.line_start);
-                    } else {
-                        result.push_str(grapheme);
                     }
+                } else {
+                    result.push_str(grapheme);
                 }
             }
+            result = trim_right_but_line_feed(fmt.trim_end, result);
             break;
         }
 
@@ -169,6 +153,18 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option<String>
     wrap_str(result, fmt.config.max_width(), fmt.shape)
 }
 
+/// Trims whitespaces to the right except for the line feed character.
+fn trim_right_but_line_feed(trim_end: bool, result: String) -> String {
+    let whitespace_except_line_feed = |c: char| c.is_whitespace() && c != '\n';
+    if trim_end && result.ends_with(whitespace_except_line_feed) {
+        result
+            .trim_right_matches(whitespace_except_line_feed)
+            .to_string()
+    } else {
+        result
+    }
+}
+
 /// Result of breaking a string so it fits in a line and the state it ended in.
 /// The state informs about what to do with the snippet and how to continue the breaking process.
 #[derive(Debug, PartialEq)]
@@ -198,17 +194,22 @@ fn break_string(max_chars: usize, trim_end: bool, input: &[&str]) -> SnippetStat
     let break_at = |index /* grapheme at index is included */| {
         // Take in any whitespaces to the left/right of `input[index]` while
         // preserving line feeds
+        let not_whitespace_except_line_feed = |g| is_line_feed(g) || !is_whitespace(g);
         let index_minus_ws = input[0..=index]
             .iter()
-            .rposition(|grapheme| !is_whitespace(grapheme))
+            .rposition(|grapheme| not_whitespace_except_line_feed(grapheme))
             .unwrap_or(index);
         // Take into account newlines occuring in input[0..=index], i.e., the possible next new
         // line. If there is one, then text after it could be rewritten in a way that the available
         // space is fully used.
         for (i, grapheme) in input[0..=index].iter().enumerate() {
             if is_line_feed(grapheme) {
-                if i < index_minus_ws || !trim_end {
-                    return SnippetState::EndWithLineFeed(input[0..=i].join("").to_string(), i + 1);
+                if i <= index_minus_ws {
+                    let mut line = input[0..i].join("");
+                    if trim_end {
+                        line = line.trim_right().to_string();
+                    }
+                    return SnippetState::EndWithLineFeed(format!("{}\n", line), i + 1);
                 }
                 break;
             }
@@ -221,7 +222,7 @@ fn break_string(max_chars: usize, trim_end: bool, input: &[&str]) -> SnippetStat
                     input[0..=index + 1 + i].join("").to_string(),
                     index + 2 + i,
                 );
-            } else if !is_whitespace(grapheme) {
+            } else if not_whitespace_except_line_feed(grapheme) {
                 index_plus_ws = index + i;
                 break;
             }
@@ -524,4 +525,38 @@ fn blank_line_with_non_empty_line_start() {
             )
         );
     }
+
+    #[test]
+    fn retain_blank_lines() {
+        let config: Config = Default::default();
+        let fmt = StringFormat {
+            opener: "",
+            closer: "",
+            line_start: "// ",
+            line_end: "",
+            shape: Shape::legacy(20, Indent::from_width(&config, 4)),
+            trim_end: true,
+            config: &config,
+        };
+
+        let comment = "Aenean\n\nmetus. Vestibulum ac lacus.\n\n";
+        assert_eq!(
+            rewrite_string(comment, &fmt),
+            Some(
+                "Aenean\n    //\n    // metus. Vestibulum ac\n    // lacus.\n    //\n".to_string()
+            )
+        );
+
+        let comment = "Aenean\n\nmetus. Vestibulum ac lacus.\n";
+        assert_eq!(
+            rewrite_string(comment, &fmt),
+            Some("Aenean\n    //\n    // metus. Vestibulum ac\n    // lacus.\n".to_string())
+        );
+
+        let comment = "Aenean\n        \nmetus. Vestibulum ac lacus.";
+        assert_eq!(
+            rewrite_string(comment, &fmt),
+            Some("Aenean\n    //\n    // metus. Vestibulum ac\n    // lacus.".to_string())
+        );
+    }
 }