Fix Paragraph::sentence_at at the first character of a sentence (#3105)

* Fix Paragraph::sentence_at at the first character of a sentence

Found while testing crates/doc/src/para.rs:1397-1427

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* sentence_at: a terminator followed directly by text doesn't end the sentence at the caret

"Hello.World" at offset 6 gave an empty (6,6) range; only treat the caret as just past a
sentence end when the character at the caret is a space.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
NetterSilver
2026-10-19 12:45:25 -04:00
committed by GitHub
co-authored by Claude Opus 5.5 Brandon Thomas
parent e8866ea58b
commit 2304bf6ac6
+17 -2
View File
@@ -1400,7 +1400,7 @@ impl Paragraph {
let mut a = 0;
let mut prev_end = false;
for (i, c) in t.char_indices() {
if i >= off {
if i > off {
break;
}
if prev_end && c != ' ' {
@@ -1413,7 +1413,9 @@ impl Paragraph {
}
}
let mut b = t.len();
let mut ended = false;
// A caret on the space right after a sentence's end belongs to that sentence; a terminator
// directly followed by text ("Hello.World") doesn't end the sentence the caret is in.
let mut ended = t.get(..off).unwrap_or("").ends_with(['.', '!', '?']) && t.get(off..).unwrap_or("").starts_with(' ');
for (i, c) in t.get(off..).unwrap_or("").char_indices() {
if ended && c != ' ' {
b = off + i;
@@ -1431,6 +1433,19 @@ impl Paragraph {
mod tests {
use super::*;
#[test]
fn sentence_at_sentence_start() {
let p = Paragraph::with_text("Hello. World", CharProps::default());
assert_eq!(p.sentence_at(0), (0, 7));
assert_eq!(p.sentence_at(6), (0, 7));
assert_eq!(p.sentence_at(7), (7, 12));
assert_eq!(p.sentence_at(8), (7, 12));
assert_eq!(p.sentence_at(99), (7, 12));
let p = Paragraph::with_text("Hello.World", CharProps::default());
assert_eq!(p.sentence_at(6), (6, 11));
assert_eq!(p.sentence_at(8), (6, 11));
}
fn bold() -> CharProps {
CharProps { bold: Some(true), ..Default::default() }
}