Introduce DisplayRow, MultiBufferRow newtypes and BufferRow type alias (#11656)

Part of https://github.com/zed-industries/zed/issues/8081

To avoid confusion and bugs when converting between various row `u32`'s,
use different types for each.
Further PRs should split `Point` into buffer and multi buffer variants
and make the code more readable.

Release Notes:

- N/A

---------

Co-authored-by: Piotr <piotr@zed.dev>
This commit is contained in:
Kirill Bulatov 2024-05-11 00:06:51 +03:00 committed by GitHub
parent 38f110852f
commit df41435d1a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
46 changed files with 1726 additions and 1220 deletions

View file

@ -1,13 +1,14 @@
use editor::{
display_map::{DisplaySnapshot, FoldPoint, ToDisplayPoint},
display_map::{DisplayRow, DisplaySnapshot, FoldPoint, ToDisplayPoint},
movement::{
self, find_boundary, find_preceding_boundary_display_point, FindRange, TextLayoutDetails,
},
scroll::Autoscroll,
Anchor, Bias, DisplayPoint, ToOffset,
Anchor, Bias, DisplayPoint, RowExt, ToOffset,
};
use gpui::{actions, impl_actions, px, ViewContext, WindowContext};
use language::{char_kind, CharKind, Point, Selection, SelectionGoal};
use multi_buffer::MultiBufferRow;
use serde::Deserialize;
use std::ops::Range;
use workspace::Workspace;
@ -843,7 +844,7 @@ impl Motion {
selection.end = map.clip_point(selection.end, Bias::Right);
// Don't reset the end here
return Some(selection.start..selection.end);
} else if selection.start.row() > 0 {
} else if selection.start.row().0 > 0 {
*selection.start.row_mut() -= 1;
*selection.start.column_mut() = map.line_len(selection.start.row());
selection.start = map.clip_point(selection.start, Bias::Left);
@ -860,10 +861,10 @@ impl Motion {
ignore_punctuation: _,
} = self
{
let start_row = selection.start.to_point(&map).row;
if selection.end.to_point(&map).row > start_row {
let start_row = MultiBufferRow(selection.start.to_point(&map).row);
if selection.end.to_point(&map).row > start_row.0 {
selection.end =
Point::new(start_row, map.buffer_snapshot.line_len(start_row))
Point::new(start_row.0, map.buffer_snapshot.line_len(start_row))
.to_display_point(&map)
}
}
@ -997,7 +998,7 @@ fn up_down_buffer_rows(
map.fold_snapshot
.clip_point(FoldPoint::new(start.row(), 0), Bias::Left),
);
let select_nth_wrapped_row = point.row() - begin_folded_line.row();
let select_nth_wrapped_row = point.row().0 - begin_folded_line.row().0;
let (goal_wrap, goal_x) = match goal {
SelectionGoal::WrappedHorizontalPosition((row, x)) => (row, x),
@ -1020,7 +1021,7 @@ fn up_down_buffer_rows(
let mut i = 0;
while i < goal_wrap && begin_folded_line.row() < map.max_point().row() {
let next_folded_line = DisplayPoint::new(begin_folded_line.row() + 1, 0);
let next_folded_line = DisplayPoint::new(begin_folded_line.row().next_row(), 0);
if map
.display_point_to_fold_point(next_folded_line, Bias::Right)
.row()
@ -1215,7 +1216,7 @@ fn previous_word_end(
let scope = map.buffer_snapshot.language_scope_at(point.to_point(map));
let mut point = point.to_point(map);
if point.column < map.buffer_snapshot.line_len(point.row) {
if point.column < map.buffer_snapshot.line_len(MultiBufferRow(point.row)) {
point.column += 1;
}
for _ in 0..times {
@ -1375,7 +1376,7 @@ fn previous_subword_end(
let scope = map.buffer_snapshot.language_scope_at(point.to_point(map));
let mut point = point.to_point(map);
if point.column < map.buffer_snapshot.line_len(point.row) {
if point.column < map.buffer_snapshot.line_len(MultiBufferRow(point.row)) {
point.column += 1;
}
for _ in 0..times {
@ -1497,7 +1498,7 @@ fn end_of_document(
let new_row = if let Some(line) = line {
(line - 1) as u32
} else {
map.max_buffer_row()
map.max_buffer_row().0
};
let new_point = Point::new(new_row, point.column());
@ -1672,22 +1673,24 @@ fn window_top(
.anchor
.to_display_point(map);
if first_visible_line.row() != 0 && text_layout_details.vertical_scroll_margin as usize > times
if first_visible_line.row() != DisplayRow(0)
&& text_layout_details.vertical_scroll_margin as usize > times
{
times = text_layout_details.vertical_scroll_margin.ceil() as usize;
}
if let Some(visible_rows) = text_layout_details.visible_rows {
let bottom_row = first_visible_line.row() + visible_rows as u32;
let new_row = (first_visible_line.row() + (times as u32))
let bottom_row = first_visible_line.row().0 + visible_rows as u32;
let new_row = (first_visible_line.row().0 + (times as u32))
.min(bottom_row)
.min(map.max_point().row());
.min(map.max_point().row().0);
let new_col = point.column().min(map.line_len(first_visible_line.row()));
let new_point = DisplayPoint::new(new_row, new_col);
let new_point = DisplayPoint::new(DisplayRow(new_row), new_col);
(map.clip_point(new_point, Bias::Left), SelectionGoal::None)
} else {
let new_row = (first_visible_line.row() + (times as u32)).min(map.max_point().row());
let new_row =
DisplayRow((first_visible_line.row().0 + (times as u32)).min(map.max_point().row().0));
let new_col = point.column().min(map.line_len(first_visible_line.row()));
let new_point = DisplayPoint::new(new_row, new_col);
@ -1707,10 +1710,11 @@ fn window_middle(
.to_display_point(map);
let max_visible_rows =
(visible_rows as u32).min(map.max_point().row() - first_visible_line.row());
(visible_rows as u32).min(map.max_point().row().0 - first_visible_line.row().0);
let new_row =
(first_visible_line.row() + (max_visible_rows / 2)).min(map.max_point().row());
(first_visible_line.row().0 + (max_visible_rows / 2)).min(map.max_point().row().0);
let new_row = DisplayRow(new_row);
let new_col = point.column().min(map.line_len(new_row));
let new_point = DisplayPoint::new(new_row, new_col);
(map.clip_point(new_point, Bias::Left), SelectionGoal::None)
@ -1730,18 +1734,19 @@ fn window_bottom(
.scroll_anchor
.anchor
.to_display_point(map);
let bottom_row = first_visible_line.row()
let bottom_row = first_visible_line.row().0
+ (visible_rows + text_layout_details.scroll_anchor.offset.y - 1.).floor() as u32;
if bottom_row < map.max_point().row()
if bottom_row < map.max_point().row().0
&& text_layout_details.vertical_scroll_margin as usize > times
{
times = text_layout_details.vertical_scroll_margin.ceil() as usize;
}
let bottom_row_capped = bottom_row.min(map.max_point().row());
let new_row = if bottom_row_capped.saturating_sub(times as u32) < first_visible_line.row() {
let bottom_row_capped = bottom_row.min(map.max_point().row().0);
let new_row = if bottom_row_capped.saturating_sub(times as u32) < first_visible_line.row().0
{
first_visible_line.row()
} else {
bottom_row_capped.saturating_sub(times as u32)
DisplayRow(bottom_row_capped.saturating_sub(times as u32))
};
let new_col = point.column().min(map.line_len(new_row));
let new_point = DisplayPoint::new(new_row, new_col);