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
This commit is contained in:
3 files changed
+46
-10
No files matched your search
+25
-9
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in new issue
Block a user