From 5d28fb871fa26af01468b5432d5be5f33b14ff4f Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 28 Apr 2021 11:09:00 +0200 Subject: [PATCH] Extract a `Selection::buffer_row_range` method --- zed/src/editor/buffer/selection.rs | 25 ++++++++++++++- zed/src/editor/buffer_view.rs | 50 ++++++++++++++---------------- 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/zed/src/editor/buffer/selection.rs b/zed/src/editor/buffer/selection.rs index 99c71e0a4426e61ac863729324434b586ab83eb5..514d87394bd7f0e76793da0bc9176dba71bb54c5 100644 --- a/zed/src/editor/buffer/selection.rs +++ b/zed/src/editor/buffer/selection.rs @@ -1,7 +1,7 @@ use crate::{ editor::{ buffer::{Anchor, Buffer, Point, ToPoint}, - display_map::DisplayMap, + display_map::{Bias, DisplayMap}, DisplayPoint, }, time, @@ -72,4 +72,27 @@ impl Selection { start..end } } + + pub fn buffer_row_range(&self, map: &DisplayMap, ctx: &AppContext) -> Range { + let display_start = self.start.to_display_point(map, ctx).unwrap(); + let buffer_start = DisplayPoint::new(display_start.row(), 0) + .to_buffer_point(map, Bias::Left, ctx) + .unwrap(); + + let mut display_end = self.end.to_display_point(map, ctx).unwrap(); + if display_end != map.max_point(ctx) + && display_start.row() != display_end.row() + && display_end.column() == 0 + { + *display_end.row_mut() -= 1; + } + let buffer_end = DisplayPoint::new( + display_end.row(), + map.line_len(display_end.row(), ctx).unwrap(), + ) + .to_buffer_point(map, Bias::Left, ctx) + .unwrap(); + + buffer_start.row..buffer_end.row + 1 + } } diff --git a/zed/src/editor/buffer_view.rs b/zed/src/editor/buffer_view.rs index ba3ea337a44b689a957477362c6ae91f3f523e04..3c0fd8be83f7cdc09412777261077f9b802c6047 100644 --- a/zed/src/editor/buffer_view.rs +++ b/zed/src/editor/buffer_view.rs @@ -554,6 +554,7 @@ impl BufferView { self.start_transaction(ctx); let app = ctx.as_ref(); + let map = self.display_map.read(app); let buffer = self.buffer.read(app); let mut new_cursors = Vec::new(); @@ -561,52 +562,49 @@ impl BufferView { let mut selections = self.selections(app).iter().peekable(); while let Some(selection) = selections.next() { - let start = selection.start.to_point(buffer).unwrap(); - let mut end = selection.end.to_point(buffer).unwrap(); - let goal_column = if selection.reversed { - start.column - } else { - end.column - }; + let mut range = selection.buffer_row_range(map, app); + let goal_display_column = selection + .head() + .to_display_point(map, app) + .unwrap() + .column(); // Accumulate contiguous regions of rows that we want to delete. while let Some(next_selection) = selections.peek() { - let next_start = next_selection.start.to_point(buffer).unwrap(); - if next_start.row <= end.row + 1 { - end = next_selection.end.to_point(buffer).unwrap(); + let next_range = next_selection.buffer_row_range(map, app); + if next_range.start <= range.end { + range.end = next_range.end; selections.next().unwrap(); } else { break; } } - // When the deletion straddles multiple rows but ends at the beginning of a line, avoid - // deleting that final line. - if start.row != end.row && end.column == 0 { - end.row -= 1; - } - - let mut edit_start = Point::new(start.row, 0).to_offset(buffer).unwrap(); + let mut edit_start = Point::new(range.start, 0).to_offset(buffer).unwrap(); let edit_end; - let mut cursor; - - if let Ok(end_offset) = Point::new(end.row + 1, 0).to_offset(buffer) { + let cursor_buffer_row; + if let Ok(end_offset) = Point::new(range.end, 0).to_offset(buffer) { // If there's a line after the range, delete the \n from the end of the row range // and position the cursor on the next line. edit_end = end_offset; - cursor = Point::new(end.row + 1, goal_column); + cursor_buffer_row = range.end; } else { // If there isn't a line after the range, delete the \n from the line before the // start of the row range and position the cursor there. edit_start = edit_start.saturating_sub(1); edit_end = buffer.len(); - cursor = Point::new(start.row.saturating_sub(1), goal_column); + cursor_buffer_row = range.start.saturating_sub(1); } - // We tried to maintain the column of the original cursor but the new line may be - // shorter, so clip the new cursor's column. - cursor.column = cmp::min(cursor.column, buffer.line_len(cursor.row).unwrap()); - new_cursors.push(cursor); + let mut cursor = Point::new(cursor_buffer_row, 0) + .to_display_point(map, app) + .unwrap(); + *cursor.column_mut() = cmp::min( + goal_display_column, + map.line_len(cursor.row(), app).unwrap(), + ); + + new_cursors.push(cursor.to_buffer_point(map, Bias::Left, app).unwrap()); edit_ranges.push(edit_start..edit_end); }