T10: a match whose line is kept, grown or cut stays current when held under the same line above or in its place, before a twin line elsewhere
CI / platforms (windows-latest) (push) Failing after 10s
CI / macos (push) Failing after 8m52s
CI / platforms (ubuntu-24.04) (push) Canceled after 0s

This commit is contained in:
ZacharyZhang-NY committed 2026-10-14 17:43:36 -04:00
1 parent 11b2ce6f34
commit 39761d9f40
3 files changed
+46 -10

No files matched your search

+25 -9
View File
@@ -192,11 +192,21 @@ impl Found {
start..self.breaks.get(ends).copied().unwrap_or(self.text.len())
}
/// The match that was `then`'s `at`: at its place in its line, kept, grown or cut; else the nearest.
/// The text of the line before `line`, if one is.
fn above(&self, line: &Range<usize>) -> Option<&str> {
let end = line.start.checked_sub(1)?;
Some(&self.text[self.line(end)])
}
/// The match that was `then`'s `at`: its line kept, grown or cut, held under the same line or in place; else the nearest.
fn follow(&self, then: &Found, at: usize) -> Option<usize> {
let was = then.bytes[at].start;
let line = then.line(was);
let (whole, offset) = (&then.text[line.clone()], was - line.start);
let (whole, offset, above) = (
&then.text[line.clone()],
was - line.start,
then.above(&line),
);
let place = *then.hits[at].start();
let grew = self.history as i32 - then.history as i32;
// A cleared or trimmed history moves no line; a resize pulls lines back down.
@@ -209,16 +219,22 @@ impl Found {
for (index, bytes) in self.bytes.iter().enumerate() {
let line = self.line(bytes.start);
let now = &self.text[line.clone()];
let rank = match bytes.start - line.start == offset {
true if now == whole => 0,
true if now.starts_with(whole) || whole.starts_with(now) => 1,
_ => 2,
let kin = match bytes.start - line.start == offset {
true if now == whole => Some(0),
true if now.starts_with(whole) || whole.starts_with(now) => Some(1),
_ => None,
};
let start = self.hits[index].start();
let away = (start.line.0 + scrolled - place.line.0).abs();
let key = (rank, away, start.column.0.abs_diff(place.column.0));
if best.is_none_or(|(least, _)| key < least) {
best = Some((key, index));
let column = start.column.0.abs_diff(place.column.0);
let held = kin.is_some() && ((away, column) == (0, 0) || self.above(&line) == above);
let rank = match kin {
Some(kin) if held => kin,
Some(kin) => 2 + kin,
None => 4,
};
if best.is_none_or(|(least, _)| (rank, away, column) < least) {
best = Some(((rank, away, column), index));
}
}
best.map(|(_, index)| index)
+20
View File
@@ -194,6 +194,26 @@ fn a_line_that_grows_or_changes_keeps_the_match_at_its_place() {
"needle 6 itself before needle 60 in its place"
);
let mut twins = term("needle\r\nneedle", 20, 3, 10);
let then = found(&twins, "needle", PLAIN);
feed(&mut twins, "!");
let now = found(&twins, "needle", PLAIN);
assert_eq!(
now.follow(&then, 1),
Some(1),
"the grown line, not its twin above"
);
let mut rewritten = term("needle\r\nA\r\nneedle", 20, 4, 10);
let then = found(&rewritten, "needle", PLAIN);
feed(&mut rewritten, "\x1b[2;1HB\x1b[3;7H!");
let now = found(&rewritten, "needle", PLAIN);
assert_eq!(
now.follow(&then, 1),
Some(1),
"grown in its place, though the line above changed"
);
let mut changed = term("needle A needle B", 30, 3, 10);
let then = found(&changed, "needle", PLAIN);
feed(&mut changed, "\rneedle X needle Y");