editor: Preserve non-breaking whitespace during rewrap (#59893)
## Objective Prevent rewrap from breaking at whitespace that Unicode classifies as non-breaking. The original approach, prompted by #59664, treated every non-ASCII whitespace character as unbreakable. Unicode classifies `U+2009 THIN SPACE` as breakable and `U+202F NARROW NO-BREAK SPACE` as its non-breaking counterpart. ## Solution - Treat `U+00A0 NO-BREAK SPACE`, `U+2007 FIGURE SPACE`, and `U+202F NARROW NO-BREAK SPACE` as part of the surrounding word - Keep thin spaces, em spaces, and other Unicode breaking spaces as line-break opportunities - Cover all three non-breaking whitespace variants in tokenizer and wrapping tests ## Testing - `cargo test -p editor rewrap::tests` Release Notes: - Fixed rewrap breaking lines at non-breaking spaces. --------- Co-authored-by: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
1 parent
af01c321fa
commit
9dfdaa62b7
1 file changed
+37
-2
@@ -430,8 +430,13 @@ fn is_grapheme_ideographic(text: &str) -> bool {
|
||||
text.chars().any(is_char_ideographic)
|
||||
}
|
||||
|
||||
fn is_non_breaking_whitespace(character: char) -> bool {
|
||||
matches!(character, '\u{00A0}' | '\u{2007}' | '\u{202F}')
|
||||
}
|
||||
|
||||
fn is_grapheme_whitespace(text: &str) -> bool {
|
||||
text.chars().any(|x| x.is_whitespace())
|
||||
text.chars()
|
||||
.any(|character| character.is_whitespace() && !is_non_breaking_whitespace(character))
|
||||
}
|
||||
|
||||
fn should_stay_with_preceding_ideograph(text: &str) -> bool {
|
||||
@@ -690,7 +695,23 @@ mod tests {
|
||||
word("笔", 1),
|
||||
],
|
||||
),
|
||||
(" mutton", &[whitespace(" ", 1), word("mutton", 6)]),
|
||||
(
|
||||
"\u{2003}mutton",
|
||||
&[whitespace("\u{2003}", 1), word("mutton", 6)],
|
||||
),
|
||||
(
|
||||
"a\u{2009}b\u{2009}c",
|
||||
&[
|
||||
word("a", 1),
|
||||
whitespace("\u{2009}", 1),
|
||||
word("b", 1),
|
||||
whitespace("\u{2009}", 1),
|
||||
word("c", 1),
|
||||
],
|
||||
),
|
||||
("a\u{a0}b\u{a0}c", &[word("a\u{a0}b\u{a0}c", 5)]),
|
||||
("a\u{2007}b\u{2007}c", &[word("a\u{2007}b\u{2007}c", 5)]),
|
||||
("a\u{202f}b\u{202f}c", &[word("a\u{202f}b\u{202f}c", 5)]),
|
||||
];
|
||||
|
||||
fn word(token: &'static str, grapheme_len: usize) -> WordBreakToken<'static> {
|
||||
@@ -778,5 +799,19 @@ mod tests {
|
||||
),
|
||||
format!("foo{}bar", '\u{2009}')
|
||||
);
|
||||
for non_breaking_space in ['\u{a0}', '\u{2007}', '\u{202f}'] {
|
||||
let input = format!("a{0}a{0}a{0}a{0}a", non_breaking_space);
|
||||
assert_eq!(
|
||||
wrap_with_prefix(
|
||||
String::new(),
|
||||
String::new(),
|
||||
input.clone(),
|
||||
4,
|
||||
NonZeroU32::new(4).unwrap(),
|
||||
false,
|
||||
),
|
||||
input
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user