diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 04821df62e..655fb39257 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -75,8 +75,6 @@ pub use multi_buffer::{ use ordered_float::OrderedFloat; use project::{FormatTrigger, Location, LocationLink, Project, ProjectPath, ProjectTransaction}; use rand::{seq::SliceRandom, thread_rng}; -// use rand::seq::SliceRandom; -// use rand::thread_rng; use scroll::{ autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide, }; @@ -4221,7 +4219,7 @@ impl Editor { _: &SortLinesCaseSensitive, cx: &mut ViewContext, ) { - self.manipulate_lines(cx, |lines| lines.sort()) + self.manipulate_lines(cx, |text| text.sort()) } pub fn sort_lines_case_insensitive( @@ -4229,20 +4227,24 @@ impl Editor { _: &SortLinesCaseInsensitive, cx: &mut ViewContext, ) { - self.manipulate_lines(cx, |lines| lines.sort_by_key(|line| line.to_lowercase())) + self.manipulate_lines(cx, |text| text.sort_by_key(|line| line.to_lowercase())) } pub fn reverse_lines(&mut self, _: &ReverseLines, cx: &mut ViewContext) { - self.manipulate_lines(cx, |lines| lines.reverse()) + self.manipulate_lines(cx, |lines| { + lines.reverse(); + }) } pub fn shuffle_lines(&mut self, _: &ShuffleLines, cx: &mut ViewContext) { - self.manipulate_lines(cx, |lines| lines.shuffle(&mut thread_rng())) + self.manipulate_lines(cx, |lines| { + lines.shuffle(&mut thread_rng()); + }) } fn manipulate_lines(&mut self, cx: &mut ViewContext, mut callback: Fn) where - Fn: FnMut(&mut Vec<&str>), + Fn: FnMut(&mut [&str]), { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); let buffer = self.buffer.read(cx).snapshot(cx); @@ -4252,9 +4254,9 @@ impl Editor { let selections = self.selections.all::(cx); let mut selections = selections.iter().peekable(); let mut contiguous_row_selections = Vec::new(); + let mut new_selections = Vec::new(); while let Some(selection) = selections.next() { - // Find all the selections that span a contiguous row range let (start_row, end_row) = consume_contiguous_rows( &mut contiguous_row_selections, selection, @@ -4262,12 +4264,35 @@ impl Editor { &mut selections, ); - let start = Point::new(start_row, 0); - let end = Point::new(end_row - 1, buffer.line_len(end_row - 1)); - let text = buffer.text_for_range(start..end).collect::(); - let mut lines = text.split("\n").collect::>(); - callback(&mut lines); - edits.push((start..end, lines.join("\n"))); + let start_point = Point::new(start_row, 0); + let end_point = Point::new(end_row - 1, buffer.line_len(end_row - 1)); + let text = buffer + .text_for_range(start_point..end_point) + .collect::(); + let mut text = text.split("\n").collect_vec(); + + let text_len = text.len(); + callback(&mut text); + + // This is a current limitation with selections. + // If we wanted to support removing or adding lines, we'd need to fix the logic associated with selections. + debug_assert!( + text.len() == text_len, + "callback should not change the number of lines" + ); + + edits.push((start_point..end_point, text.join("\n"))); + let start_anchor = buffer.anchor_after(start_point); + let end_anchor = buffer.anchor_before(end_point); + + // Make selection and push + new_selections.push(Selection { + id: selection.id, + start: start_anchor.to_offset(&buffer), + end: end_anchor.to_offset(&buffer), + goal: SelectionGoal::None, + reversed: selection.reversed, + }); } self.transact(cx, |this, cx| { @@ -4276,7 +4301,7 @@ impl Editor { }); this.change_selections(Some(Autoscroll::fit()), cx, |s| { - s.select(contiguous_row_selections); + s.select(new_selections); }); this.request_autoscroll(Autoscroll::fit(), cx); diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 18028eb8ee..bc814f8c15 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -2501,7 +2501,7 @@ fn test_join_lines_with_multi_selection(cx: &mut TestAppContext) { } #[gpui::test] -fn test_sort_lines_with_single_selection(cx: &mut TestAppContext) { +fn test_manipulate_lines_with_single_selection(cx: &mut TestAppContext) { init_test(cx, |_| {}); cx.add_window(|cx| { @@ -2510,7 +2510,7 @@ fn test_sort_lines_with_single_selection(cx: &mut TestAppContext) { let buffer = buffer.read(cx).as_singleton().unwrap(); editor.change_selections(None, cx, |s| { - s.select_ranges([Point::new(0, 2)..Point::new(0, 2)]) + s.select_ranges([Point::new(0, 1)..Point::new(0, 1)]) }); editor.sort_lines_case_sensitive(&SortLinesCaseSensitive, cx); assert_eq!( @@ -2520,13 +2520,13 @@ fn test_sort_lines_with_single_selection(cx: &mut TestAppContext) { ); assert_eq!( editor.selections.ranges::(cx), - &[Point::new(0, 2)..Point::new(0, 2)] + &[Point::new(0, 1)..Point::new(0, 2)] ); editor.change_selections(None, cx, |s| { - s.select_ranges([Point::new(0, 2)..Point::new(5, 1)]) + s.select_ranges([Point::new(0, 2)..Point::new(5, 0)]) }); - editor.sort_lines_case_sensitive(&SortLinesCaseSensitive, cx); + //editor.sort_lines(); assert_eq!( buffer.read(cx).text(), "a\nbb\nccc\ndddd\n\n", @@ -2542,7 +2542,7 @@ fn test_sort_lines_with_single_selection(cx: &mut TestAppContext) { } #[gpui::test] -fn test_sort_lines_with_multi_selection(cx: &mut TestAppContext) { +fn test_manipulate_lines_with_multi_selection(cx: &mut TestAppContext) { init_test(cx, |_| {}); cx.add_window(|cx| { diff --git a/crates/editor/src/selections_collection.rs b/crates/editor/src/selections_collection.rs index a22506f751..1921bc0738 100644 --- a/crates/editor/src/selections_collection.rs +++ b/crates/editor/src/selections_collection.rs @@ -138,7 +138,7 @@ impl SelectionsCollection { .collect() } - // Returns all of the selections, adjusted to take into account the selection line_mode + /// Returns all of the selections, adjusted to take into account the selection line_mode pub fn all_adjusted(&self, cx: &mut AppContext) -> Vec> { let mut selections = self.all::(cx); if self.line_mode {