From ccf4252a738ccfeb91be871800c9c132c49fa528 Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Tue, 3 Nov 2026 22:10:14 -0800 Subject: [PATCH] Type: typing a list's start in a continued paragraph starts no list In a threaded frame whose first paragraph continues from the frame before, the text at the frame's start is not the start of a paragraph, and the frame draws no list marker for it. Typing "* " or "1. " there removed the characters and set a list that never showed. typed_list_at now returns None for that paragraph. --- crates/doc/src/text/object.rs | 6 ++++-- crates/doc/src/text/tests.rs | 13 +++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/crates/doc/src/text/object.rs b/crates/doc/src/text/object.rs index c6a22a29c..70e953922 100644 --- a/crates/doc/src/text/object.rs +++ b/crates/doc/src/text/object.rs @@ -200,14 +200,16 @@ impl TextObject { } /// The list that the characters before byte `at` start ([`ParaList::typed`]) with the byte /// where their paragraph starts: when the plain text from the start of the paragraph up to - /// `at` is a list's start followed by a space, and the paragraph is in no list. None otherwise. + /// `at` is a list's start followed by a space, and the paragraph is in no list. None otherwise, + /// and for a first paragraph that continues from the frame before + /// ([`TextObject::first_para_continues`]). pub fn typed_list_at(&self, at: usize) -> Option<(usize, ParaList)> { let text = self.plain_text(); let before = text.get(..at)?; let start = before.rfind('\n').map_or(0, |i| i + 1); let list = ParaList::typed(before[start..].strip_suffix(' ')?)?; let index = before.bytes().filter(|&b| b == b'\n').count(); - self.para_at(index).list.is_none().then_some((start, list)) + (!(index == 0 && self.first_para_continues) && self.para_at(index).list.is_none()).then_some((start, list)) } /// Apply `f` to the attributes of paragraphs `range` (indices; None = every paragraph). pub fn edit_paras(&mut self, range: Option>, mut f: impl FnMut(&mut ParaStyle)) { diff --git a/crates/doc/src/text/tests.rs b/crates/doc/src/text/tests.rs index 04deae8ee..2a47ee453 100644 --- a/crates/doc/src/text/tests.rs +++ b/crates/doc/src/text/tests.rs @@ -239,6 +239,19 @@ fn typed_list_starts_are_found_at_a_paragraphs_start() { assert_eq!(t.typed_list_at(19), Some((16, letters))); } +/// In a threaded frame whose first paragraph continues from the frame before, the text at the +/// frame's start is not the start of a paragraph, so typing a list's start there starts nothing. +/// The paragraphs after it still start lists. +#[test] +fn typed_list_starts_skip_a_continued_paragraph() { + let dot = ParaList::bulleted(Bullet::Dot); + let mut t = TextObject::point(Point::ZERO, "* Pears\n# ", CharStyle::default()); + assert_eq!(t.typed_list_at(2), Some((0, dot))); + t.first_para_continues = true; + assert_eq!(t.typed_list_at(2), None, "a continued paragraph starts no list"); + assert_eq!(t.typed_list_at(10), Some((8, dot))); +} + #[test] fn character_controls_reject_collapsed_and_nonfinite_transforms() { let mut t = TextObject::point(Point::ZERO, "Text", CharStyle::default());