From 88a8e53696e2f82cbae5d7317e753f96b93db5b6 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 7 Nov 2025 11:21:14 +0100 Subject: [PATCH] editor: Remove buffer and display map fields from SelectionsCollection (#42175) Release Notes: - N/A *or* Added/Fixed/Improved ... --- crates/diagnostics/src/diagnostics.rs | 10 +- crates/diagnostics/src/diagnostics_tests.rs | 8 +- crates/editor/src/display_map/block_map.rs | 8 + crates/editor/src/display_map/fold_map.rs | 8 + crates/editor/src/display_map/inlay_map.rs | 8 + crates/editor/src/display_map/tab_map.rs | 8 + crates/editor/src/display_map/wrap_map.rs | 8 + crates/editor/src/editor.rs | 54 +-- crates/editor/src/editor_tests.rs | 381 +++++++++----------- crates/editor/src/selections_collection.rs | 135 +++---- crates/search/src/buffer_search.rs | 84 +++-- crates/search/src/project_search.rs | 32 +- crates/vim/src/change_list.rs | 2 +- crates/vim/src/command.rs | 3 +- crates/vim/src/helix/paste.rs | 2 +- crates/vim/src/vim.rs | 2 +- crates/vim/src/visual.rs | 4 +- crates/zed/src/zed.rs | 4 +- 18 files changed, 394 insertions(+), 367 deletions(-) diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 5506cdba9ae4aaa7fbf1246aaa7b07e653ad0efc..d4aa24ae1d0d6198d582f6f304d4aae363cd47a0 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -315,11 +315,15 @@ impl ProjectDiagnosticsEditor { cx: &mut Context, retain_selections: bool, ) { - let buffer_ids = self.multibuffer.read(cx).all_buffer_ids(); - let selected_buffers = self.editor.update(cx, |editor, cx| { + let snapshot = self + .editor + .update(cx, |editor, cx| editor.display_snapshot(cx)); + let buffer = self.multibuffer.read(cx); + let buffer_ids = buffer.all_buffer_ids(); + let selected_buffers = self.editor.update(cx, |editor, _| { editor .selections - .all_anchors(cx) + .all_anchors(&snapshot) .iter() .filter_map(|anchor| anchor.start.buffer_id) .collect::>() diff --git a/crates/diagnostics/src/diagnostics_tests.rs b/crates/diagnostics/src/diagnostics_tests.rs index ad7c675fa82aaa95379a9e06dfc2561880d5da7f..16c5be55701f8ec1a8c773899f9ea35ca8ddcae7 100644 --- a/crates/diagnostics/src/diagnostics_tests.rs +++ b/crates/diagnostics/src/diagnostics_tests.rs @@ -156,7 +156,9 @@ async fn test_diagnostics(cx: &mut TestAppContext) { // Cursor is at the first diagnostic editor.update(cx, |editor, cx| { assert_eq!( - editor.selections.display_ranges(cx), + editor + .selections + .display_ranges(&editor.display_snapshot(cx)), [DisplayPoint::new(DisplayRow(3), 8)..DisplayPoint::new(DisplayRow(3), 8)] ); }); @@ -232,7 +234,9 @@ async fn test_diagnostics(cx: &mut TestAppContext) { // Cursor keeps its position. editor.update(cx, |editor, cx| { assert_eq!( - editor.selections.display_ranges(cx), + editor + .selections + .display_ranges(&editor.display_snapshot(cx)), [DisplayPoint::new(DisplayRow(8), 8)..DisplayPoint::new(DisplayRow(8), 8)] ); }); diff --git a/crates/editor/src/display_map/block_map.rs b/crates/editor/src/display_map/block_map.rs index 27e61c51903b2ba8ca28623de46b742e710eba11..54c008ef60cdaf3a6c7b9231bfbb90d2caf0b3ae 100644 --- a/crates/editor/src/display_map/block_map.rs +++ b/crates/editor/src/display_map/block_map.rs @@ -63,6 +63,14 @@ pub struct BlockSnapshot { pub(super) excerpt_header_height: u32, } +impl Deref for BlockSnapshot { + type Target = WrapSnapshot; + + fn deref(&self) -> &Self::Target { + &self.wrap_snapshot + } +} + #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct CustomBlockId(pub usize); diff --git a/crates/editor/src/display_map/fold_map.rs b/crates/editor/src/display_map/fold_map.rs index a31599ef9b276246226c12640fa8ffbec57eb9e3..4a628f866807aa9b1a1edd45fb9714a5fcc3d5d3 100644 --- a/crates/editor/src/display_map/fold_map.rs +++ b/crates/editor/src/display_map/fold_map.rs @@ -630,6 +630,14 @@ pub struct FoldSnapshot { pub version: usize, } +impl Deref for FoldSnapshot { + type Target = InlaySnapshot; + + fn deref(&self) -> &Self::Target { + &self.inlay_snapshot + } +} + impl FoldSnapshot { pub fn buffer(&self) -> &MultiBufferSnapshot { &self.inlay_snapshot.buffer diff --git a/crates/editor/src/display_map/inlay_map.rs b/crates/editor/src/display_map/inlay_map.rs index 486676f1120bc2e9d85effd4c328a2b7a547e06b..697cf1f68ceac4f6a777a3ec401658394f646af5 100644 --- a/crates/editor/src/display_map/inlay_map.rs +++ b/crates/editor/src/display_map/inlay_map.rs @@ -32,6 +32,14 @@ pub struct InlaySnapshot { pub version: usize, } +impl std::ops::Deref for InlaySnapshot { + type Target = MultiBufferSnapshot; + + fn deref(&self) -> &Self::Target { + &self.buffer + } +} + #[derive(Clone, Debug)] enum Transform { Isomorphic(TextSummary), diff --git a/crates/editor/src/display_map/tab_map.rs b/crates/editor/src/display_map/tab_map.rs index 7a63723f53a49483eaa728373a5ae8530aa6f4d6..ab3bddf7278605e89b816831059de73873853b32 100644 --- a/crates/editor/src/display_map/tab_map.rs +++ b/crates/editor/src/display_map/tab_map.rs @@ -167,6 +167,14 @@ pub struct TabSnapshot { pub version: usize, } +impl std::ops::Deref for TabSnapshot { + type Target = FoldSnapshot; + + fn deref(&self) -> &Self::Target { + &self.fold_snapshot + } +} + impl TabSnapshot { pub fn buffer_snapshot(&self) -> &MultiBufferSnapshot { &self.fold_snapshot.inlay_snapshot.buffer diff --git a/crates/editor/src/display_map/wrap_map.rs b/crates/editor/src/display_map/wrap_map.rs index f8214d9c804906e5760636c2149392ded07fe6ed..ffdae5913229de33faeab195dd5211229c641f73 100644 --- a/crates/editor/src/display_map/wrap_map.rs +++ b/crates/editor/src/display_map/wrap_map.rs @@ -43,6 +43,14 @@ pub struct WrapSnapshot { interpolated: bool, } +impl std::ops::Deref for WrapSnapshot { + type Target = TabSnapshot; + + fn deref(&self) -> &Self::Target { + &self.tab_snapshot + } +} + #[derive(Clone, Debug, Default, Eq, PartialEq)] struct Transform { summary: TransformSummary, diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 4cb566f93e2bf74c5982f370e8ccaca548d4fb11..646e5ba4ab9f3ecbb4b4ab8be502eaca7a08dbcd 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -1843,7 +1843,7 @@ impl Editor { }) }); - let selections = SelectionsCollection::new(display_map.clone(), multi_buffer.clone()); + let selections = SelectionsCollection::new(); let blink_manager = cx.new(|cx| { let mut blink_manager = BlinkManager::new(CURSOR_BLINK_INTERVAL, cx); @@ -2434,7 +2434,7 @@ impl Editor { } pub fn display_snapshot(&self, cx: &mut App) -> DisplaySnapshot { - self.selections.display_map(cx) + self.display_map.update(cx, |map, cx| map.snapshot(cx)) } pub fn deploy_mouse_context_menu( @@ -3366,11 +3366,13 @@ impl Editor { other: Entity, cx: &mut Context, ) -> gpui::Subscription { + assert_eq!(self.buffer(), other.read(cx).buffer()); let other_selections = other.read(cx).selections.disjoint_anchors().to_vec(); if !other_selections.is_empty() { - self.selections.change_with(cx, |selections| { - selections.select_anchors(other_selections); - }); + self.selections + .change_with(&self.display_snapshot(cx), |selections| { + selections.select_anchors(other_selections); + }); } let other_subscription = cx.subscribe(&other, |this, other, other_evt, cx| { @@ -3379,7 +3381,8 @@ impl Editor { if other_selections.is_empty() { return; } - this.selections.change_with(cx, |selections| { + let snapshot = this.display_snapshot(cx); + this.selections.change_with(&snapshot, |selections| { selections.select_anchors(other_selections); }); } @@ -3392,9 +3395,12 @@ impl Editor { return; } other.update(cx, |other_editor, cx| { - other_editor.selections.change_with(cx, |selections| { - selections.select_anchors(these_selections); - }) + let snapshot = other_editor.display_snapshot(cx); + other_editor + .selections + .change_with(&snapshot, |selections| { + selections.select_anchors(these_selections); + }) }); } }); @@ -3410,13 +3416,14 @@ impl Editor { effects: SelectionEffects, window: &mut Window, cx: &mut Context, - change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R, + change: impl FnOnce(&mut MutableSelectionsCollection<'_, '_>) -> R, ) -> R { + let snapshot = self.display_snapshot(cx); if let Some(state) = &mut self.deferred_selection_effects_state { state.effects.scroll = effects.scroll.or(state.effects.scroll); state.effects.completions = effects.completions; state.effects.nav_history = effects.nav_history.or(state.effects.nav_history); - let (changed, result) = self.selections.change_with(cx, change); + let (changed, result) = self.selections.change_with(&snapshot, change); state.changed |= changed; return result; } @@ -3431,7 +3438,7 @@ impl Editor { add_selections_state: self.add_selections_state.clone(), }, }; - let (changed, result) = self.selections.change_with(cx, change); + let (changed, result) = self.selections.change_with(&snapshot, change); state.changed = state.changed || changed; if self.defer_selection_effects { self.deferred_selection_effects_state = Some(state); @@ -16276,7 +16283,7 @@ impl Editor { .map(|s| s.to_vec()) { self.change_selections(Default::default(), window, cx, |s| { - let map = s.display_map(); + let map = s.display_snapshot(); s.select_display_ranges(selections.iter().map(|a| { let point = a.to_display_point(&map); point..point @@ -16297,7 +16304,7 @@ impl Editor { .map(|s| s.to_vec()) { self.change_selections(Default::default(), window, cx, |s| { - let map = s.display_map(); + let map = s.display_snapshot(); s.select_display_ranges(selections.iter().map(|a| { let point = a.to_display_point(&map); point..point @@ -18092,14 +18099,15 @@ impl Editor { cx: &mut Context, ) { let old_cursor_position = self.selections.newest_anchor().head(); - self.selections.change_with(cx, |s| { - s.select_anchors(selections); - if let Some(pending_selection) = pending_selection { - s.set_pending(pending_selection, SelectMode::Character); - } else { - s.clear_pending(); - } - }); + self.selections + .change_with(&self.display_snapshot(cx), |s| { + s.select_anchors(selections); + if let Some(pending_selection) = pending_selection { + s.set_pending(pending_selection, SelectMode::Character); + } else { + s.clear_pending(); + } + }); self.selections_did_change( false, &old_cursor_position, @@ -20307,7 +20315,7 @@ impl Editor { let locations = self .selections - .all_anchors(cx) + .all_anchors(&self.display_snapshot(cx)) .iter() .map(|selection| { ( diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index f411bda96ee444c1e4b2ff0c2d11f1475e85b9ac..1c387b021106fb4532585f3c1c8638ee0e9fe1c4 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -68,6 +68,12 @@ use workspace::{ register_project_item, }; +fn display_ranges(editor: &Editor, cx: &mut Context<'_, Editor>) -> Vec> { + editor + .selections + .display_ranges(&editor.display_snapshot(cx)) +} + #[gpui::test] fn test_edit_events(cx: &mut TestAppContext) { init_test(cx, |_| {}); @@ -416,7 +422,7 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) { }); assert_eq!( editor - .update(cx, |editor, _, cx| editor.selections.display_ranges(cx)) + .update(cx, |editor, _, cx| display_ranges(editor, cx)) .unwrap(), [DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(2), 2)] ); @@ -433,7 +439,7 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) { assert_eq!( editor - .update(cx, |editor, _, cx| editor.selections.display_ranges(cx)) + .update(cx, |editor, _, cx| display_ranges(editor, cx)) .unwrap(), [DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(3), 3)] ); @@ -450,7 +456,7 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) { assert_eq!( editor - .update(cx, |editor, _, cx| editor.selections.display_ranges(cx)) + .update(cx, |editor, _, cx| display_ranges(editor, cx)) .unwrap(), [DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(1), 1)] ); @@ -468,7 +474,7 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) { assert_eq!( editor - .update(cx, |editor, _, cx| editor.selections.display_ranges(cx)) + .update(cx, |editor, _, cx| display_ranges(editor, cx)) .unwrap(), [DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(1), 1)] ); @@ -486,7 +492,7 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) { assert_eq!( editor - .update(cx, |editor, _, cx| editor.selections.display_ranges(cx)) + .update(cx, |editor, _, cx| display_ranges(editor, cx)) .unwrap(), [ DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(1), 1), @@ -500,7 +506,7 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) { assert_eq!( editor - .update(cx, |editor, _, cx| editor.selections.display_ranges(cx)) + .update(cx, |editor, _, cx| display_ranges(editor, cx)) .unwrap(), [DisplayPoint::new(DisplayRow(3), 3)..DisplayPoint::new(DisplayRow(0), 0)] ); @@ -533,7 +539,7 @@ fn test_multiple_cursor_removal(cx: &mut TestAppContext) { assert_eq!( editor - .update(cx, |editor, _, cx| editor.selections.display_ranges(cx)) + .update(cx, |editor, _, cx| display_ranges(editor, cx)) .unwrap(), [ DisplayPoint::new(DisplayRow(2), 1)..DisplayPoint::new(DisplayRow(2), 1), @@ -551,7 +557,7 @@ fn test_multiple_cursor_removal(cx: &mut TestAppContext) { assert_eq!( editor - .update(cx, |editor, _, cx| editor.selections.display_ranges(cx)) + .update(cx, |editor, _, cx| display_ranges(editor, cx)) .unwrap(), [DisplayPoint::new(DisplayRow(3), 2)..DisplayPoint::new(DisplayRow(3), 2)] ); @@ -569,7 +575,7 @@ fn test_canceling_pending_selection(cx: &mut TestAppContext) { _ = editor.update(cx, |editor, window, cx| { editor.begin_selection(DisplayPoint::new(DisplayRow(2), 2), false, 1, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(2), 2)] ); }); @@ -583,7 +589,7 @@ fn test_canceling_pending_selection(cx: &mut TestAppContext) { cx, ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(3), 3)] ); }); @@ -598,7 +604,7 @@ fn test_canceling_pending_selection(cx: &mut TestAppContext) { cx, ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(3), 3)] ); }); @@ -616,25 +622,25 @@ fn test_movement_actions_with_pending_selection(cx: &mut TestAppContext) { _ = editor.update(cx, |editor, window, cx| { editor.begin_selection(DisplayPoint::new(DisplayRow(2), 2), false, 1, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(2), 2)] ); editor.move_down(&Default::default(), window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [DisplayPoint::new(DisplayRow(3), 2)..DisplayPoint::new(DisplayRow(3), 2)] ); editor.begin_selection(DisplayPoint::new(DisplayRow(2), 2), false, 1, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(2), 2)] ); editor.move_up(&Default::default(), window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [DisplayPoint::new(DisplayRow(1), 2)..DisplayPoint::new(DisplayRow(1), 2)] ); }); @@ -653,14 +659,14 @@ fn test_extending_selection(cx: &mut TestAppContext) { editor.begin_selection(DisplayPoint::new(DisplayRow(0), 5), false, 1, window, cx); editor.end_selection(window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [DisplayPoint::new(DisplayRow(0), 5)..DisplayPoint::new(DisplayRow(0), 5)] ); editor.extend_selection(DisplayPoint::new(DisplayRow(0), 10), 1, window, cx); editor.end_selection(window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [DisplayPoint::new(DisplayRow(0), 5)..DisplayPoint::new(DisplayRow(0), 10)] ); @@ -668,7 +674,7 @@ fn test_extending_selection(cx: &mut TestAppContext) { editor.end_selection(window, cx); editor.extend_selection(DisplayPoint::new(DisplayRow(0), 10), 2, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [DisplayPoint::new(DisplayRow(0), 5)..DisplayPoint::new(DisplayRow(0), 11)] ); @@ -681,7 +687,7 @@ fn test_extending_selection(cx: &mut TestAppContext) { ); editor.end_selection(window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [DisplayPoint::new(DisplayRow(0), 5)..DisplayPoint::new(DisplayRow(0), 0)] ); @@ -690,13 +696,13 @@ fn test_extending_selection(cx: &mut TestAppContext) { editor.begin_selection(DisplayPoint::new(DisplayRow(0), 5), true, 2, window, cx); editor.end_selection(window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [DisplayPoint::new(DisplayRow(0), 4)..DisplayPoint::new(DisplayRow(0), 7)] ); editor.extend_selection(DisplayPoint::new(DisplayRow(0), 10), 1, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [DisplayPoint::new(DisplayRow(0), 4)..DisplayPoint::new(DisplayRow(0), 11)] ); @@ -708,7 +714,7 @@ fn test_extending_selection(cx: &mut TestAppContext) { cx, ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [DisplayPoint::new(DisplayRow(0), 4)..DisplayPoint::new(DisplayRow(0), 7)] ); @@ -721,7 +727,7 @@ fn test_extending_selection(cx: &mut TestAppContext) { ); editor.end_selection(window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [DisplayPoint::new(DisplayRow(0), 7)..DisplayPoint::new(DisplayRow(0), 0)] ); }); @@ -804,10 +810,14 @@ fn test_clone(cx: &mut TestAppContext) { ); assert_set_eq!( cloned_editor - .update(cx, |e, _window, cx| e.selections.display_ranges(cx)) + .update(cx, |e, _window, cx| e + .selections + .display_ranges(&e.display_snapshot(cx))) .unwrap(), editor - .update(cx, |e, _, cx| e.selections.display_ranges(cx)) + .update(cx, |e, _, cx| e + .selections + .display_ranges(&e.display_snapshot(cx))) .unwrap() ); } @@ -861,7 +871,9 @@ async fn test_navigation_history(cx: &mut TestAppContext) { editor.navigate(nav_entry.data.unwrap(), window, cx); assert_eq!(nav_entry.item.id(), cx.entity_id()); assert_eq!( - editor.selections.display_ranges(cx), + editor + .selections + .display_ranges(&editor.display_snapshot(cx)), &[DisplayPoint::new(DisplayRow(3), 0)..DisplayPoint::new(DisplayRow(3), 0)] ); assert!(pop_history(&mut editor, cx).is_none()); @@ -871,7 +883,9 @@ async fn test_navigation_history(cx: &mut TestAppContext) { editor.begin_selection(DisplayPoint::new(DisplayRow(5), 0), false, 1, window, cx); editor.end_selection(window, cx); assert_eq!( - editor.selections.display_ranges(cx), + editor + .selections + .display_ranges(&editor.display_snapshot(cx)), &[DisplayPoint::new(DisplayRow(5), 0)..DisplayPoint::new(DisplayRow(5), 0)] ); assert!(pop_history(&mut editor, cx).is_none()); @@ -881,14 +895,18 @@ async fn test_navigation_history(cx: &mut TestAppContext) { editor.begin_selection(DisplayPoint::new(DisplayRow(15), 0), false, 1, window, cx); editor.end_selection(window, cx); assert_eq!( - editor.selections.display_ranges(cx), + editor + .selections + .display_ranges(&editor.display_snapshot(cx)), &[DisplayPoint::new(DisplayRow(15), 0)..DisplayPoint::new(DisplayRow(15), 0)] ); let nav_entry = pop_history(&mut editor, cx).unwrap(); editor.navigate(nav_entry.data.unwrap(), window, cx); assert_eq!(nav_entry.item.id(), cx.entity_id()); assert_eq!( - editor.selections.display_ranges(cx), + editor + .selections + .display_ranges(&editor.display_snapshot(cx)), &[DisplayPoint::new(DisplayRow(5), 0)..DisplayPoint::new(DisplayRow(5), 0)] ); assert!(pop_history(&mut editor, cx).is_none()); @@ -924,7 +942,9 @@ async fn test_navigation_history(cx: &mut TestAppContext) { cx, ); assert_eq!( - editor.selections.display_ranges(cx), + editor + .selections + .display_ranges(&editor.display_snapshot(cx)), &[editor.max_point(cx)..editor.max_point(cx)] ); assert_eq!( @@ -967,7 +987,7 @@ fn test_cancel(cx: &mut TestAppContext) { ); editor.end_selection(window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [ DisplayPoint::new(DisplayRow(0), 1)..DisplayPoint::new(DisplayRow(0), 3), DisplayPoint::new(DisplayRow(3), 4)..DisplayPoint::new(DisplayRow(1), 1), @@ -978,7 +998,7 @@ fn test_cancel(cx: &mut TestAppContext) { _ = editor.update(cx, |editor, window, cx| { editor.cancel(&Cancel, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [DisplayPoint::new(DisplayRow(3), 4)..DisplayPoint::new(DisplayRow(1), 1)] ); }); @@ -986,7 +1006,7 @@ fn test_cancel(cx: &mut TestAppContext) { _ = editor.update(cx, |editor, window, cx| { editor.cancel(&Cancel, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [DisplayPoint::new(DisplayRow(1), 1)..DisplayPoint::new(DisplayRow(1), 1)] ); }); @@ -1447,43 +1467,43 @@ fn test_move_cursor(cx: &mut TestAppContext) { }); _ = editor.update(cx, |editor, window, cx| { assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0)] ); editor.move_down(&MoveDown, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(1), 0)..DisplayPoint::new(DisplayRow(1), 0)] ); editor.move_right(&MoveRight, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(1), 4)..DisplayPoint::new(DisplayRow(1), 4)] ); editor.move_left(&MoveLeft, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(1), 0)..DisplayPoint::new(DisplayRow(1), 0)] ); editor.move_up(&MoveUp, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0)] ); editor.move_to_end(&MoveToEnd, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(5), 6)..DisplayPoint::new(DisplayRow(5), 6)] ); editor.move_to_beginning(&MoveToBeginning, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0)] ); @@ -1494,13 +1514,13 @@ fn test_move_cursor(cx: &mut TestAppContext) { }); editor.select_to_beginning(&SelectToBeginning, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(0), 1)..DisplayPoint::new(DisplayRow(0), 0)] ); editor.select_to_end(&SelectToEnd, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(0), 1)..DisplayPoint::new(DisplayRow(5), 6)] ); }); @@ -1532,94 +1552,43 @@ fn test_move_cursor_multibyte(cx: &mut TestAppContext) { assert_eq!(editor.display_text(cx), "🟥🟧⋯🟦🟪\nab⋯e\nαβ⋯ε"); editor.move_right(&MoveRight, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(0, "🟥".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(0, "🟥".len())]); editor.move_right(&MoveRight, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(0, "🟥🟧".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(0, "🟥🟧".len())]); editor.move_right(&MoveRight, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(0, "🟥🟧⋯".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(0, "🟥🟧⋯".len())]); editor.move_down(&MoveDown, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(1, "ab⋯e".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(1, "ab⋯e".len())]); editor.move_left(&MoveLeft, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(1, "ab⋯".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(1, "ab⋯".len())]); editor.move_left(&MoveLeft, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(1, "ab".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(1, "ab".len())]); editor.move_left(&MoveLeft, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(1, "a".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(1, "a".len())]); editor.move_down(&MoveDown, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(2, "α".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(2, "α".len())]); editor.move_right(&MoveRight, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(2, "αβ".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(2, "αβ".len())]); editor.move_right(&MoveRight, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(2, "αβ⋯".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(2, "αβ⋯".len())]); editor.move_right(&MoveRight, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(2, "αβ⋯ε".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(2, "αβ⋯ε".len())]); editor.move_up(&MoveUp, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(1, "ab⋯e".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(1, "ab⋯e".len())]); editor.move_down(&MoveDown, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(2, "αβ⋯ε".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(2, "αβ⋯ε".len())]); editor.move_up(&MoveUp, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(1, "ab⋯e".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(1, "ab⋯e".len())]); editor.move_up(&MoveUp, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(0, "🟥🟧".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(0, "🟥🟧".len())]); editor.move_left(&MoveLeft, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(0, "🟥".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(0, "🟥".len())]); editor.move_left(&MoveLeft, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(0, "".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(0, "".len())]); }); } @@ -1639,65 +1608,35 @@ fn test_move_cursor_different_line_lengths(cx: &mut TestAppContext) { // moving above start of document should move selection to start of document, // but the next move down should still be at the original goal_x editor.move_up(&MoveUp, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(0, "".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(0, "".len())]); editor.move_down(&MoveDown, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(1, "abcd".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(1, "abcd".len())]); editor.move_down(&MoveDown, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(2, "αβγ".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(2, "αβγ".len())]); editor.move_down(&MoveDown, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(3, "abcd".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(3, "abcd".len())]); editor.move_down(&MoveDown, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]); // moving past end of document should not change goal_x editor.move_down(&MoveDown, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(5, "".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(5, "".len())]); editor.move_down(&MoveDown, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(5, "".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(5, "".len())]); editor.move_up(&MoveUp, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]); editor.move_up(&MoveUp, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(3, "abcd".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(3, "abcd".len())]); editor.move_up(&MoveUp, window, cx); - assert_eq!( - editor.selections.display_ranges(cx), - &[empty_range(2, "αβγ".len())] - ); + assert_eq!(display_ranges(editor, cx), &[empty_range(2, "αβγ".len())]); }); } @@ -1733,7 +1672,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { _ = editor.update(cx, |editor, window, cx| { editor.move_to_beginning_of_line(&move_to_beg, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[ DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0), DisplayPoint::new(DisplayRow(1), 2)..DisplayPoint::new(DisplayRow(1), 2), @@ -1744,7 +1683,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { _ = editor.update(cx, |editor, window, cx| { editor.move_to_beginning_of_line(&move_to_beg, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[ DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0), DisplayPoint::new(DisplayRow(1), 0)..DisplayPoint::new(DisplayRow(1), 0), @@ -1755,7 +1694,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { _ = editor.update(cx, |editor, window, cx| { editor.move_to_beginning_of_line(&move_to_beg, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[ DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0), DisplayPoint::new(DisplayRow(1), 2)..DisplayPoint::new(DisplayRow(1), 2), @@ -1766,7 +1705,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { _ = editor.update(cx, |editor, window, cx| { editor.move_to_end_of_line(&move_to_end, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[ DisplayPoint::new(DisplayRow(0), 3)..DisplayPoint::new(DisplayRow(0), 3), DisplayPoint::new(DisplayRow(1), 5)..DisplayPoint::new(DisplayRow(1), 5), @@ -1778,7 +1717,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { _ = editor.update(cx, |editor, window, cx| { editor.move_to_end_of_line(&move_to_end, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[ DisplayPoint::new(DisplayRow(0), 3)..DisplayPoint::new(DisplayRow(0), 3), DisplayPoint::new(DisplayRow(1), 5)..DisplayPoint::new(DisplayRow(1), 5), @@ -1797,7 +1736,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { cx, ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[ DisplayPoint::new(DisplayRow(0), 2)..DisplayPoint::new(DisplayRow(0), 0), DisplayPoint::new(DisplayRow(1), 4)..DisplayPoint::new(DisplayRow(1), 2), @@ -1815,7 +1754,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { cx, ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[ DisplayPoint::new(DisplayRow(0), 2)..DisplayPoint::new(DisplayRow(0), 0), DisplayPoint::new(DisplayRow(1), 4)..DisplayPoint::new(DisplayRow(1), 0), @@ -1833,7 +1772,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { cx, ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[ DisplayPoint::new(DisplayRow(0), 2)..DisplayPoint::new(DisplayRow(0), 0), DisplayPoint::new(DisplayRow(1), 4)..DisplayPoint::new(DisplayRow(1), 2), @@ -1850,7 +1789,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { cx, ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[ DisplayPoint::new(DisplayRow(0), 2)..DisplayPoint::new(DisplayRow(0), 3), DisplayPoint::new(DisplayRow(1), 4)..DisplayPoint::new(DisplayRow(1), 5), @@ -1862,7 +1801,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { editor.delete_to_end_of_line(&DeleteToEndOfLine, window, cx); assert_eq!(editor.display_text(cx), "ab\n de"); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[ DisplayPoint::new(DisplayRow(0), 2)..DisplayPoint::new(DisplayRow(0), 2), DisplayPoint::new(DisplayRow(1), 4)..DisplayPoint::new(DisplayRow(1), 4), @@ -1874,7 +1813,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { editor.delete_to_beginning_of_line(&delete_to_beg, window, cx); assert_eq!(editor.display_text(cx), "\n"); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[ DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0), DisplayPoint::new(DisplayRow(1), 0)..DisplayPoint::new(DisplayRow(1), 0), @@ -1927,14 +1866,14 @@ fn test_beginning_end_of_line_ignore_soft_wrap(cx: &mut TestAppContext) { editor.move_to_beginning_of_line(&move_to_beg, window, cx); assert_eq!( vec![DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0),], - editor.selections.display_ranges(cx) + display_ranges(editor, cx) ); // Moving to the end of the line should put us at the end of the line. editor.move_to_end_of_line(&move_to_end, window, cx); assert_eq!( vec![DisplayPoint::new(DisplayRow(0), 16)..DisplayPoint::new(DisplayRow(0), 16),], - editor.selections.display_ranges(cx) + display_ranges(editor, cx) ); // Now, let's assert behavior on the second line, that ended up being soft-wrapped. @@ -1950,14 +1889,14 @@ fn test_beginning_end_of_line_ignore_soft_wrap(cx: &mut TestAppContext) { editor.move_to_beginning_of_line(&move_to_beg, window, cx); assert_eq!( vec![DisplayPoint::new(DisplayRow(1), 0)..DisplayPoint::new(DisplayRow(1), 0),], - editor.selections.display_ranges(cx) + display_ranges(editor, cx) ); // Moving to the beginning of the line again should be a no-op. editor.move_to_beginning_of_line(&move_to_beg, window, cx); assert_eq!( vec![DisplayPoint::new(DisplayRow(1), 0)..DisplayPoint::new(DisplayRow(1), 0),], - editor.selections.display_ranges(cx) + display_ranges(editor, cx) ); // Moving to the end of the line should put us right after the `s` that was soft-wrapped to the @@ -1965,14 +1904,14 @@ fn test_beginning_end_of_line_ignore_soft_wrap(cx: &mut TestAppContext) { editor.move_to_end_of_line(&move_to_end, window, cx); assert_eq!( vec![DisplayPoint::new(DisplayRow(2), 5)..DisplayPoint::new(DisplayRow(2), 5),], - editor.selections.display_ranges(cx) + display_ranges(editor, cx) ); // Moving to the end of the line again should be a no-op. editor.move_to_end_of_line(&move_to_end, window, cx); assert_eq!( vec![DisplayPoint::new(DisplayRow(2), 5)..DisplayPoint::new(DisplayRow(2), 5),], - editor.selections.display_ranges(cx) + display_ranges(editor, cx) ); }); } @@ -2016,7 +1955,7 @@ fn test_beginning_of_line_stop_at_indent(cx: &mut TestAppContext) { // and the second cursor at the first non-whitespace character in the line. editor.move_to_beginning_of_line(&move_to_beg, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[ DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0), DisplayPoint::new(DisplayRow(1), 2)..DisplayPoint::new(DisplayRow(1), 2), @@ -2027,7 +1966,7 @@ fn test_beginning_of_line_stop_at_indent(cx: &mut TestAppContext) { // and should move the second cursor to the beginning of the line. editor.move_to_beginning_of_line(&move_to_beg, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[ DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0), DisplayPoint::new(DisplayRow(1), 0)..DisplayPoint::new(DisplayRow(1), 0), @@ -2038,7 +1977,7 @@ fn test_beginning_of_line_stop_at_indent(cx: &mut TestAppContext) { // and should move the second cursor back to the first non-whitespace character in the line. editor.move_to_beginning_of_line(&move_to_beg, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[ DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0), DisplayPoint::new(DisplayRow(1), 2)..DisplayPoint::new(DisplayRow(1), 2), @@ -2051,7 +1990,7 @@ fn test_beginning_of_line_stop_at_indent(cx: &mut TestAppContext) { editor.move_left(&MoveLeft, window, cx); editor.select_to_beginning_of_line(&select_to_beg, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[ DisplayPoint::new(DisplayRow(0), 2)..DisplayPoint::new(DisplayRow(0), 0), DisplayPoint::new(DisplayRow(1), 4)..DisplayPoint::new(DisplayRow(1), 2), @@ -2062,7 +2001,7 @@ fn test_beginning_of_line_stop_at_indent(cx: &mut TestAppContext) { // and should select to the beginning of the line for the second cursor. editor.select_to_beginning_of_line(&select_to_beg, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[ DisplayPoint::new(DisplayRow(0), 2)..DisplayPoint::new(DisplayRow(0), 0), DisplayPoint::new(DisplayRow(1), 4)..DisplayPoint::new(DisplayRow(1), 0), @@ -2103,21 +2042,21 @@ fn test_beginning_of_line_with_cursor_between_line_start_and_indent(cx: &mut Tes // cursor should move to line_start editor.move_to_beginning_of_line(&move_to_beg, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0)] ); // cursor should move to indent_start editor.move_to_beginning_of_line(&move_to_beg, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(0), 4)..DisplayPoint::new(DisplayRow(0), 4)] ); // cursor should move to back to line_start editor.move_to_beginning_of_line(&move_to_beg, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0)] ); }); @@ -2210,37 +2149,37 @@ fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut TestAppContext) { editor.move_to_next_word_end(&MoveToNextWordEnd, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(1), 9)..DisplayPoint::new(DisplayRow(1), 9)] ); editor.move_to_next_word_end(&MoveToNextWordEnd, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(1), 14)..DisplayPoint::new(DisplayRow(1), 14)] ); editor.move_to_next_word_end(&MoveToNextWordEnd, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(2), 4)..DisplayPoint::new(DisplayRow(2), 4)] ); editor.move_to_next_word_end(&MoveToNextWordEnd, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(2), 8)..DisplayPoint::new(DisplayRow(2), 8)] ); editor.move_to_previous_word_start(&MoveToPreviousWordStart, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(2), 4)..DisplayPoint::new(DisplayRow(2), 4)] ); editor.move_to_previous_word_start(&MoveToPreviousWordStart, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(1), 14)..DisplayPoint::new(DisplayRow(1), 14)] ); }); @@ -4487,7 +4426,7 @@ fn test_delete_line(cx: &mut TestAppContext) { editor.delete_line(&DeleteLine, window, cx); assert_eq!(editor.display_text(cx), "ghi"); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), vec![ DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0), DisplayPoint::new(DisplayRow(0), 1)..DisplayPoint::new(DisplayRow(0), 1), @@ -4508,7 +4447,7 @@ fn test_delete_line(cx: &mut TestAppContext) { editor.delete_line(&DeleteLine, window, cx); assert_eq!(editor.display_text(cx), "ghi\n"); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), vec![DisplayPoint::new(DisplayRow(0), 1)..DisplayPoint::new(DisplayRow(0), 1)] ); }); @@ -4526,7 +4465,7 @@ fn test_delete_line(cx: &mut TestAppContext) { editor.delete_line(&DeleteLine, window, cx); assert_eq!(editor.display_text(cx), "\njkl\nmno"); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), vec![DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0)] ); }); @@ -5685,7 +5624,7 @@ fn test_duplicate_line(cx: &mut TestAppContext) { editor.duplicate_line_down(&DuplicateLineDown, window, cx); assert_eq!(editor.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n"); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), vec![ DisplayPoint::new(DisplayRow(1), 0)..DisplayPoint::new(DisplayRow(1), 1), DisplayPoint::new(DisplayRow(1), 2)..DisplayPoint::new(DisplayRow(1), 2), @@ -5709,7 +5648,7 @@ fn test_duplicate_line(cx: &mut TestAppContext) { editor.duplicate_line_down(&DuplicateLineDown, window, cx); assert_eq!(editor.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n"); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), vec![ DisplayPoint::new(DisplayRow(3), 1)..DisplayPoint::new(DisplayRow(4), 1), DisplayPoint::new(DisplayRow(4), 2)..DisplayPoint::new(DisplayRow(5), 1), @@ -5735,7 +5674,7 @@ fn test_duplicate_line(cx: &mut TestAppContext) { editor.duplicate_line_up(&DuplicateLineUp, window, cx); assert_eq!(editor.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n"); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), vec![ DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 1), DisplayPoint::new(DisplayRow(0), 2)..DisplayPoint::new(DisplayRow(0), 2), @@ -5759,7 +5698,7 @@ fn test_duplicate_line(cx: &mut TestAppContext) { editor.duplicate_line_up(&DuplicateLineUp, window, cx); assert_eq!(editor.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n"); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), vec![ DisplayPoint::new(DisplayRow(0), 1)..DisplayPoint::new(DisplayRow(1), 1), DisplayPoint::new(DisplayRow(1), 2)..DisplayPoint::new(DisplayRow(2), 1), @@ -5781,7 +5720,7 @@ fn test_duplicate_line(cx: &mut TestAppContext) { editor.duplicate_selection(&DuplicateSelection, window, cx); assert_eq!(editor.display_text(cx), "abc\ndbc\ndef\ngf\nghi\n"); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), vec![ DisplayPoint::new(DisplayRow(0), 1)..DisplayPoint::new(DisplayRow(1), 1), DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(3), 1), @@ -5828,7 +5767,7 @@ fn test_move_line_up_down(cx: &mut TestAppContext) { "aa⋯bbb\nccc⋯eeee\nggggg\n⋯i\njjjjj\nfffff" ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), vec![ DisplayPoint::new(DisplayRow(0), 1)..DisplayPoint::new(DisplayRow(0), 1), DisplayPoint::new(DisplayRow(2), 1)..DisplayPoint::new(DisplayRow(2), 1), @@ -5845,7 +5784,7 @@ fn test_move_line_up_down(cx: &mut TestAppContext) { "ccc⋯eeee\naa⋯bbb\nfffff\nggggg\n⋯i\njjjjj" ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), vec![ DisplayPoint::new(DisplayRow(1), 1)..DisplayPoint::new(DisplayRow(1), 1), DisplayPoint::new(DisplayRow(3), 1)..DisplayPoint::new(DisplayRow(3), 1), @@ -5862,7 +5801,7 @@ fn test_move_line_up_down(cx: &mut TestAppContext) { "ccc⋯eeee\nfffff\naa⋯bbb\nggggg\n⋯i\njjjjj" ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), vec![ DisplayPoint::new(DisplayRow(2), 1)..DisplayPoint::new(DisplayRow(2), 1), DisplayPoint::new(DisplayRow(3), 1)..DisplayPoint::new(DisplayRow(3), 1), @@ -5879,7 +5818,7 @@ fn test_move_line_up_down(cx: &mut TestAppContext) { "ccc⋯eeee\naa⋯bbb\nggggg\n⋯i\njjjjj\nfffff" ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), vec![ DisplayPoint::new(DisplayRow(1), 1)..DisplayPoint::new(DisplayRow(1), 1), DisplayPoint::new(DisplayRow(2), 1)..DisplayPoint::new(DisplayRow(2), 1), @@ -7612,7 +7551,7 @@ fn test_select_all(cx: &mut TestAppContext) { _ = editor.update(cx, |editor, window, cx| { editor.select_all(&SelectAll, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(2), 3)] ); }); @@ -7637,7 +7576,7 @@ fn test_select_line(cx: &mut TestAppContext) { }); editor.select_line(&SelectLine, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), vec![ DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(2), 0), DisplayPoint::new(DisplayRow(4), 0)..DisplayPoint::new(DisplayRow(5), 0), @@ -7648,7 +7587,7 @@ fn test_select_line(cx: &mut TestAppContext) { _ = editor.update(cx, |editor, window, cx| { editor.select_line(&SelectLine, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), vec![ DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(3), 0), DisplayPoint::new(DisplayRow(4), 0)..DisplayPoint::new(DisplayRow(5), 5), @@ -7659,7 +7598,7 @@ fn test_select_line(cx: &mut TestAppContext) { _ = editor.update(cx, |editor, window, cx| { editor.select_line(&SelectLine, window, cx); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), vec![DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(5), 5)] ); }); @@ -7784,7 +7723,7 @@ async fn test_split_selection_into_lines_interacting_with_creases(cx: &mut TestA "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii" ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [ DisplayPoint::new(DisplayRow(0), 5)..DisplayPoint::new(DisplayRow(0), 5), DisplayPoint::new(DisplayRow(1), 5)..DisplayPoint::new(DisplayRow(1), 5), @@ -8928,7 +8867,9 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut TestAppContext) { editor.select_larger_syntax_node(&SelectLargerSyntaxNode, window, cx); }); assert_eq!( - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)), + editor.update(cx, |editor, cx| editor + .selections + .display_ranges(&editor.display_snapshot(cx))), &[DisplayPoint::new(DisplayRow(5), 0)..DisplayPoint::new(DisplayRow(0), 0)] ); @@ -8937,7 +8878,9 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut TestAppContext) { editor.select_larger_syntax_node(&SelectLargerSyntaxNode, window, cx); }); assert_eq!( - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)), + editor.update(cx, |editor, cx| editor + .selections + .display_ranges(&editor.display_snapshot(cx))), &[DisplayPoint::new(DisplayRow(5), 0)..DisplayPoint::new(DisplayRow(0), 0)] ); @@ -10716,7 +10659,7 @@ async fn test_surround_with_pair(cx: &mut TestAppContext) { .unindent() ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [ DisplayPoint::new(DisplayRow(0), 3)..DisplayPoint::new(DisplayRow(0), 4), DisplayPoint::new(DisplayRow(1), 3)..DisplayPoint::new(DisplayRow(1), 4), @@ -10737,7 +10680,7 @@ async fn test_surround_with_pair(cx: &mut TestAppContext) { .unindent() ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [ DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 1), DisplayPoint::new(DisplayRow(1), 0)..DisplayPoint::new(DisplayRow(1), 1), @@ -10758,7 +10701,7 @@ async fn test_surround_with_pair(cx: &mut TestAppContext) { .unindent() ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [ DisplayPoint::new(DisplayRow(0), 1)..DisplayPoint::new(DisplayRow(0), 1), DisplayPoint::new(DisplayRow(1), 1)..DisplayPoint::new(DisplayRow(1), 1), @@ -10777,7 +10720,7 @@ async fn test_surround_with_pair(cx: &mut TestAppContext) { .unindent() ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [ DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 1), DisplayPoint::new(DisplayRow(1), 0)..DisplayPoint::new(DisplayRow(1), 1), @@ -10798,7 +10741,7 @@ async fn test_surround_with_pair(cx: &mut TestAppContext) { .unindent() ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), [ DisplayPoint::new(DisplayRow(0), 1)..DisplayPoint::new(DisplayRow(0), 1), DisplayPoint::new(DisplayRow(1), 1)..DisplayPoint::new(DisplayRow(1), 1), @@ -26025,7 +25968,7 @@ async fn test_add_selection_skip_soft_wrap_option(cx: &mut TestAppContext) { ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[ DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0), DisplayPoint::new(DisplayRow(8), 0)..DisplayPoint::new(DisplayRow(8), 0), @@ -26041,7 +25984,7 @@ async fn test_add_selection_skip_soft_wrap_option(cx: &mut TestAppContext) { ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0)] ); @@ -26054,7 +25997,7 @@ async fn test_add_selection_skip_soft_wrap_option(cx: &mut TestAppContext) { ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[ DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0), DisplayPoint::new(DisplayRow(1), 0)..DisplayPoint::new(DisplayRow(1), 0), @@ -26070,7 +26013,7 @@ async fn test_add_selection_skip_soft_wrap_option(cx: &mut TestAppContext) { ); assert_eq!( - editor.selections.display_ranges(cx), + display_ranges(editor, cx), &[DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0)] ); }); @@ -26489,14 +26432,18 @@ async fn test_select_next_prev_syntax_node(cx: &mut TestAppContext) { ]); }); - let initial_selection = editor.selections.display_ranges(cx); + let initial_selection = editor + .selections + .display_ranges(&editor.display_snapshot(cx)); assert_eq!(initial_selection.len(), 1, "Should have one selection"); // Test select next sibling - should move up levels to find the next sibling // Since "let a = 1;" has no siblings in the if block, it should move up // to find "let b = 2;" which is a sibling of the if block editor.select_next_syntax_node(&SelectNextSyntaxNode, window, cx); - let next_selection = editor.selections.display_ranges(cx); + let next_selection = editor + .selections + .display_ranges(&editor.display_snapshot(cx)); // Should have a selection and it should be different from the initial assert_eq!( @@ -26518,7 +26465,9 @@ async fn test_select_next_prev_syntax_node(cx: &mut TestAppContext) { }); editor.select_next_syntax_node(&SelectNextSyntaxNode, window, cx); - let function_next_selection = editor.selections.display_ranges(cx); + let function_next_selection = editor + .selections + .display_ranges(&editor.display_snapshot(cx)); // Should move to the next function assert_eq!( @@ -26529,7 +26478,9 @@ async fn test_select_next_prev_syntax_node(cx: &mut TestAppContext) { // Test select previous sibling navigation editor.select_prev_syntax_node(&SelectPreviousSyntaxNode, window, cx); - let prev_selection = editor.selections.display_ranges(cx); + let prev_selection = editor + .selections + .display_ranges(&editor.display_snapshot(cx)); // Should have a selection and it should be different assert_eq!( @@ -26998,7 +26949,9 @@ fn test_duplicate_line_up_on_last_line_without_newline(cx: &mut TestAppContext) ); assert_eq!( - editor.selections.display_ranges(cx), + editor + .selections + .display_ranges(&editor.display_snapshot(cx)), vec![DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0)], "Selection should move to the duplicated line" ); diff --git a/crates/editor/src/selections_collection.rs b/crates/editor/src/selections_collection.rs index 72a0fcf045955805efaa5f8dea7e6ef78525d26c..15058fa0c821fe3bf7c60d1a7bd681eb98650cfe 100644 --- a/crates/editor/src/selections_collection.rs +++ b/crates/editor/src/selections_collection.rs @@ -1,33 +1,30 @@ use std::{ - cell::Ref, cmp, fmt, iter, mem, ops::{Deref, DerefMut, Range, Sub}, sync::Arc, }; use collections::HashMap; -use gpui::{App, Entity, Pixels}; -use itertools::Itertools; +use gpui::Pixels; +use itertools::Itertools as _; use language::{Bias, Point, Selection, SelectionGoal, TextDimension}; use util::post_inc; use crate::{ - Anchor, DisplayPoint, DisplayRow, ExcerptId, MultiBuffer, MultiBufferSnapshot, SelectMode, - ToOffset, ToPoint, - display_map::{DisplayMap, DisplaySnapshot, ToDisplayPoint}, + Anchor, DisplayPoint, DisplayRow, ExcerptId, MultiBufferSnapshot, SelectMode, ToOffset, + ToPoint, + display_map::{DisplaySnapshot, ToDisplayPoint}, movement::TextLayoutDetails, }; #[derive(Debug, Clone)] pub struct PendingSelection { - pub selection: Selection, - pub mode: SelectMode, + selection: Selection, + mode: SelectMode, } #[derive(Debug, Clone)] pub struct SelectionsCollection { - display_map: Entity, - buffer: Entity, next_selection_id: usize, line_mode: bool, /// The non-pending, non-overlapping selections. @@ -40,10 +37,8 @@ pub struct SelectionsCollection { } impl SelectionsCollection { - pub fn new(display_map: Entity, buffer: Entity) -> Self { + pub fn new() -> Self { Self { - display_map, - buffer, next_selection_id: 1, line_mode: false, disjoint: Arc::default(), @@ -62,14 +57,6 @@ impl SelectionsCollection { } } - pub fn display_map(&self, cx: &mut App) -> DisplaySnapshot { - self.display_map.update(cx, |map, cx| map.snapshot(cx)) - } - - fn buffer<'a>(&self, cx: &'a App) -> Ref<'a, MultiBufferSnapshot> { - self.buffer.read(cx).read(cx) - } - pub fn clone_state(&mut self, other: &SelectionsCollection) { self.next_selection_id = other.next_selection_id; self.line_mode = other.line_mode; @@ -106,15 +93,14 @@ impl SelectionsCollection { } /// Non-overlapping selections using anchors, including the pending selection. - pub fn all_anchors(&self, cx: &mut App) -> Arc<[Selection]> { + pub fn all_anchors(&self, snapshot: &DisplaySnapshot) -> Arc<[Selection]> { if self.pending.is_none() { self.disjoint_anchors_arc() } else { - let all_offset_selections = self.all::(&self.display_map(cx)); - let buffer = self.buffer(cx); + let all_offset_selections = self.all::(snapshot); all_offset_selections .into_iter() - .map(|selection| selection_to_anchor_selection(selection, &buffer)) + .map(|selection| selection_to_anchor_selection(selection, snapshot)) .collect() } } @@ -354,16 +340,17 @@ impl SelectionsCollection { } #[cfg(any(test, feature = "test-support"))] - pub fn display_ranges(&self, cx: &mut App) -> Vec> { - let display_map = self.display_map(cx); + pub fn display_ranges(&self, display_snapshot: &DisplaySnapshot) -> Vec> { self.disjoint_anchors_arc() .iter() .chain(self.pending_anchor()) .map(|s| { if s.reversed { - s.end.to_display_point(&display_map)..s.start.to_display_point(&display_map) + s.end.to_display_point(display_snapshot) + ..s.start.to_display_point(display_snapshot) } else { - s.start.to_display_point(&display_map)..s.end.to_display_point(&display_map) + s.start.to_display_point(display_snapshot) + ..s.end.to_display_point(display_snapshot) } }) .collect() @@ -414,13 +401,13 @@ impl SelectionsCollection { pub fn change_with( &mut self, - cx: &mut App, - change: impl FnOnce(&mut MutableSelectionsCollection) -> R, + snapshot: &DisplaySnapshot, + change: impl FnOnce(&mut MutableSelectionsCollection<'_, '_>) -> R, ) -> (bool, R) { let mut mutable_collection = MutableSelectionsCollection { + snapshot, collection: self, selections_changed: false, - cx, }; let result = change(&mut mutable_collection); @@ -460,13 +447,13 @@ impl SelectionsCollection { } } -pub struct MutableSelectionsCollection<'a> { +pub struct MutableSelectionsCollection<'snap, 'a> { collection: &'a mut SelectionsCollection, + snapshot: &'snap DisplaySnapshot, selections_changed: bool, - cx: &'a mut App, } -impl<'a> fmt::Debug for MutableSelectionsCollection<'a> { +impl<'snap, 'a> fmt::Debug for MutableSelectionsCollection<'snap, 'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("MutableSelectionsCollection") .field("collection", &self.collection) @@ -475,13 +462,9 @@ impl<'a> fmt::Debug for MutableSelectionsCollection<'a> { } } -impl<'a> MutableSelectionsCollection<'a> { - pub fn display_map(&mut self) -> DisplaySnapshot { - self.collection.display_map(self.cx) - } - - pub fn buffer(&self) -> Ref<'_, MultiBufferSnapshot> { - self.collection.buffer(self.cx) +impl<'snap, 'a> MutableSelectionsCollection<'snap, 'a> { + pub fn display_snapshot(&self) -> DisplaySnapshot { + self.snapshot.clone() } pub fn clear_disjoint(&mut self) { @@ -512,12 +495,11 @@ impl<'a> MutableSelectionsCollection<'a> { } pub(crate) fn set_pending_anchor_range(&mut self, range: Range, mode: SelectMode) { - let buffer = self.buffer.read(self.cx).snapshot(self.cx); self.collection.pending = Some(PendingSelection { selection: { let mut start = range.start; let mut end = range.end; - let reversed = if start.cmp(&end, &buffer).is_gt() { + let reversed = if start.cmp(&end, self.snapshot).is_gt() { mem::swap(&mut start, &mut end); true } else { @@ -557,7 +539,7 @@ impl<'a> MutableSelectionsCollection<'a> { return true; } - if !oldest.start.cmp(&oldest.end, &self.buffer()).is_eq() { + if !oldest.start.cmp(&oldest.end, self.snapshot).is_eq() { let head = oldest.head(); oldest.start = head; oldest.end = head; @@ -573,10 +555,10 @@ impl<'a> MutableSelectionsCollection<'a> { where T: 'a + ToOffset + ToPoint + TextDimension + Ord + Sub + std::marker::Copy, { - let display_map = self.display_map(); + let display_map = self.display_snapshot(); let mut selections = self.collection.all(&display_map); - let mut start = range.start.to_offset(&self.buffer()); - let mut end = range.end.to_offset(&self.buffer()); + let mut start = range.start.to_offset(self.snapshot); + let mut end = range.end.to_offset(self.snapshot); let reversed = if start > end { mem::swap(&mut start, &mut end); true @@ -597,10 +579,9 @@ impl<'a> MutableSelectionsCollection<'a> { where T: ToOffset + std::marker::Copy + std::fmt::Debug, { - let buffer = self.buffer.read(self.cx).snapshot(self.cx); let mut selections = selections .into_iter() - .map(|selection| selection.map(|it| it.to_offset(&buffer))) + .map(|selection| selection.map(|it| it.to_offset(self.snapshot))) .map(|mut selection| { if selection.start > selection.end { mem::swap(&mut selection.start, &mut selection.end); @@ -629,14 +610,14 @@ impl<'a> MutableSelectionsCollection<'a> { self.collection.disjoint = Arc::from_iter( selections .into_iter() - .map(|selection| selection_to_anchor_selection(selection, &buffer)), + .map(|selection| selection_to_anchor_selection(selection, self.snapshot)), ); self.collection.pending = None; self.selections_changed = true; } pub fn select_anchors(&mut self, selections: Vec>) { - let map = self.display_map(); + let map = self.display_snapshot(); let resolved_selections = resolve_selections_wrapping_blocks::(&selections, &map).collect::>(); self.select(resolved_selections); @@ -647,10 +628,9 @@ impl<'a> MutableSelectionsCollection<'a> { I: IntoIterator>, T: ToOffset, { - let buffer = self.buffer.read(self.cx).snapshot(self.cx); let ranges = ranges .into_iter() - .map(|range| range.start.to_offset(&buffer)..range.end.to_offset(&buffer)); + .map(|range| range.start.to_offset(self.snapshot)..range.end.to_offset(self.snapshot)); self.select_offset_ranges(ranges); } @@ -686,13 +666,12 @@ impl<'a> MutableSelectionsCollection<'a> { where I: IntoIterator>, { - let buffer = self.buffer.read(self.cx).snapshot(self.cx); let selections = ranges .into_iter() .map(|range| { let mut start = range.start; let mut end = range.end; - let reversed = if start.cmp(&end, &buffer).is_gt() { + let reversed = if start.cmp(&end, self.snapshot).is_gt() { mem::swap(&mut start, &mut end); true } else { @@ -718,7 +697,6 @@ impl<'a> MutableSelectionsCollection<'a> { where T: IntoIterator>, { - let display_map = self.display_map(); let selections = ranges .into_iter() .map(|range| { @@ -732,8 +710,8 @@ impl<'a> MutableSelectionsCollection<'a> { }; Selection { id: post_inc(&mut self.collection.next_selection_id), - start: start.to_point(&display_map), - end: end.to_point(&display_map), + start: start.to_point(self.snapshot), + end: end.to_point(self.snapshot), reversed, goal: SelectionGoal::None, } @@ -743,7 +721,6 @@ impl<'a> MutableSelectionsCollection<'a> { } pub fn reverse_selections(&mut self) { - let map = &self.display_map(); let mut new_selections: Vec> = Vec::new(); let disjoint = self.disjoint.clone(); for selection in disjoint @@ -753,8 +730,14 @@ impl<'a> MutableSelectionsCollection<'a> { { new_selections.push(Selection { id: self.new_selection_id(), - start: selection.start.to_display_point(map).to_point(map), - end: selection.end.to_display_point(map).to_point(map), + start: selection + .start + .to_display_point(self.snapshot) + .to_point(self.snapshot), + end: selection + .end + .to_display_point(self.snapshot) + .to_point(self.snapshot), reversed: selection.reversed, goal: selection.goal, }); @@ -767,7 +750,7 @@ impl<'a> MutableSelectionsCollection<'a> { mut move_selection: impl FnMut(&DisplaySnapshot, &mut Selection), ) { let mut changed = false; - let display_map = self.display_map(); + let display_map = self.display_snapshot(); let selections = self.collection.all_display(&display_map); let selections = selections .into_iter() @@ -791,22 +774,20 @@ impl<'a> MutableSelectionsCollection<'a> { mut move_selection: impl FnMut(&MultiBufferSnapshot, &mut Selection), ) { let mut changed = false; - let snapshot = self.buffer().clone(); - let display_map = self.display_map(); + let display_map = self.display_snapshot(); let selections = self .collection .all::(&display_map) .into_iter() .map(|selection| { let mut moved_selection = selection.clone(); - move_selection(&snapshot, &mut moved_selection); + move_selection(self.snapshot, &mut moved_selection); if selection != moved_selection { changed = true; } moved_selection }) .collect(); - drop(snapshot); if changed { self.select(selections) @@ -858,11 +839,10 @@ impl<'a> MutableSelectionsCollection<'a> { &mut self, find_replacement_cursors: impl FnOnce(&DisplaySnapshot) -> Vec, ) { - let display_map = self.display_map(); - let new_selections = find_replacement_cursors(&display_map) + let new_selections = find_replacement_cursors(self.snapshot) .into_iter() .map(|cursor| { - let cursor_point = cursor.to_point(&display_map); + let cursor_point = cursor.to_point(self.snapshot); Selection { id: post_inc(&mut self.collection.next_selection_id), start: cursor_point, @@ -886,12 +866,11 @@ impl<'a> MutableSelectionsCollection<'a> { let mut selections_with_lost_position = HashMap::default(); let anchors_with_status = { - let buffer = self.buffer(); let disjoint_anchors = self .disjoint .iter() .flat_map(|selection| [&selection.start, &selection.end]); - buffer.refresh_anchors(disjoint_anchors) + self.snapshot.refresh_anchors(disjoint_anchors) }; let adjusted_disjoint: Vec<_> = anchors_with_status .chunks(2) @@ -919,16 +898,16 @@ impl<'a> MutableSelectionsCollection<'a> { .collect(); if !adjusted_disjoint.is_empty() { - let map = self.display_map(); + let map = self.display_snapshot(); let resolved_selections = resolve_selections_wrapping_blocks(adjusted_disjoint.iter(), &map).collect(); self.select::(resolved_selections); } if let Some(pending) = pending.as_mut() { - let buffer = self.buffer(); - let anchors = - buffer.refresh_anchors([&pending.selection.start, &pending.selection.end]); + let anchors = self + .snapshot + .refresh_anchors([&pending.selection.start, &pending.selection.end]); let (_, start, kept_start) = anchors[0]; let (_, end, kept_end) = anchors[1]; let kept_head = if pending.selection.reversed { @@ -951,14 +930,14 @@ impl<'a> MutableSelectionsCollection<'a> { } } -impl Deref for MutableSelectionsCollection<'_> { +impl Deref for MutableSelectionsCollection<'_, '_> { type Target = SelectionsCollection; fn deref(&self) -> &Self::Target { self.collection } } -impl DerefMut for MutableSelectionsCollection<'_> { +impl DerefMut for MutableSelectionsCollection<'_, '_> { fn deref_mut(&mut self) -> &mut Self::Target { self.collection } diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index cd25c6c1bff63839a3f15a2d1cd50f7f55987a74..d9616d85c8dddf84cde9692863cb77894e9a78e7 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -1685,7 +1685,9 @@ mod tests { assert_eq!(search_bar.active_match_index, Some(0)); search_bar.select_next_match(&SelectNextMatch, window, cx); assert_eq!( - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)), + editor.update(cx, |editor, cx| editor + .selections + .display_ranges(&editor.display_snapshot(cx))), [DisplayPoint::new(DisplayRow(0), 41)..DisplayPoint::new(DisplayRow(0), 43)] ); }); @@ -1696,7 +1698,9 @@ mod tests { search_bar.update_in(cx, |search_bar, window, cx| { search_bar.select_next_match(&SelectNextMatch, window, cx); assert_eq!( - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)), + editor.update(cx, |editor, cx| editor + .selections + .display_ranges(&editor.display_snapshot(cx))), [DisplayPoint::new(DisplayRow(3), 11)..DisplayPoint::new(DisplayRow(3), 13)] ); }); @@ -1707,7 +1711,9 @@ mod tests { search_bar.update_in(cx, |search_bar, window, cx| { search_bar.select_next_match(&SelectNextMatch, window, cx); assert_eq!( - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)), + editor.update(cx, |editor, cx| editor + .selections + .display_ranges(&editor.display_snapshot(cx))), [DisplayPoint::new(DisplayRow(3), 56)..DisplayPoint::new(DisplayRow(3), 58)] ); }); @@ -1718,7 +1724,9 @@ mod tests { search_bar.update_in(cx, |search_bar, window, cx| { search_bar.select_next_match(&SelectNextMatch, window, cx); assert_eq!( - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)), + editor.update(cx, |editor, cx| editor + .selections + .display_ranges(&editor.display_snapshot(cx))), [DisplayPoint::new(DisplayRow(0), 41)..DisplayPoint::new(DisplayRow(0), 43)] ); }); @@ -1729,7 +1737,9 @@ mod tests { search_bar.update_in(cx, |search_bar, window, cx| { search_bar.select_prev_match(&SelectPreviousMatch, window, cx); assert_eq!( - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)), + editor.update(cx, |editor, cx| editor + .selections + .display_ranges(&editor.display_snapshot(cx))), [DisplayPoint::new(DisplayRow(3), 56)..DisplayPoint::new(DisplayRow(3), 58)] ); }); @@ -1740,7 +1750,9 @@ mod tests { search_bar.update_in(cx, |search_bar, window, cx| { search_bar.select_prev_match(&SelectPreviousMatch, window, cx); assert_eq!( - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)), + editor.update(cx, |editor, cx| editor + .selections + .display_ranges(&editor.display_snapshot(cx))), [DisplayPoint::new(DisplayRow(3), 11)..DisplayPoint::new(DisplayRow(3), 13)] ); }); @@ -1751,7 +1763,9 @@ mod tests { search_bar.update_in(cx, |search_bar, window, cx| { search_bar.select_prev_match(&SelectPreviousMatch, window, cx); assert_eq!( - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)), + editor.update(cx, |editor, cx| editor + .selections + .display_ranges(&editor.display_snapshot(cx))), [DisplayPoint::new(DisplayRow(0), 41)..DisplayPoint::new(DisplayRow(0), 43)] ); }); @@ -1772,7 +1786,9 @@ mod tests { assert_eq!(search_bar.active_match_index, Some(1)); search_bar.select_prev_match(&SelectPreviousMatch, window, cx); assert_eq!( - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)), + editor.update(cx, |editor, cx| editor + .selections + .display_ranges(&editor.display_snapshot(cx))), [DisplayPoint::new(DisplayRow(0), 41)..DisplayPoint::new(DisplayRow(0), 43)] ); }); @@ -1793,7 +1809,9 @@ mod tests { assert_eq!(search_bar.active_match_index, Some(1)); search_bar.select_next_match(&SelectNextMatch, window, cx); assert_eq!( - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)), + editor.update(cx, |editor, cx| editor + .selections + .display_ranges(&editor.display_snapshot(cx))), [DisplayPoint::new(DisplayRow(3), 11)..DisplayPoint::new(DisplayRow(3), 13)] ); }); @@ -1814,7 +1832,9 @@ mod tests { assert_eq!(search_bar.active_match_index, Some(2)); search_bar.select_prev_match(&SelectPreviousMatch, window, cx); assert_eq!( - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)), + editor.update(cx, |editor, cx| editor + .selections + .display_ranges(&editor.display_snapshot(cx))), [DisplayPoint::new(DisplayRow(3), 56)..DisplayPoint::new(DisplayRow(3), 58)] ); }); @@ -1835,7 +1855,9 @@ mod tests { assert_eq!(search_bar.active_match_index, Some(2)); search_bar.select_next_match(&SelectNextMatch, window, cx); assert_eq!( - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)), + editor.update(cx, |editor, cx| editor + .selections + .display_ranges(&editor.display_snapshot(cx))), [DisplayPoint::new(DisplayRow(0), 41)..DisplayPoint::new(DisplayRow(0), 43)] ); }); @@ -1856,7 +1878,9 @@ mod tests { assert_eq!(search_bar.active_match_index, Some(0)); search_bar.select_prev_match(&SelectPreviousMatch, window, cx); assert_eq!( - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)), + editor.update(cx, |editor, cx| editor + .selections + .display_ranges(&editor.display_snapshot(cx))), [DisplayPoint::new(DisplayRow(3), 56)..DisplayPoint::new(DisplayRow(3), 58)] ); }); @@ -1989,7 +2013,7 @@ mod tests { "Initially, the editor should not be focused" ); let initial_selections = editor.update(cx, |editor, cx| { - let initial_selections = editor.selections.display_ranges(cx); + let initial_selections = editor.selections.display_ranges(&editor.display_snapshot(cx)); assert_eq!( initial_selections.len(), 1, "Expected to have only one selection before adding carets to all matches, but got: {initial_selections:?}", @@ -2008,7 +2032,7 @@ mod tests { ); search_bar.update(cx, |search_bar, cx| { let all_selections = - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)); + editor.update(cx, |editor, cx| editor.selections.display_ranges(&editor.display_snapshot(cx))); assert_eq!( all_selections.len(), expected_query_matches_count, @@ -2032,8 +2056,11 @@ mod tests { "Should still have editor focused after SelectNextMatch" ); search_bar.update(cx, |search_bar, cx| { - let all_selections = - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)); + let all_selections = editor.update(cx, |editor, cx| { + editor + .selections + .display_ranges(&editor.display_snapshot(cx)) + }); assert_eq!( all_selections.len(), 1, @@ -2062,7 +2089,7 @@ mod tests { ); search_bar.update(cx, |search_bar, cx| { let all_selections = - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)); + editor.update(cx, |editor, cx| editor.selections.display_ranges(&editor.display_snapshot(cx))); assert_eq!( all_selections.len(), expected_query_matches_count, @@ -2087,8 +2114,11 @@ mod tests { ); search_bar.update(cx, |search_bar, cx| { - let all_selections = - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)); + let all_selections = editor.update(cx, |editor, cx| { + editor + .selections + .display_ranges(&editor.display_snapshot(cx)) + }); assert_eq!( all_selections.len(), 1, @@ -2130,7 +2160,7 @@ mod tests { ); search_bar.update(cx, |search_bar, cx| { let all_selections = - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)); + editor.update(cx, |editor, cx| editor.selections.display_ranges(&editor.display_snapshot(cx))); assert_eq!( all_selections, last_match_selections, "Should not select anything new if there are no matches" @@ -2194,8 +2224,11 @@ mod tests { search_bar.select_all_matches(&SelectAllMatches, window, cx); }); search_bar.update(cx, |_, cx| { - let all_selections = - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)); + let all_selections = editor.update(cx, |editor, cx| { + editor + .selections + .display_ranges(&editor.display_snapshot(cx)) + }); assert_eq!( all_selections.len(), 2, @@ -2220,8 +2253,11 @@ mod tests { search_bar.select_all_matches(&SelectAllMatches, window, cx); }); search_bar.update(cx, |_, cx| { - let all_selections = - editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)); + let all_selections = editor.update(cx, |editor, cx| { + editor + .selections + .display_ranges(&editor.display_snapshot(cx)) + }); assert_eq!( all_selections.len(), 2, diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index f5a9c272d4846a94230286cc3ae2f7903608dd7d..a6d0db1fa03b3c406d3de2dcf40efb07528fcdd3 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -2526,7 +2526,7 @@ pub mod tests { assert_eq!( search_view .results_editor - .update(cx, |editor, cx| editor.selections.display_ranges(cx)), + .update(cx, |editor, cx| editor.selections.display_ranges(&editor.display_snapshot(cx))), [DisplayPoint::new(DisplayRow(2), 32)..DisplayPoint::new(DisplayRow(2), 35)] ); @@ -2537,9 +2537,9 @@ pub mod tests { .update(cx, |search_view, window, cx| { assert_eq!(search_view.active_match_index, Some(1)); assert_eq!( - search_view - .results_editor - .update(cx, |editor, cx| editor.selections.display_ranges(cx)), + search_view.results_editor.update(cx, |editor, cx| editor + .selections + .display_ranges(&editor.display_snapshot(cx))), [DisplayPoint::new(DisplayRow(2), 37)..DisplayPoint::new(DisplayRow(2), 40)] ); search_view.select_match(Direction::Next, window, cx); @@ -2550,9 +2550,9 @@ pub mod tests { .update(cx, |search_view, window, cx| { assert_eq!(search_view.active_match_index, Some(2)); assert_eq!( - search_view - .results_editor - .update(cx, |editor, cx| editor.selections.display_ranges(cx)), + search_view.results_editor.update(cx, |editor, cx| editor + .selections + .display_ranges(&editor.display_snapshot(cx))), [DisplayPoint::new(DisplayRow(5), 6)..DisplayPoint::new(DisplayRow(5), 9)] ); search_view.select_match(Direction::Next, window, cx); @@ -2563,9 +2563,9 @@ pub mod tests { .update(cx, |search_view, window, cx| { assert_eq!(search_view.active_match_index, Some(0)); assert_eq!( - search_view - .results_editor - .update(cx, |editor, cx| editor.selections.display_ranges(cx)), + search_view.results_editor.update(cx, |editor, cx| editor + .selections + .display_ranges(&editor.display_snapshot(cx))), [DisplayPoint::new(DisplayRow(2), 32)..DisplayPoint::new(DisplayRow(2), 35)] ); search_view.select_match(Direction::Prev, window, cx); @@ -2576,9 +2576,9 @@ pub mod tests { .update(cx, |search_view, window, cx| { assert_eq!(search_view.active_match_index, Some(2)); assert_eq!( - search_view - .results_editor - .update(cx, |editor, cx| editor.selections.display_ranges(cx)), + search_view.results_editor.update(cx, |editor, cx| editor + .selections + .display_ranges(&editor.display_snapshot(cx))), [DisplayPoint::new(DisplayRow(5), 6)..DisplayPoint::new(DisplayRow(5), 9)] ); search_view.select_match(Direction::Prev, window, cx); @@ -2589,9 +2589,9 @@ pub mod tests { .update(cx, |search_view, _, cx| { assert_eq!(search_view.active_match_index, Some(1)); assert_eq!( - search_view - .results_editor - .update(cx, |editor, cx| editor.selections.display_ranges(cx)), + search_view.results_editor.update(cx, |editor, cx| editor + .selections + .display_ranges(&editor.display_snapshot(cx))), [DisplayPoint::new(DisplayRow(2), 37)..DisplayPoint::new(DisplayRow(2), 40)] ); }) diff --git a/crates/vim/src/change_list.rs b/crates/vim/src/change_list.rs index a921d182e6ebd0ef96ef0b8d1cce75ed6d532d96..21cd3328009906e5ab24b95ca660e62caf0b4cb7 100644 --- a/crates/vim/src/change_list.rs +++ b/crates/vim/src/change_list.rs @@ -38,7 +38,7 @@ impl Vim { .map(|s| s.to_vec()) { editor.change_selections(Default::default(), window, cx, |s| { - let map = s.display_map(); + let map = s.display_snapshot(); s.select_display_ranges(selections.iter().map(|a| { let point = a.to_display_point(&map); point..point diff --git a/crates/vim/src/command.rs b/crates/vim/src/command.rs index 4b66cb1aaa7e423d202dfe03c5f5ad1d315199c0..b44ec8907399a7d744f91d9e90b397a174d5f85a 100644 --- a/crates/vim/src/command.rs +++ b/crates/vim/src/command.rs @@ -682,8 +682,9 @@ pub fn register(editor: &mut Editor, cx: &mut Context) { .disjoint_anchor_ranges() .collect::>() }); + let snapshot = editor.buffer().read(cx).snapshot(cx); editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| { - let end = Point::new(range.end.0, s.buffer().line_len(range.end)); + let end = Point::new(range.end.0, snapshot.line_len(range.end)); s.select_ranges([end..Point::new(range.start.0, 0)]); }); selections diff --git a/crates/vim/src/helix/paste.rs b/crates/vim/src/helix/paste.rs index 62d8c6caef99050cffa17a2e608a924aa97c3e99..67af7650011b0220f4ad05cebb6badf5d0ba7aa7 100644 --- a/crates/vim/src/helix/paste.rs +++ b/crates/vim/src/helix/paste.rs @@ -120,8 +120,8 @@ impl Vim { editor.edit(edits, cx); + let snapshot = editor.buffer().read(cx).snapshot(cx); editor.change_selections(Default::default(), window, cx, |s| { - let snapshot = s.buffer().clone(); s.select_ranges(new_selections.into_iter().map(|(anchor, len)| { let offset = anchor.to_offset(&snapshot); if action.before { diff --git a/crates/vim/src/vim.rs b/crates/vim/src/vim.rs index 3310c1dab1ac3c05bc24aa1b56f94dcfa22511f8..40b8dc4b56723c94e9d9a873e05d5b00cdbf9987 100644 --- a/crates/vim/src/vim.rs +++ b/crates/vim/src/vim.rs @@ -1210,7 +1210,7 @@ impl Vim { s.select_anchor_ranges(vec![pos..pos]) } - let snapshot = s.display_map(); + let snapshot = s.display_snapshot(); if let Some(pending) = s.pending_anchor_mut() && pending.reversed && mode.is_visual() diff --git a/crates/vim/src/visual.rs b/crates/vim/src/visual.rs index 17423f32dc9c235effe53d5a47edca0573bcda6f..4172de80afdc1beacbf3ea342846de03953e1fc6 100644 --- a/crates/vim/src/visual.rs +++ b/crates/vim/src/visual.rs @@ -179,7 +179,7 @@ pub fn register(editor: &mut Editor, cx: &mut Context) { vim.update_editor(cx, |_, editor, cx| { editor.set_clip_at_line_ends(false, cx); editor.change_selections(Default::default(), window, cx, |s| { - let map = s.display_map(); + let map = s.display_snapshot(); let ranges = ranges .into_iter() .map(|(start, end, reversed)| { @@ -304,7 +304,7 @@ impl Vim { ) { let text_layout_details = editor.text_layout_details(window); editor.change_selections(Default::default(), window, cx, |s| { - let map = &s.display_map(); + let map = &s.display_snapshot(); let mut head = s.newest_anchor().head().to_display_point(map); let mut tail = s.oldest_anchor().tail().to_display_point(map); diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index dbbff04b92df1f67c31e20cc33cff78cce877a2f..f50d6cf5f8bc1e5e2acadc19a4d7dcc5045000b6 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -4072,7 +4072,9 @@ mod tests { let editor = item.downcast::().unwrap(); let (selections, scroll_position) = editor.update(cx, |editor, cx| { ( - editor.selections.display_ranges(cx), + editor + .selections + .display_ranges(&editor.display_snapshot(cx)), editor.scroll_position(cx), ) });