Ensure BlockMap::clip_point always yield a valid buffer location

This commit is contained in:
Antonio Scandurra
2021-12-16 12:29:37 +01:00
parent ec39c9d335
commit 64e2f6d506
2 changed files with 55 additions and 19 deletions
+47 -19
View File
@@ -581,37 +581,45 @@ impl BlockSnapshot {
cursor.seek(&BlockRow(point.row), Bias::Right, &());
let max_input_row = WrapRow(self.transforms.summary().input_rows);
let search_left =
let mut search_left =
(bias == Bias::Left && cursor.start().1 .0 > 0) || cursor.end(&()).1 == max_input_row;
let mut reversed = false;
loop {
if let Some(transform) = cursor.item() {
if transform.is_isomorphic() {
let (output_start_row, input_start_row) = cursor.start();
let (output_end_row, input_end_row) = cursor.end(&());
if point.row >= output_end_row.0 {
return BlockPoint::new(
output_end_row.0 - 1,
self.wrap_snapshot.line_len(input_end_row.0 - 1),
);
}
let output_start = Point::new(output_start_row.0, 0);
let output_overshoot = point.0 - output_start;
let input_start = Point::new(input_start_row.0, 0);
let input_point = self
.wrap_snapshot
.clip_point(WrapPoint(input_start + output_overshoot), bias);
let input_overshoot = input_point.0 - input_start;
return BlockPoint(output_start + input_overshoot);
} else if search_left {
let input_end = Point::new(input_end_row.0, 0);
let input_point = if point.row >= output_end_row.0 {
let line_len = self.wrap_snapshot.line_len(input_end_row.0 - 1);
self.wrap_snapshot
.clip_point(WrapPoint::new(input_end_row.0 - 1, line_len), bias)
} else {
let output_overshoot = point.0.saturating_sub(output_start);
self.wrap_snapshot
.clip_point(WrapPoint(input_start + output_overshoot), bias)
};
if (input_start..input_end).contains(&input_point.0) {
let input_overshoot = input_point.0.saturating_sub(input_start);
return BlockPoint(output_start + input_overshoot);
}
}
if search_left {
cursor.prev(&());
} else {
cursor.next(&());
}
} else {
} else if reversed {
return self.max_point();
} else {
reversed = true;
search_left = !search_left;
cursor.seek(&BlockRow(point.row), Bias::Right, &());
}
}
}
@@ -1368,16 +1376,30 @@ mod tests {
let mut block_point = BlockPoint::new(0, 0);
for c in expected_text.chars() {
let left_point = blocks_snapshot.clip_point(block_point, Bias::Left);
let right_point = blocks_snapshot.clip_point(block_point, Bias::Right);
let left_buffer_point = blocks_snapshot.to_point(left_point, Bias::Left);
assert_eq!(
blocks_snapshot.to_block_point(blocks_snapshot.to_wrap_point(left_point)),
left_point
);
assert_eq!(
left_buffer_point,
buffer_snapshot.clip_point(left_buffer_point, Bias::Right),
"{:?} is not valid in buffer coordinates",
left_point
);
let right_point = blocks_snapshot.clip_point(block_point, Bias::Right);
let right_buffer_point = blocks_snapshot.to_point(right_point, Bias::Right);
assert_eq!(
blocks_snapshot.to_block_point(blocks_snapshot.to_wrap_point(right_point)),
right_point
);
assert_eq!(
right_buffer_point,
buffer_snapshot.clip_point(right_buffer_point, Bias::Left),
"{:?} is not valid in buffer coordinates",
right_point
);
if c == '\n' {
block_point.0 += Point::new(1, 0);
@@ -1387,4 +1409,10 @@ mod tests {
}
}
}
impl BlockSnapshot {
fn to_point(&self, point: BlockPoint, bias: Bias) -> Point {
self.wrap_snapshot.to_point(self.to_wrap_point(point), bias)
}
}
}
+8
View File
@@ -35,6 +35,14 @@ impl Point {
pub fn is_zero(&self) -> bool {
self.row == 0 && self.column == 0
}
pub fn saturating_sub(self, other: Self) -> Self {
if self < other {
Point::zero()
} else {
self - other
}
}
}
impl<'a> Add<&'a Self> for Point {