From 05f8a61bc89d80674acb0774bdc5e8f3fe0fa90e Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 28 Jul 2021 15:08:24 -0700 Subject: [PATCH] Add a bias parameter when converting buffer points to fold points --- zed/src/editor.rs | 62 ++++++++++++++------------ zed/src/editor/buffer/selection.rs | 8 ++-- zed/src/editor/display_map.rs | 46 ++++++++++--------- zed/src/editor/display_map/fold_map.rs | 30 +++++++++---- 4 files changed, 83 insertions(+), 63 deletions(-) diff --git a/zed/src/editor.rs b/zed/src/editor.rs index 20f3b12ce3430a2847653ee9a1beda29941d5411..9d33c04ace642bfd3bb08c2e589b9215a736fbb3 100644 --- a/zed/src/editor.rs +++ b/zed/src/editor.rs @@ -528,14 +528,14 @@ impl Editor { .first() .unwrap() .head() - .to_display_point(&display_map) + .to_display_point(&display_map, Bias::Left) .row() as f32; let last_cursor_bottom = self .selections(cx) .last() .unwrap() .head() - .to_display_point(&display_map) + .to_display_point(&display_map, Bias::Right) .row() as f32 + 1.0; @@ -575,7 +575,7 @@ impl Editor { let mut target_left = std::f32::INFINITY; let mut target_right = 0.0_f32; for selection in self.selections(cx) { - let head = selection.head().to_display_point(&display_map); + let head = selection.head().to_display_point(&display_map, Bias::Left); let start_column = head.column().saturating_sub(3); let end_column = cmp::min(display_map.line_len(head.row()), head.column() + 3); target_left = target_left @@ -806,7 +806,7 @@ impl Editor { for selection in &mut selections { let range = selection.point_range(buffer); if range.start == range.end { - let head = selection.head().to_display_point(&display_map); + let head = selection.head().to_display_point(&display_map, Bias::Left); let cursor = display_map .anchor_before(movement::left(&display_map, head).unwrap(), Bias::Left); selection.set_head(&buffer, cursor); @@ -829,7 +829,7 @@ impl Editor { for selection in &mut selections { let range = selection.point_range(buffer); if range.start == range.end { - let head = selection.head().to_display_point(&display_map); + let head = selection.head().to_display_point(&display_map, Bias::Left); let cursor = display_map .anchor_before(movement::right(&display_map, head).unwrap(), Bias::Right); selection.set_head(&buffer, cursor); @@ -856,7 +856,10 @@ impl Editor { let mut selections = self.selections(app).iter().peekable(); while let Some(selection) = selections.next() { let (mut rows, _) = selection.buffer_rows_for_display_rows(false, &display_map); - let goal_display_column = selection.head().to_display_point(&display_map).column(); + let goal_display_column = selection + .head() + .to_display_point(&display_map, Bias::Left) + .column(); // Accumulate contiguous regions of rows that we want to delete. while let Some(next_selection) = selections.peek() { @@ -886,7 +889,8 @@ impl Editor { cursor_buffer_row = rows.start.saturating_sub(1); } - let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map); + let mut cursor = + Point::new(cursor_buffer_row, 0).to_display_point(&display_map, Bias::Left); *cursor.column_mut() = cmp::min(goal_display_column, display_map.line_len(cursor.row())); @@ -1286,8 +1290,8 @@ impl Editor { let mut selections = self.selections(app).to_vec(); { for selection in &mut selections { - let start = selection.start.to_display_point(&display_map); - let end = selection.end.to_display_point(&display_map); + let start = selection.start.to_display_point(&display_map, Bias::Left); + let end = selection.end.to_display_point(&display_map, Bias::Left); if start != end { selection.end = selection.start.clone(); @@ -1310,7 +1314,7 @@ impl Editor { { let buffer = self.buffer.read(cx); for selection in &mut selections { - let head = selection.head().to_display_point(&display_map); + let head = selection.head().to_display_point(&display_map, Bias::Left); let cursor = display_map .anchor_before(movement::left(&display_map, head).unwrap(), Bias::Left); selection.set_head(&buffer, cursor); @@ -1325,8 +1329,8 @@ impl Editor { let mut selections = self.selections(cx.as_ref()).to_vec(); { for selection in &mut selections { - let start = selection.start.to_display_point(&display_map); - let end = selection.end.to_display_point(&display_map); + let start = selection.start.to_display_point(&display_map, Bias::Left); + let end = selection.end.to_display_point(&display_map, Bias::Left); if start != end { selection.start = selection.end.clone(); @@ -1350,7 +1354,7 @@ impl Editor { let app = cx.as_ref(); let buffer = self.buffer.read(app); for selection in &mut selections { - let head = selection.head().to_display_point(&display_map); + let head = selection.head().to_display_point(&display_map, Bias::Left); let cursor = display_map .anchor_before(movement::right(&display_map, head).unwrap(), Bias::Right); selection.set_head(&buffer, cursor); @@ -1368,8 +1372,8 @@ impl Editor { let mut selections = self.selections(cx.as_ref()).to_vec(); { for selection in &mut selections { - let start = selection.start.to_display_point(&display_map); - let end = selection.end.to_display_point(&display_map); + let start = selection.start.to_display_point(&display_map, Bias::Left); + let end = selection.end.to_display_point(&display_map, Bias::Left); if start != end { selection.goal = SelectionGoal::None; } @@ -1393,7 +1397,7 @@ impl Editor { let app = cx.as_ref(); let buffer = self.buffer.read(app); for selection in &mut selections { - let head = selection.head().to_display_point(&display_map); + let head = selection.head().to_display_point(&display_map, Bias::Left); let (head, goal) = movement::up(&display_map, head, selection.goal).unwrap(); selection.set_head(&buffer, display_map.anchor_before(head, Bias::Left)); selection.goal = goal; @@ -1410,8 +1414,8 @@ impl Editor { let mut selections = self.selections(cx.as_ref()).to_vec(); { for selection in &mut selections { - let start = selection.start.to_display_point(&display_map); - let end = selection.end.to_display_point(&display_map); + let start = selection.start.to_display_point(&display_map, Bias::Left); + let end = selection.end.to_display_point(&display_map, Bias::Left); if start != end { selection.goal = SelectionGoal::None; } @@ -1435,7 +1439,7 @@ impl Editor { let app = cx.as_ref(); let buffer = self.buffer.read(app); for selection in &mut selections { - let head = selection.head().to_display_point(&display_map); + let head = selection.head().to_display_point(&display_map, Bias::Left); let (head, goal) = movement::down(&display_map, head, selection.goal).unwrap(); selection.set_head(&buffer, display_map.anchor_before(head, Bias::Right)); selection.goal = goal; @@ -1449,7 +1453,7 @@ impl Editor { let mut selections = self.selections(cx).to_vec(); { for selection in &mut selections { - let head = selection.head().to_display_point(&display_map); + let head = selection.head().to_display_point(&display_map, Bias::Left); let new_head = movement::prev_word_boundary(&display_map, head).unwrap(); let anchor = display_map.anchor_before(new_head, Bias::Left); selection.start = anchor.clone(); @@ -1467,7 +1471,7 @@ impl Editor { { let buffer = self.buffer.read(cx); for selection in &mut selections { - let head = selection.head().to_display_point(&display_map); + let head = selection.head().to_display_point(&display_map, Bias::Left); let new_head = movement::prev_word_boundary(&display_map, head).unwrap(); let anchor = display_map.anchor_before(new_head, Bias::Left); selection.set_head(buffer, anchor); @@ -1489,7 +1493,7 @@ impl Editor { let mut selections = self.selections(cx).to_vec(); { for selection in &mut selections { - let head = selection.head().to_display_point(&display_map); + let head = selection.head().to_display_point(&display_map, Bias::Left); let new_head = movement::next_word_boundary(&display_map, head).unwrap(); let anchor = display_map.anchor_before(new_head, Bias::Left); selection.start = anchor.clone(); @@ -1507,7 +1511,7 @@ impl Editor { { let buffer = self.buffer.read(cx); for selection in &mut selections { - let head = selection.head().to_display_point(&display_map); + let head = selection.head().to_display_point(&display_map, Bias::Left); let new_head = movement::next_word_boundary(&display_map, head).unwrap(); let anchor = display_map.anchor_before(new_head, Bias::Left); selection.set_head(buffer, anchor); @@ -1529,7 +1533,7 @@ impl Editor { let mut selections = self.selections(cx).to_vec(); { for selection in &mut selections { - let head = selection.head().to_display_point(&display_map); + let head = selection.head().to_display_point(&display_map, Bias::Left); let new_head = movement::line_beginning(&display_map, head, true).unwrap(); let anchor = display_map.anchor_before(new_head, Bias::Left); selection.start = anchor.clone(); @@ -1551,7 +1555,7 @@ impl Editor { { let buffer = self.buffer.read(cx); for selection in &mut selections { - let head = selection.head().to_display_point(&display_map); + let head = selection.head().to_display_point(&display_map, Bias::Left); let new_head = movement::line_beginning(&display_map, head, *toggle_indent).unwrap(); let anchor = display_map.anchor_before(new_head, Bias::Left); @@ -1574,7 +1578,7 @@ impl Editor { let mut selections = self.selections(cx).to_vec(); { for selection in &mut selections { - let head = selection.head().to_display_point(&display_map); + let head = selection.head().to_display_point(&display_map, Bias::Left); let new_head = movement::line_end(&display_map, head).unwrap(); let anchor = display_map.anchor_before(new_head, Bias::Left); selection.start = anchor.clone(); @@ -1592,7 +1596,7 @@ impl Editor { { let buffer = self.buffer.read(cx); for selection in &mut selections { - let head = selection.head().to_display_point(&display_map); + let head = selection.head().to_display_point(&display_map, Bias::Left); let new_head = movement::line_end(&display_map, head).unwrap(); let anchor = display_map.anchor_before(new_head, Bias::Left); selection.set_head(buffer, anchor); @@ -2480,7 +2484,9 @@ fn compute_scroll_position( mut scroll_position: Vector2F, scroll_top_anchor: &Anchor, ) -> Vector2F { - let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32; + let scroll_top = scroll_top_anchor + .to_display_point(snapshot, Bias::Left) + .row() as f32; scroll_position.set_y(scroll_top + scroll_position.y()); scroll_position } diff --git a/zed/src/editor/buffer/selection.rs b/zed/src/editor/buffer/selection.rs index 3fe057d5910baa7db3fb1084270bb2e45a1a310d..061d6091e6d05e6dd49415b67cc4a2af7d748108 100644 --- a/zed/src/editor/buffer/selection.rs +++ b/zed/src/editor/buffer/selection.rs @@ -80,8 +80,8 @@ impl Selection { } pub fn display_range(&self, map: &DisplayMapSnapshot) -> Range { - let start = self.start.to_display_point(map); - let end = self.end.to_display_point(map); + let start = self.start.to_display_point(map, Bias::Left); + let end = self.end.to_display_point(map, Bias::Left); if self.reversed { end..start } else { @@ -94,11 +94,11 @@ impl Selection { include_end_if_at_line_start: bool, map: &DisplayMapSnapshot, ) -> (Range, Range) { - let display_start = self.start.to_display_point(map); + let display_start = self.start.to_display_point(map, Bias::Left); let buffer_start = DisplayPoint::new(display_start.row(), 0).to_buffer_point(map, Bias::Left); - let mut display_end = self.end.to_display_point(map); + let mut display_end = self.end.to_display_point(map, Bias::Right); if !include_end_if_at_line_start && display_end.row() != map.max_point().row() && display_start.row() != display_end.row() diff --git a/zed/src/editor/display_map.rs b/zed/src/editor/display_map.rs index c8d896b0436ce489289812a3e62958d976931150..af22e50d836a728c1061e6241ccb2b2cbefe76d1 100644 --- a/zed/src/editor/display_map.rs +++ b/zed/src/editor/display_map.rs @@ -117,24 +117,25 @@ impl DisplayMapSnapshot { let mut point = display_point.to_buffer_point(self, Bias::Left); while point.column != 0 { point.column = 0; - display_point = point.to_display_point(self); + display_point = point.to_display_point(self, Bias::Left); if display_point.column() != 0 { *display_point.column_mut() = 0; - point = display_point.to_buffer_point(self, Bias::Left); } + point = display_point.to_buffer_point(self, Bias::Left); } (display_point, point) } pub fn next_row_boundary(&self, mut display_point: DisplayPoint) -> (DisplayPoint, Point) { + let max_point = self.max_point(); *display_point.row_mut() += 1; *display_point.column_mut() = 0; let mut point = display_point.to_buffer_point(self, Bias::Right); - while point.column != 0 { + while point.column != 0 && display_point <= max_point { point.column = 0; point.row += 1; - display_point = point.to_display_point(self); + display_point = point.to_display_point(self, Bias::Right); if display_point.column() != 0 { *display_point.row_mut() += 1; *display_point.column_mut() = 0; @@ -142,7 +143,7 @@ impl DisplayMapSnapshot { } } - (display_point, point) + (display_point.min(max_point), point) } pub fn max_point(&self) -> DisplayPoint { @@ -307,8 +308,8 @@ impl DisplayPoint { } impl Point { - pub fn to_display_point(self, map: &DisplayMapSnapshot) -> DisplayPoint { - let fold_point = self.to_fold_point(&map.folds_snapshot); + pub fn to_display_point(self, map: &DisplayMapSnapshot, bias: Bias) -> DisplayPoint { + let fold_point = self.to_fold_point(&map.folds_snapshot, bias); let tab_point = map.tabs_snapshot.to_tab_point(fold_point); let wrap_point = map.wraps_snapshot.to_wrap_point(tab_point); DisplayPoint(wrap_point) @@ -316,8 +317,9 @@ impl Point { } impl Anchor { - pub fn to_display_point(&self, map: &DisplayMapSnapshot) -> DisplayPoint { - self.to_point(&map.buffer_snapshot).to_display_point(map) + pub fn to_display_point(&self, map: &DisplayMapSnapshot, bias: Bias) -> DisplayPoint { + self.to_point(&map.buffer_snapshot) + .to_display_point(map, bias) } } @@ -435,13 +437,13 @@ mod tests { } assert_eq!( - prev_buffer_bound.to_display_point(&snapshot), + prev_buffer_bound.to_display_point(&snapshot, Left), prev_display_bound, "{:?} to display point", prev_buffer_bound ); assert_eq!( - next_buffer_bound.to_display_point(&snapshot), + next_buffer_bound.to_display_point(&snapshot, Left), next_display_bound, "{:?} to display point", next_buffer_bound @@ -787,40 +789,40 @@ mod tests { let point = Point::new(0, "✅\t\t".len() as u32); let display_point = DisplayPoint::new(0, "✅ ".len() as u32); - assert_eq!(point.to_display_point(&map), display_point); - assert_eq!(display_point.to_buffer_point(&map, Bias::Left), point,); + assert_eq!(point.to_display_point(&map, Left), display_point); + assert_eq!(display_point.to_buffer_point(&map, Left), point,); let point = Point::new(1, "β\t".len() as u32); let display_point = DisplayPoint::new(1, "β ".len() as u32); - assert_eq!(point.to_display_point(&map), display_point); - assert_eq!(display_point.to_buffer_point(&map, Bias::Left), point,); + assert_eq!(point.to_display_point(&map, Left), display_point); + assert_eq!(display_point.to_buffer_point(&map, Left), point,); let point = Point::new(2, "🏀β\t\t".len() as u32); let display_point = DisplayPoint::new(2, "🏀β ".len() as u32); - assert_eq!(point.to_display_point(&map), display_point); - assert_eq!(display_point.to_buffer_point(&map, Bias::Left), point,); + assert_eq!(point.to_display_point(&map, Left), display_point); + assert_eq!(display_point.to_buffer_point(&map, Left), point,); // Display points inside of expanded tabs assert_eq!( - DisplayPoint::new(0, "✅ ".len() as u32).to_buffer_point(&map, Bias::Right), + DisplayPoint::new(0, "✅ ".len() as u32).to_buffer_point(&map, Right), Point::new(0, "✅\t\t".len() as u32), ); assert_eq!( - DisplayPoint::new(0, "✅ ".len() as u32).to_buffer_point(&map, Bias::Left), + DisplayPoint::new(0, "✅ ".len() as u32).to_buffer_point(&map, Left), Point::new(0, "✅\t".len() as u32), ); assert_eq!( - DisplayPoint::new(0, "✅ ".len() as u32).to_buffer_point(&map, Bias::Right), + DisplayPoint::new(0, "✅ ".len() as u32).to_buffer_point(&map, Right), Point::new(0, "✅\t".len() as u32), ); assert_eq!( - DisplayPoint::new(0, "✅ ".len() as u32).to_buffer_point(&map, Bias::Left), + DisplayPoint::new(0, "✅ ".len() as u32).to_buffer_point(&map, Left), Point::new(0, "✅".len() as u32), ); // Clipping display points inside of multi-byte characters assert_eq!( - map.clip_point(DisplayPoint::new(0, "✅".len() as u32 - 1), Bias::Left), + map.clip_point(DisplayPoint::new(0, "✅".len() as u32 - 1), Left), DisplayPoint::new(0, 0) ); assert_eq!( diff --git a/zed/src/editor/display_map/fold_map.rs b/zed/src/editor/display_map/fold_map.rs index 738d48dbb659255670a72572a4a0918db5506003..eb7a58c68b944f756e52b4da856f67f8828ed3ee 100644 --- a/zed/src/editor/display_map/fold_map.rs +++ b/zed/src/editor/display_map/fold_map.rs @@ -77,14 +77,21 @@ impl FoldPoint { } impl Point { - pub fn to_fold_point(&self, snapshot: &Snapshot) -> FoldPoint { + pub fn to_fold_point(&self, snapshot: &Snapshot, bias: Bias) -> FoldPoint { let mut cursor = snapshot.transforms.cursor::(); cursor.seek(self, Bias::Right, &()); - let overshoot = *self - cursor.seek_start(); - FoldPoint(cmp::min( - cursor.sum_start().0 + overshoot, - cursor.sum_end(&()).0, - )) + if cursor.item().map_or(false, |t| t.is_fold()) { + match bias { + Bias::Left => *cursor.sum_start(), + Bias::Right => cursor.sum_end(&()), + } + } else { + let overshoot = *self - cursor.seek_start(); + FoldPoint(cmp::min( + cursor.sum_start().0 + overshoot, + cursor.sum_end(&()).0, + )) + } } } @@ -1365,7 +1372,7 @@ mod tests { let buffer_point = fold_point.to_buffer_point(&snapshot); let buffer_offset = buffer_point.to_offset(&buffer); assert_eq!( - buffer_point.to_fold_point(&snapshot), + buffer_point.to_fold_point(&snapshot, Right), fold_point, "buffer_Point.to_fold_point({:?})", buffer_point, @@ -1413,7 +1420,9 @@ mod tests { } for (idx, buffer_row) in expected_buffer_rows.iter().enumerate() { - let fold_row = Point::new(*buffer_row, 0).to_fold_point(&snapshot).row(); + let fold_row = Point::new(*buffer_row, 0) + .to_fold_point(&snapshot, Right) + .row(); assert_eq!( snapshot.buffer_rows(fold_row).collect::>(), expected_buffer_rows[idx..], @@ -1421,7 +1430,10 @@ mod tests { } for fold_range in map.merged_fold_ranges(cx.as_ref()) { - let fold_point = fold_range.start.to_point(&buffer).to_fold_point(&snapshot); + let fold_point = fold_range + .start + .to_point(&buffer) + .to_fold_point(&snapshot, Right); assert!(snapshot.is_line_folded(fold_point.row())); }