From 2ce75b114716cf8900640b8f8e5db44438fc25da Mon Sep 17 00:00:00 2001 From: David Bar-On <61089727+davidBar-On@users.noreply.github.com> Date: Thu, 10 Dec 2020 01:41:17 +0200 Subject: [PATCH] Not wrap strings at escape backslash (#4524) * Issue #4471 - not wrap strings at backslash * Changes according to comments to the fix PR #4524 * Some more modifications to improve the code per comments received --- src/formatting/string.rs | 18 ++++++++++++++++++ tests/source/string-lit.rs | 9 +++++++++ tests/target/string-lit.rs | 23 +++++++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/src/formatting/string.rs b/src/formatting/string.rs index 08960959ebf..4844352f1bc 100644 --- a/src/formatting/string.rs +++ b/src/formatting/string.rs @@ -226,6 +226,24 @@ fn not_whitespace_except_line_feed(g: &str) -> bool { /// FIXME(issue#3281): We must follow UAX#14 algorithm instead of this. fn break_string(max_width: usize, trim_end: bool, line_end: &str, input: &[&str]) -> SnippetState { let break_at = |index /* grapheme at index is included */| { + // Ensure break is not after an escape '\' as it will "escape" the `\` that is added + // for concatenating the two parts of the broken line. + let index = if input[index] != "\\" { + index + } else { + let index_offset = match input[0..index] + .iter() + .rposition(|grapheme| grapheme.ne(&"\\")) + { + // There is a non-`\` to the left + Some(non_backslash_index) => (index - non_backslash_index) % 2, + // Only `\` to the left + None => index % 2, + }; + // Make sure break is after even number (including zero) of `\` + index - index_offset + }; + // Take in any whitespaces to the left/right of `input[index]` while // preserving line feeds let index_minus_ws = input[0..=index] diff --git a/tests/source/string-lit.rs b/tests/source/string-lit.rs index 7719e76ffe7..39cb0be98d9 100644 --- a/tests/source/string-lit.rs +++ b/tests/source/string-lit.rs @@ -59,3 +59,12 @@ fn issue_1282() { // #1987 #[link_args = "-s NO_FILESYSTEM=1 -s NO_EXIT_RUNTIME=1 -s EXPORTED_RUNTIME_METHODS=[\"_malloc\"] -s NO_DYNAMIC_EXECUTION=1 -s ELIMINATE_DUPLICATE_FUNCTIONS=1 -s EVAL_CTORS=1"] extern "C" {} + +// #4471 - strings including `\` shaouldnot wrap at the `\` +const ASCII_ESCAPE: &str = "id\u{1f}1\u{1f}/Users/nixon/dev/rs/gitstatusd\u{1f}1c9be4fe5460a30e70de9cbf99c3ec7064296b28\u{1f}master\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}7\u{1f}0\u{1f}1\u{1f}0\u{1f}1\u{1f}0\u{1f}0\u{1f}0\u{1f}\u{1f}0\u{1f}0\u{1f}0\u{1f}\u{1f}\u{1f}0\u{1f}0\u{1f}0\u{1f}0"; +const ASCII_ESCAPE: &str = "id\u{1f}1\u{1f}/Users/nixon/dev/rs/gitstatusd\u{1f}1c9be4fe5460a30e70de9cbf99c3ec7064296b28\u{1f}master\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}7\u{1f}0"; +const ASCII_ESCAPE: &str = "id\u{1f}1\u{1f}/Users/nixon/dev/rs/gitstatusd\u{1f}1c9be4fe5460a30e70de9cbf99c3ec70642,96b28\u{1f}master\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}7\u{1f}0"; +const ASCII_ESCAPE: &str = "id\u{1f}1\u{1f}/Users/nixon/dev/rs/gitstatusd\u{1f}1c9be4fe5460a30e70de9cbf99c3ec70642 96b28\u{1f}master\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}7\u{1f}0"; +const ASCII_ESCAPE: &str = "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"; +const ASCII: &str = "xxxxxxxxxxxxxxxxxxxxxxxxxx\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"; +const ASCII: &str = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\\nyyyyyyyyyyyy"; diff --git a/tests/target/string-lit.rs b/tests/target/string-lit.rs index 2d33061074d..af01d4326ae 100644 --- a/tests/target/string-lit.rs +++ b/tests/target/string-lit.rs @@ -61,3 +61,26 @@ fn issue_1282() { #[link_args = "-s NO_FILESYSTEM=1 -s NO_EXIT_RUNTIME=1 -s EXPORTED_RUNTIME_METHODS=[\"_malloc\"] \ -s NO_DYNAMIC_EXECUTION=1 -s ELIMINATE_DUPLICATE_FUNCTIONS=1 -s EVAL_CTORS=1"] extern "C" {} + +// #4471 - strings including `\` shaouldnot wrap at the `\` +const ASCII_ESCAPE: &str = + "id\u{1f}1\u{1f}/Users/nixon/dev/rs/gitstatusd\u{1f}1c9be4fe5460a30e70de9cbf99c3ec7064296b28\ + \u{1f}master\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}7\u{1f}0\u{1f}1\u{1f}0\u{1f}1\u{1f}0\u{1f}0\u{1f}0\ + \u{1f}\u{1f}0\u{1f}0\u{1f}0\u{1f}\u{1f}\u{1f}0\u{1f}0\u{1f}0\u{1f}0"; +const ASCII_ESCAPE: &str = "id\u{1f}1\u{1f}/Users/nixon/dev/rs/gitstatusd\ + \u{1f}1c9be4fe5460a30e70de9cbf99c3ec7064296b28\u{1f}master\u{1f}\ + \u{1f}\u{1f}\u{1f}\u{1f}7\u{1f}0"; +const ASCII_ESCAPE: &str = "id\u{1f}1\u{1f}/Users/nixon/dev/rs/gitstatusd\ + \u{1f}1c9be4fe5460a30e70de9cbf99c3ec70642,96b28\u{1f}master\u{1f}\ + \u{1f}\u{1f}\u{1f}\u{1f}7\u{1f}0"; +const ASCII_ESCAPE: &str = "id\u{1f}1\u{1f}/Users/nixon/dev/rs/gitstatusd\ + \u{1f}1c9be4fe5460a30e70de9cbf99c3ec70642 \ + 96b28\u{1f}master\u{1f}\u{1f}\u{1f}\u{1f}\u{1f}7\u{1f}0"; +const ASCII_ESCAPE: &str = "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + \\"; +const ASCII: &str = "xxxxxxxxxxxxxxxxxxxxxxxxxx\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"; +const ASCII: &str = + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\\ + \nyyyyyyyyyyyy";