From 10f7ca65cf49089b325b1f4cceba1f0058f8e517 Mon Sep 17 00:00:00 2001 From: Krzysztof Witkowski Date: Mon, 24 Jun 2024 10:32:37 +0200 Subject: [PATCH] Multi-cursor removal possibility (#13431) Release Notes: - Added the ability to remove multi-cursors by clicking on them again. ([#13058](https://github.com/zed-industries/zed/issues/13058)). --- crates/editor/src/editor.rs | 45 +++++++++++++++++++++++---- crates/editor/src/editor_tests.rs | 51 +++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index fc82b3f30e8dfadfeaf47deb26eb5c4a90fcbe35..43c061818fb606eb86f2e358ce77f94713d2036c 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -2564,14 +2564,47 @@ impl Editor { } } - self.change_selections(auto_scroll.then(|| Autoscroll::newest()), cx, |s| { - if !add { - s.clear_disjoint(); - } else if click_count > 1 { - s.delete(newest_selection.id) + let point_to_delete: Option = { + let selected_points: Vec> = + self.selections.disjoint_in_range(start..end, cx); + + if !add || click_count > 1 { + None + } else if selected_points.len() > 0 { + Some(selected_points[0].id) + } else { + let clicked_point_already_selected = + self.selections.disjoint.iter().find(|selection| { + selection.start.to_point(buffer) == start.to_point(buffer) + || selection.end.to_point(buffer) == end.to_point(buffer) + }); + + if let Some(selection) = clicked_point_already_selected { + Some(selection.id) + } else { + None + } } + }; + + let selections_count = self.selections.count(); - s.set_pending_anchor_range(start..end, mode); + self.change_selections(auto_scroll.then(|| Autoscroll::newest()), cx, |s| { + if let Some(point_to_delete) = point_to_delete { + s.delete(point_to_delete); + + if selections_count == 1 { + s.set_pending_anchor_range(start..end, mode); + } + } else { + if !add { + s.clear_disjoint(); + } else if click_count > 1 { + s.delete(newest_selection.id) + } + + s.set_pending_anchor_range(start..end, mode); + } }); } diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 26ac14acdbe0430a2ccdd4a1734ba362ef1f84ba..384b045f3fa2a0c99bb0becda047d5d680368f87 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -436,6 +436,57 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) { ); } +#[gpui::test] +fn test_multiple_cursor_removal(cx: &mut TestAppContext) { + init_test(cx, |_| {}); + + let editor = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx); + build_editor(buffer, cx) + }); + + _ = editor.update(cx, |view, cx| { + view.begin_selection(DisplayPoint::new(DisplayRow(2), 1), false, 1, cx); + }); + + _ = editor.update(cx, |view, cx| { + view.end_selection(cx); + }); + + _ = editor.update(cx, |view, cx| { + view.begin_selection(DisplayPoint::new(DisplayRow(3), 2), true, 1, cx); + }); + + _ = editor.update(cx, |view, cx| { + view.end_selection(cx); + }); + + assert_eq!( + editor + .update(cx, |view, cx| view.selections.display_ranges(cx)) + .unwrap(), + [ + DisplayPoint::new(DisplayRow(2), 1)..DisplayPoint::new(DisplayRow(2), 1), + DisplayPoint::new(DisplayRow(3), 2)..DisplayPoint::new(DisplayRow(3), 2) + ] + ); + + _ = editor.update(cx, |view, cx| { + view.begin_selection(DisplayPoint::new(DisplayRow(2), 1), true, 1, cx); + }); + + _ = editor.update(cx, |view, cx| { + view.end_selection(cx); + }); + + assert_eq!( + editor + .update(cx, |view, cx| view.selections.display_ranges(cx)) + .unwrap(), + [DisplayPoint::new(DisplayRow(3), 2)..DisplayPoint::new(DisplayRow(3), 2)] + ); +} + #[gpui::test] fn test_canceling_pending_selection(cx: &mut TestAppContext) { init_test(cx, |_| {});