diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index fc82b3f30e..43c061818f 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); - s.set_pending_anchor_range(start..end, mode); + 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(); + + 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 26ac14acdb..384b045f3f 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, |_| {});