Detailed changes
@@ -652,7 +652,9 @@ impl ContextPickerCompletionProvider {
.active_item(cx)
.and_then(|item| item.downcast::<Editor>())
.is_some_and(|editor| {
- editor.update(cx, |editor, cx| editor.has_non_empty_selection(cx))
+ editor.update(cx, |editor, cx| {
+ editor.has_non_empty_selection(&editor.display_snapshot(cx))
+ })
});
if has_selection {
entries.push(ContextPickerEntry::Action(
@@ -452,7 +452,10 @@ fn update_editor_selection(
window: &mut Window,
cx: &mut Context<Editor>,
) {
- let newest_cursor = editor.selections.newest::<Point>(cx).head();
+ let newest_cursor = editor
+ .selections
+ .newest::<Point>(&editor.display_snapshot(cx))
+ .head();
if !diff_hunks.iter().any(|hunk| {
hunk.row_range
@@ -1895,7 +1898,9 @@ mod tests {
);
assert_eq!(
editor
- .update(cx, |editor, cx| editor.selections.newest::<Point>(cx))
+ .update(cx, |editor, cx| editor
+ .selections
+ .newest::<Point>(&editor.display_snapshot(cx)))
.range(),
Point::new(1, 0)..Point::new(1, 0)
);
@@ -1909,7 +1914,9 @@ mod tests {
);
assert_eq!(
editor
- .update(cx, |editor, cx| editor.selections.newest::<Point>(cx))
+ .update(cx, |editor, cx| editor
+ .selections
+ .newest::<Point>(&editor.display_snapshot(cx)))
.range(),
Point::new(3, 0)..Point::new(3, 0)
);
@@ -1930,7 +1937,9 @@ mod tests {
);
assert_eq!(
editor
- .update(cx, |editor, cx| editor.selections.newest::<Point>(cx))
+ .update(cx, |editor, cx| editor
+ .selections
+ .newest::<Point>(&editor.display_snapshot(cx)))
.range(),
Point::new(3, 0)..Point::new(3, 0)
);
@@ -1962,7 +1971,9 @@ mod tests {
);
assert_eq!(
editor
- .update(cx, |editor, cx| editor.selections.newest::<Point>(cx))
+ .update(cx, |editor, cx| editor
+ .selections
+ .newest::<Point>(&editor.display_snapshot(cx)))
.range(),
Point::new(3, 0)..Point::new(3, 0)
);
@@ -2119,7 +2130,9 @@ mod tests {
);
assert_eq!(
editor1
- .update(cx, |editor, cx| editor.selections.newest::<Point>(cx))
+ .update(cx, |editor, cx| editor
+ .selections
+ .newest::<Point>(&editor.display_snapshot(cx)))
.range(),
Point::new(1, 0)..Point::new(1, 0)
);
@@ -2160,7 +2173,9 @@ mod tests {
);
assert_eq!(
editor1
- .update(cx, |editor, cx| editor.selections.newest::<Point>(cx))
+ .update(cx, |editor, cx| editor
+ .selections
+ .newest::<Point>(&editor.display_snapshot(cx)))
.range(),
Point::new(3, 0)..Point::new(3, 0)
);
@@ -2181,7 +2196,9 @@ mod tests {
);
assert_eq!(
editor1
- .update(cx, |editor, cx| editor.selections.newest::<Point>(cx))
+ .update(cx, |editor, cx| editor
+ .selections
+ .newest::<Point>(&editor.display_snapshot(cx)))
.range(),
Point::new(3, 0)..Point::new(3, 0)
);
@@ -2207,7 +2224,9 @@ mod tests {
);
assert_eq!(
editor1
- .update(cx, |editor, cx| editor.selections.newest::<Point>(cx))
+ .update(cx, |editor, cx| editor
+ .selections
+ .newest::<Point>(&editor.display_snapshot(cx)))
.range(),
Point::new(3, 0)..Point::new(3, 0)
);
@@ -2240,7 +2259,9 @@ mod tests {
);
assert_eq!(
editor2
- .update(cx, |editor, cx| editor.selections.newest::<Point>(cx))
+ .update(cx, |editor, cx| editor
+ .selections
+ .newest::<Point>(&editor.display_snapshot(cx)))
.range(),
Point::new(0, 0)..Point::new(0, 0)
);
@@ -606,7 +606,11 @@ pub(crate) fn available_context_picker_entries(
.read(cx)
.active_item(cx)
.and_then(|item| item.downcast::<Editor>())
- .is_some_and(|editor| editor.update(cx, |editor, cx| editor.has_non_empty_selection(cx)));
+ .is_some_and(|editor| {
+ editor.update(cx, |editor, cx| {
+ editor.has_non_empty_selection(&editor.display_snapshot(cx))
+ })
+ });
if has_selection {
entries.push(ContextPickerEntry::Action(
ContextPickerAction::AddSelections,
@@ -725,7 +729,7 @@ pub(crate) fn selection_ranges(
};
editor.update(cx, |editor, cx| {
- let selections = editor.selections.all_adjusted(cx);
+ let selections = editor.selections.all_adjusted(&editor.display_snapshot(cx));
let buffer = editor.buffer().clone().read(cx);
let snapshot = buffer.snapshot(cx);
@@ -363,9 +363,12 @@ impl InlineAssistant {
cx: &mut App,
) {
let (snapshot, initial_selections, newest_selection) = editor.update(cx, |editor, cx| {
- let selections = editor.selections.all::<Point>(cx);
- let newest_selection = editor.selections.newest::<Point>(cx);
- (editor.snapshot(window, cx), selections, newest_selection)
+ let snapshot = editor.snapshot(window, cx);
+ let selections = editor.selections.all::<Point>(&snapshot.display_snapshot);
+ let newest_selection = editor
+ .selections
+ .newest::<Point>(&snapshot.display_snapshot);
+ (snapshot, selections, newest_selection)
});
// Check if there is already an inline assistant that contains the
@@ -798,7 +801,9 @@ impl InlineAssistant {
if editor.read(cx).selections.count() == 1 {
let (selection, buffer) = editor.update(cx, |editor, cx| {
(
- editor.selections.newest::<usize>(cx),
+ editor
+ .selections
+ .newest::<usize>(&editor.display_snapshot(cx)),
editor.buffer().read(cx).snapshot(cx),
)
});
@@ -829,7 +834,9 @@ impl InlineAssistant {
if editor.read(cx).selections.count() == 1 {
let (selection, buffer) = editor.update(cx, |editor, cx| {
(
- editor.selections.newest::<usize>(cx),
+ editor
+ .selections
+ .newest::<usize>(&editor.display_snapshot(cx)),
editor.buffer().read(cx).snapshot(cx),
)
});
@@ -431,9 +431,9 @@ impl TextThreadEditor {
}
fn cursors(&self, cx: &mut App) -> Vec<usize> {
- let selections = self
- .editor
- .update(cx, |editor, cx| editor.selections.all::<usize>(cx));
+ let selections = self.editor.update(cx, |editor, cx| {
+ editor.selections.all::<usize>(&editor.display_snapshot(cx))
+ });
selections
.into_iter()
.map(|selection| selection.head())
@@ -446,7 +446,10 @@ impl TextThreadEditor {
editor.transact(window, cx, |editor, window, cx| {
editor.change_selections(Default::default(), window, cx, |s| s.try_cancel());
let snapshot = editor.buffer().read(cx).snapshot(cx);
- let newest_cursor = editor.selections.newest::<Point>(cx).head();
+ let newest_cursor = editor
+ .selections
+ .newest::<Point>(&editor.display_snapshot(cx))
+ .head();
if newest_cursor.column > 0
|| snapshot
.chars_at(newest_cursor)
@@ -1248,11 +1251,19 @@ impl TextThreadEditor {
let context_editor = context_editor_view.read(cx).editor.clone();
context_editor.update(cx, |context_editor, cx| {
- if context_editor.selections.newest::<Point>(cx).is_empty() {
+ let display_map = context_editor.display_snapshot(cx);
+ if context_editor
+ .selections
+ .newest::<Point>(&display_map)
+ .is_empty()
+ {
let snapshot = context_editor.buffer().read(cx).snapshot(cx);
let (_, _, snapshot) = snapshot.as_singleton()?;
- let head = context_editor.selections.newest::<Point>(cx).head();
+ let head = context_editor
+ .selections
+ .newest::<Point>(&display_map)
+ .head();
let offset = snapshot.point_to_offset(head);
let surrounding_code_block_range = find_surrounding_code_block(snapshot, offset)?;
@@ -1269,7 +1280,7 @@ impl TextThreadEditor {
(!text.is_empty()).then_some((text, true))
} else {
- let selection = context_editor.selections.newest_adjusted(cx);
+ let selection = context_editor.selections.newest_adjusted(&display_map);
let buffer = context_editor.buffer().read(cx).snapshot(cx);
let selected_text = buffer.text_for_range(selection.range()).collect::<String>();
@@ -1457,7 +1468,7 @@ impl TextThreadEditor {
let selections = editor.update(cx, |editor, cx| {
editor
.selections
- .all_adjusted(cx)
+ .all_adjusted(&editor.display_snapshot(cx))
.into_iter()
.filter_map(|s| {
(!s.is_empty())
@@ -1489,7 +1500,10 @@ impl TextThreadEditor {
self.editor.update(cx, |editor, cx| {
editor.insert("\n", window, cx);
for (text, crease_title) in creases {
- let point = editor.selections.newest::<Point>(cx).head();
+ let point = editor
+ .selections
+ .newest::<Point>(&editor.display_snapshot(cx))
+ .head();
let start_row = MultiBufferRow(point.row);
editor.insert(&text, window, cx);
@@ -1561,7 +1575,9 @@ impl TextThreadEditor {
cx: &mut Context<Self>,
) -> (String, CopyMetadata, Vec<text::Selection<usize>>) {
let (mut selection, creases) = self.editor.update(cx, |editor, cx| {
- let mut selection = editor.selections.newest_adjusted(cx);
+ let mut selection = editor
+ .selections
+ .newest_adjusted(&editor.display_snapshot(cx));
let snapshot = editor.buffer().read(cx).snapshot(cx);
selection.goal = SelectionGoal::None;
@@ -1680,7 +1696,10 @@ impl TextThreadEditor {
if images.is_empty() {
self.editor.update(cx, |editor, cx| {
- let paste_position = editor.selections.newest::<usize>(cx).head();
+ let paste_position = editor
+ .selections
+ .newest::<usize>(&editor.display_snapshot(cx))
+ .head();
editor.paste(action, window, cx);
if let Some(metadata) = metadata {
@@ -1727,13 +1746,13 @@ impl TextThreadEditor {
editor.transact(window, cx, |editor, _window, cx| {
let edits = editor
.selections
- .all::<usize>(cx)
+ .all::<usize>(&editor.display_snapshot(cx))
.into_iter()
.map(|selection| (selection.start..selection.end, "\n"));
editor.edit(edits, cx);
let snapshot = editor.buffer().read(cx).snapshot(cx);
- for selection in editor.selections.all::<usize>(cx) {
+ for selection in editor.selections.all::<usize>(&editor.display_snapshot(cx)) {
image_positions.push(snapshot.anchor_before(selection.end));
}
});
@@ -79,7 +79,7 @@ impl SlashCommand for SelectionCommand {
editor.update(cx, |editor, cx| {
let selection_ranges = editor
.selections
- .all_adjusted(cx)
+ .all_adjusted(&editor.display_snapshot(cx))
.iter()
.map(|selection| selection.range())
.collect::<Vec<_>>();
@@ -877,7 +877,7 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T
6..9
);
rename.editor.update(cx, |rename_editor, cx| {
- let rename_selection = rename_editor.selections.newest::<usize>(cx);
+ let rename_selection = rename_editor.selections.newest::<usize>(&rename_editor.display_snapshot(cx));
assert_eq!(
rename_selection.range(),
0..3,
@@ -924,7 +924,7 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T
let lsp_rename_end = rename.range.end.to_offset(&buffer);
assert_eq!(lsp_rename_start..lsp_rename_end, 6..9);
rename.editor.update(cx, |rename_editor, cx| {
- let rename_selection = rename_editor.selections.newest::<usize>(cx);
+ let rename_selection = rename_editor.selections.newest::<usize>(&rename_editor.display_snapshot(cx));
assert_eq!(
rename_selection.range(),
1..2,
@@ -122,13 +122,19 @@ async fn test_basic_following(
editor.handle_input("b", window, cx);
editor.handle_input("c", window, cx);
editor.select_left(&Default::default(), window, cx);
- assert_eq!(editor.selections.ranges(cx), vec![3..2]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ vec![3..2]
+ );
});
editor_a2.update_in(cx_a, |editor, window, cx| {
editor.handle_input("d", window, cx);
editor.handle_input("e", window, cx);
editor.select_left(&Default::default(), window, cx);
- assert_eq!(editor.selections.ranges(cx), vec![2..1]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ vec![2..1]
+ );
});
// When client B starts following client A, only the active view state is replicated to client B.
@@ -149,11 +155,15 @@ async fn test_basic_following(
Some((worktree_id, rel_path("2.txt")).into())
);
assert_eq!(
- editor_b2.update(cx_b, |editor, cx| editor.selections.ranges(cx)),
+ editor_b2.update(cx_b, |editor, cx| editor
+ .selections
+ .ranges(&editor.display_snapshot(cx))),
vec![2..1]
);
assert_eq!(
- editor_b1.update(cx_b, |editor, cx| editor.selections.ranges(cx)),
+ editor_b1.update(cx_b, |editor, cx| editor
+ .selections
+ .ranges(&editor.display_snapshot(cx))),
vec![3..3]
);
@@ -384,7 +394,10 @@ async fn test_basic_following(
cx_b.background_executor.run_until_parked();
editor_b1.update(cx_b, |editor, cx| {
- assert_eq!(editor.selections.ranges(cx), &[1..1, 2..2]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ &[1..1, 2..2]
+ );
});
editor_a1.update_in(cx_a, |editor, window, cx| {
@@ -402,7 +415,10 @@ async fn test_basic_following(
executor.advance_clock(workspace::item::LEADER_UPDATE_THROTTLE);
executor.run_until_parked();
editor_b1.update(cx_b, |editor, cx| {
- assert_eq!(editor.selections.ranges(cx), &[3..3]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ &[3..3]
+ );
});
// After unfollowing, client B stops receiving updates from client A.
@@ -1679,7 +1695,10 @@ async fn test_following_stops_on_unshare(cx_a: &mut TestAppContext, cx_b: &mut T
.advance_clock(workspace::item::LEADER_UPDATE_THROTTLE);
cx_a.run_until_parked();
editor_b.update(cx_b, |editor, cx| {
- assert_eq!(editor.selections.ranges(cx), vec![1..1])
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ vec![1..1]
+ )
});
// a unshares the project
@@ -1701,7 +1720,10 @@ async fn test_following_stops_on_unshare(cx_a: &mut TestAppContext, cx_b: &mut T
.advance_clock(workspace::item::LEADER_UPDATE_THROTTLE);
cx_a.run_until_parked();
editor_b.update(cx_b, |editor, cx| {
- assert_eq!(editor.selections.ranges(cx), vec![1..1])
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ vec![1..1]
+ )
});
cx_b.update(|_, cx| {
let room = ActiveCall::global(cx).read(cx).room().unwrap().read(cx);
@@ -1799,13 +1821,19 @@ async fn test_following_into_excluded_file(
editor.handle_input("b", window, cx);
editor.handle_input("c", window, cx);
editor.select_left(&Default::default(), window, cx);
- assert_eq!(editor.selections.ranges(cx), vec![3..2]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ vec![3..2]
+ );
});
editor_for_excluded_a.update_in(cx_a, |editor, window, cx| {
editor.select_all(&Default::default(), window, cx);
editor.handle_input("new commit message", window, cx);
editor.select_left(&Default::default(), window, cx);
- assert_eq!(editor.selections.ranges(cx), vec![18..17]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ vec![18..17]
+ );
});
// When client B starts following client A, currently visible file is replicated
@@ -1827,7 +1855,9 @@ async fn test_following_into_excluded_file(
Some((worktree_id, rel_path(".git/COMMIT_EDITMSG")).into())
);
assert_eq!(
- editor_for_excluded_b.update(cx_b, |editor, cx| editor.selections.ranges(cx)),
+ editor_for_excluded_b.update(cx_b, |editor, cx| editor
+ .selections
+ .ranges(&editor.display_snapshot(cx))),
vec![18..17]
);
@@ -2037,7 +2067,12 @@ async fn test_following_to_channel_notes_without_a_shared_project(
assert_eq!(notes.channel(cx).unwrap().name, "channel-1");
notes.editor.update(cx, |editor, cx| {
assert_eq!(editor.text(cx), "Hello from A.");
- assert_eq!(editor.selections.ranges::<usize>(cx), &[3..4]);
+ assert_eq!(
+ editor
+ .selections
+ .ranges::<usize>(&editor.display_snapshot(cx)),
+ &[3..4]
+ );
})
});
@@ -287,9 +287,12 @@ impl ChannelView {
}
fn copy_link(&mut self, _: &CopyLink, window: &mut Window, cx: &mut Context<Self>) {
- let position = self
- .editor
- .update(cx, |editor, cx| editor.selections.newest_display(cx).start);
+ let position = self.editor.update(cx, |editor, cx| {
+ editor
+ .selections
+ .newest_display(&editor.display_snapshot(cx))
+ .start
+ });
self.copy_link_for_position(position, window, cx)
}
@@ -698,7 +698,11 @@ mod tests {
editor.update_in(cx, |editor, window, cx| {
assert!(editor.focus_handle(cx).is_focused(window));
assert_eq!(
- editor.selections.last::<Point>(cx).range().start,
+ editor
+ .selections
+ .last::<Point>(&editor.display_snapshot(cx))
+ .range()
+ .start,
Point::new(2, 0)
);
});
@@ -341,8 +341,10 @@ pub fn init(cx: &mut App) {
maybe!({
let (buffer, position, _) = editor
.update(cx, |editor, cx| {
- let cursor_point: language::Point =
- editor.selections.newest(cx).head();
+ let cursor_point: language::Point = editor
+ .selections
+ .newest(&editor.display_snapshot(cx))
+ .head();
editor
.buffer()
@@ -392,7 +394,10 @@ pub fn init(cx: &mut App) {
let text = editor
.update(cx, |editor, cx| {
editor.text_for_range(
- editor.selections.newest(cx).range(),
+ editor
+ .selections
+ .newest(&editor.display_snapshot(cx))
+ .range(),
&mut None,
window,
cx,
@@ -963,8 +963,12 @@ mod tests {
) {
cx.set_state(input);
- let buffer_position =
- cx.editor(|editor, _, cx| editor.selections.newest::<Point>(cx).start);
+ let buffer_position = cx.editor(|editor, _, cx| {
+ editor
+ .selections
+ .newest::<Point>(&editor.display_snapshot(cx))
+ .start
+ });
let snapshot = &cx.buffer_snapshot();
@@ -55,7 +55,10 @@ impl StackTraceView {
cx.subscribe_in(&editor, window, |this, editor, event, window, cx| {
if let EditorEvent::SelectionsChanged { local: true } = event {
let excerpt_id = editor.update(cx, |editor, cx| {
- let position: Point = editor.selections.newest(cx).head();
+ let position: Point = editor
+ .selections
+ .newest(&editor.display_snapshot(cx))
+ .head();
editor
.snapshot(window, cx)
@@ -231,7 +231,10 @@ async fn test_save_debug_scenario_to_file(executor: BackgroundExecutor, cx: &mut
editor.update(cx, |editor, cx| {
assert_eq!(
- editor.selections.newest::<Point>(cx).head(),
+ editor
+ .selections
+ .newest::<Point>(&editor.display_snapshot(cx))
+ .head(),
Point::new(5, 2)
)
});
@@ -170,7 +170,10 @@ impl DiagnosticIndicator {
fn update(&mut self, editor: Entity<Editor>, window: &mut Window, cx: &mut Context<Self>) {
let (buffer, cursor_position) = editor.update(cx, |editor, cx| {
let buffer = editor.buffer().read(cx).snapshot(cx);
- let cursor_position = editor.selections.newest::<usize>(cx).head();
+ let cursor_position = editor
+ .selections
+ .newest::<usize>(&editor.display_snapshot(cx))
+ .head();
(buffer, cursor_position)
});
let new_diagnostic = buffer
@@ -2323,21 +2323,22 @@ impl Editor {
}
EditorEvent::Edited { .. } => {
if !vim_enabled(cx) {
- let (map, selections) = editor.selections.all_adjusted_display(cx);
+ let display_map = editor.display_snapshot(cx);
+ let selections = editor.selections.all_adjusted_display(&display_map);
let pop_state = editor
.change_list
.last()
.map(|previous| {
previous.len() == selections.len()
&& previous.iter().enumerate().all(|(ix, p)| {
- p.to_display_point(&map).row()
+ p.to_display_point(&display_map).row()
== selections[ix].head().row()
})
})
.unwrap_or(false);
let new_positions = selections
.into_iter()
- .map(|s| map.display_point_to_anchor(s.head(), Bias::Left))
+ .map(|s| display_map.display_point_to_anchor(s.head(), Bias::Left))
.collect();
editor
.change_list
@@ -2408,6 +2409,10 @@ impl Editor {
editor
}
+ pub fn display_snapshot(&self, cx: &mut App) -> DisplaySnapshot {
+ self.selections.display_map(cx)
+ }
+
pub fn deploy_mouse_context_menu(
&mut self,
position: gpui::Point<Pixels>,
@@ -2443,7 +2448,7 @@ impl Editor {
}
self.selections
- .disjoint_in_range::<usize>(range.clone(), cx)
+ .disjoint_in_range::<usize>(range.clone(), &self.display_snapshot(cx))
.into_iter()
.any(|selection| {
// This is needed to cover a corner case, if we just check for an existing
@@ -3039,7 +3044,7 @@ impl Editor {
// Copy selections to primary selection buffer
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
if local {
- let selections = self.selections.all::<usize>(cx);
+ let selections = self.selections.all::<usize>(&self.display_snapshot(cx));
let buffer_handle = self.buffer.read(cx).read(cx);
let mut text = String::new();
@@ -3491,7 +3496,7 @@ impl Editor {
cx: &mut Context<Self>,
) {
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
- let tail = self.selections.newest::<usize>(cx).tail();
+ let tail = self.selections.newest::<usize>(&display_map).tail();
let click_count = click_count.max(match self.selections.select_mode() {
SelectMode::Character => 1,
SelectMode::Word(_) => 2,
@@ -3610,7 +3615,7 @@ impl Editor {
let point_to_delete: Option<usize> = {
let selected_points: Vec<Selection<Point>> =
- self.selections.disjoint_in_range(start..end, cx);
+ self.selections.disjoint_in_range(start..end, &display_map);
if !add || click_count > 1 {
None
@@ -3686,7 +3691,7 @@ impl Editor {
);
};
- let tail = self.selections.newest::<Point>(cx).tail();
+ let tail = self.selections.newest::<Point>(&display_map).tail();
let selection_anchor = display_map.buffer_snapshot().anchor_before(tail);
self.columnar_selection_state = match mode {
ColumnarMode::FromMouse => Some(ColumnarSelectionState::FromMouse {
@@ -3813,7 +3818,7 @@ impl Editor {
fn end_selection(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.columnar_selection_state.take();
if let Some(pending_mode) = self.selections.pending_mode() {
- let selections = self.selections.all::<usize>(cx);
+ let selections = self.selections.all::<usize>(&self.display_snapshot(cx));
self.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
s.select(selections);
s.clear_pending();
@@ -3902,9 +3907,9 @@ impl Editor {
cx.notify();
}
- pub fn has_non_empty_selection(&self, cx: &mut App) -> bool {
+ pub fn has_non_empty_selection(&self, snapshot: &DisplaySnapshot) -> bool {
self.selections
- .all_adjusted(cx)
+ .all_adjusted(snapshot)
.iter()
.any(|selection| !selection.is_empty())
}
@@ -4053,7 +4058,7 @@ impl Editor {
self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx);
- let selections = self.selections.all_adjusted(cx);
+ let selections = self.selections.all_adjusted(&self.display_snapshot(cx));
let mut bracket_inserted = false;
let mut edits = Vec::new();
let mut linked_edits = HashMap::<_, Vec<_>>::default();
@@ -4403,7 +4408,7 @@ impl Editor {
let trigger_in_words =
this.show_edit_predictions_in_menu() || !had_active_edit_prediction;
if this.hard_wrap.is_some() {
- let latest: Range<Point> = this.selections.newest(cx).range();
+ let latest: Range<Point> = this.selections.newest(&map).range();
if latest.is_empty()
&& this
.buffer()
@@ -4479,7 +4484,7 @@ impl Editor {
self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx);
self.transact(window, cx, |this, window, cx| {
let (edits_with_flags, selection_info): (Vec<_>, Vec<_>) = {
- let selections = this.selections.all::<usize>(cx);
+ let selections = this.selections.all::<usize>(&this.display_snapshot(cx));
let multi_buffer = this.buffer.read(cx);
let buffer = multi_buffer.snapshot(cx);
selections
@@ -4771,7 +4776,12 @@ impl Editor {
let mut edits = Vec::new();
let mut rows = Vec::new();
- for (rows_inserted, selection) in self.selections.all_adjusted(cx).into_iter().enumerate() {
+ for (rows_inserted, selection) in self
+ .selections
+ .all_adjusted(&self.display_snapshot(cx))
+ .into_iter()
+ .enumerate()
+ {
let cursor = selection.head();
let row = cursor.row;
@@ -4831,7 +4841,7 @@ impl Editor {
let mut rows = Vec::new();
let mut rows_inserted = 0;
- for selection in self.selections.all_adjusted(cx) {
+ for selection in self.selections.all_adjusted(&self.display_snapshot(cx)) {
let cursor = selection.head();
let row = cursor.row;
@@ -4903,7 +4913,7 @@ impl Editor {
let text: Arc<str> = text.into();
self.transact(window, cx, |this, window, cx| {
- let old_selections = this.selections.all_adjusted(cx);
+ let old_selections = this.selections.all_adjusted(&this.display_snapshot(cx));
let selection_anchors = this.buffer.update(cx, |buffer, cx| {
let anchors = {
let snapshot = buffer.read(cx);
@@ -5013,7 +5023,7 @@ impl Editor {
/// If any empty selections is touching the start of its innermost containing autoclose
/// region, expand it to select the brackets.
fn select_autoclose_pair(&mut self, window: &mut Window, cx: &mut Context<Self>) {
- let selections = self.selections.all::<usize>(cx);
+ let selections = self.selections.all::<usize>(&self.display_snapshot(cx));
let buffer = self.buffer.read(cx).read(cx);
let new_selections = self
.selections_with_autoclose_regions(selections, &buffer)
@@ -6010,7 +6020,7 @@ impl Editor {
let prefix = &old_text[..old_text.len().saturating_sub(lookahead)];
let suffix = &old_text[lookbehind.min(old_text.len())..];
- let selections = self.selections.all::<usize>(cx);
+ let selections = self.selections.all::<usize>(&self.display_snapshot(cx));
let mut ranges = Vec::new();
let mut linked_edits = HashMap::<_, Vec<_>>::default();
@@ -6162,7 +6172,10 @@ impl Editor {
Some(CodeActionSource::Indicator(row)) | Some(CodeActionSource::RunMenu(row)) => {
DisplayPoint::new(*row, 0).to_point(&snapshot)
}
- _ => self.selections.newest::<Point>(cx).head(),
+ _ => self
+ .selections
+ .newest::<Point>(&snapshot.display_snapshot)
+ .head(),
};
let Some((buffer, buffer_row)) = snapshot
.buffer_snapshot()
@@ -6624,7 +6637,9 @@ impl Editor {
if newest_selection.head().diff_base_anchor.is_some() {
return None;
}
- let newest_selection_adjusted = this.selections.newest_adjusted(cx);
+ let display_snapshot = this.display_snapshot(cx);
+ let newest_selection_adjusted =
+ this.selections.newest_adjusted(&display_snapshot);
let buffer = this.buffer.read(cx);
let (start_buffer, start) =
@@ -6699,7 +6714,10 @@ impl Editor {
pub fn blame_hover(&mut self, _: &BlameHover, window: &mut Window, cx: &mut Context<Self>) {
let snapshot = self.snapshot(window, cx);
- let cursor = self.selections.newest::<Point>(cx).head();
+ let cursor = self
+ .selections
+ .newest::<Point>(&snapshot.display_snapshot)
+ .head();
let Some((buffer, point, _)) = snapshot.buffer_snapshot().point_to_buffer_point(cursor)
else {
return;
@@ -7572,7 +7590,10 @@ impl Editor {
// Find an insertion that starts at the cursor position.
let snapshot = self.buffer.read(cx).snapshot(cx);
- let cursor_offset = self.selections.newest::<usize>(cx).head();
+ let cursor_offset = self
+ .selections
+ .newest::<usize>(&self.display_snapshot(cx))
+ .head();
let insertion = edits.iter().find_map(|(range, text)| {
let range = range.to_offset(&snapshot);
if range.is_empty() && range.start == cursor_offset {
@@ -8528,7 +8549,11 @@ impl Editor {
&mut self,
cx: &mut Context<Self>,
) -> Option<(Entity<Buffer>, u32, Arc<RunnableTasks>)> {
- let cursor_row = self.selections.newest_adjusted(cx).head().row;
+ let cursor_row = self
+ .selections
+ .newest_adjusted(&self.display_snapshot(cx))
+ .head()
+ .row;
let ((buffer_id, row), tasks) = self
.tasks
@@ -8545,7 +8570,10 @@ impl Editor {
cx: &mut Context<Self>,
) -> Option<(Entity<Buffer>, u32, Arc<RunnableTasks>)> {
let snapshot = self.buffer.read(cx).snapshot(cx);
- let offset = self.selections.newest::<usize>(cx).head();
+ let offset = self
+ .selections
+ .newest::<usize>(&self.display_snapshot(cx))
+ .head();
let excerpt = snapshot.excerpt_containing(offset..offset)?;
let buffer_id = excerpt.buffer().remote_id();
@@ -9862,8 +9890,7 @@ impl Editor {
// Check whether the just-entered snippet ends with an auto-closable bracket.
if self.autoclose_regions.is_empty() {
let snapshot = self.buffer.read(cx).snapshot(cx);
- let mut all_selections = self.selections.all::<Point>(cx);
- for selection in &mut all_selections {
+ for selection in &mut self.selections.all::<Point>(&self.display_snapshot(cx)) {
let selection_head = selection.head();
let Some(scope) = snapshot.language_scope_at(selection_head) else {
continue;
@@ -10001,9 +10028,12 @@ impl Editor {
self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx);
self.transact(window, cx, |this, window, cx| {
this.select_autoclose_pair(window, cx);
+
+ let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
+
let mut linked_ranges = HashMap::<_, Vec<_>>::default();
if !this.linked_edit_ranges.is_empty() {
- let selections = this.selections.all::<MultiBufferPoint>(cx);
+ let selections = this.selections.all::<MultiBufferPoint>(&display_map);
let snapshot = this.buffer.read(cx).snapshot(cx);
for selection in selections.iter() {
@@ -10022,8 +10052,7 @@ impl Editor {
}
}
- let mut selections = this.selections.all::<MultiBufferPoint>(cx);
- let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
+ let mut selections = this.selections.all::<MultiBufferPoint>(&display_map);
for selection in &mut selections {
if selection.is_empty() {
let old_head = selection.head();
@@ -10138,7 +10167,7 @@ impl Editor {
return;
}
self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx);
- let mut selections = self.selections.all_adjusted(cx);
+ let mut selections = self.selections.all_adjusted(&self.display_snapshot(cx));
let buffer = self.buffer.read(cx);
let snapshot = buffer.snapshot(cx);
let rows_iter = selections.iter().map(|s| s.head().row);
@@ -10254,7 +10283,7 @@ impl Editor {
}
self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx);
- let mut selections = self.selections.all::<Point>(cx);
+ let mut selections = self.selections.all::<Point>(&self.display_snapshot(cx));
let mut prev_edited_row = 0;
let mut row_delta = 0;
let mut edits = Vec::new();
@@ -10363,7 +10392,7 @@ impl Editor {
self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx);
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
- let selections = self.selections.all::<Point>(cx);
+ let selections = self.selections.all::<Point>(&display_map);
let mut deletion_ranges = Vec::new();
let mut last_outdent = None;
{
@@ -10424,7 +10453,7 @@ impl Editor {
cx,
);
});
- let selections = this.selections.all::<usize>(cx);
+ let selections = this.selections.all::<usize>(&this.display_snapshot(cx));
this.change_selections(Default::default(), window, cx, |s| s.select(selections));
});
}
@@ -10441,7 +10470,7 @@ impl Editor {
self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx);
let selections = self
.selections
- .all::<usize>(cx)
+ .all::<usize>(&self.display_snapshot(cx))
.into_iter()
.map(|s| s.range());
@@ -10449,7 +10478,7 @@ impl Editor {
this.buffer.update(cx, |buffer, cx| {
buffer.autoindent_ranges(selections, cx);
});
- let selections = this.selections.all::<usize>(cx);
+ let selections = this.selections.all::<usize>(&this.display_snapshot(cx));
this.change_selections(Default::default(), window, cx, |s| s.select(selections));
});
}
@@ -10457,7 +10486,7 @@ impl Editor {
pub fn delete_line(&mut self, _: &DeleteLine, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx);
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
- let selections = self.selections.all::<Point>(cx);
+ let selections = self.selections.all::<Point>(&display_map);
let mut new_cursors = Vec::new();
let mut edit_ranges = Vec::new();
@@ -10551,7 +10580,7 @@ impl Editor {
return;
}
let mut row_ranges = Vec::<Range<MultiBufferRow>>::new();
- for selection in self.selections.all::<Point>(cx) {
+ for selection in self.selections.all::<Point>(&self.display_snapshot(cx)) {
let start = MultiBufferRow(selection.start.row);
// Treat single line selections as if they include the next line. Otherwise this action
// would do nothing for single line selections individual cursors.
@@ -10694,7 +10723,11 @@ impl Editor {
let mut edits = Vec::new();
let mut boundaries = Vec::new();
- for selection in self.selections.all::<Point>(cx).iter() {
+ for selection in self
+ .selections
+ .all::<Point>(&self.display_snapshot(cx))
+ .iter()
+ {
let Some(wrap_config) = snapshot
.language_at(selection.start)
.and_then(|lang| lang.config().wrap_characters.clone())
@@ -10764,7 +10797,7 @@ impl Editor {
self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx);
let mut buffer_ids = HashSet::default();
let snapshot = self.buffer().read(cx).snapshot(cx);
- for selection in self.selections.all::<usize>(cx) {
+ for selection in self.selections.all::<usize>(&self.display_snapshot(cx)) {
buffer_ids.extend(snapshot.buffer_ids_for_range(selection.range()))
}
@@ -10781,7 +10814,7 @@ impl Editor {
self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx);
let selections = self
.selections
- .all(cx)
+ .all(&self.display_snapshot(cx))
.into_iter()
.map(|s| s.range())
.collect();
@@ -11189,7 +11222,7 @@ impl Editor {
let mut edits = Vec::new();
- let selections = self.selections.all::<Point>(cx);
+ let selections = self.selections.all::<Point>(&display_map);
let mut selections = selections.iter().peekable();
let mut contiguous_row_selections = Vec::new();
let mut new_selections = Vec::new();
@@ -11591,7 +11624,7 @@ impl Editor {
let mut edits = Vec::new();
let mut selection_adjustment = 0i32;
- for selection in self.selections.all_adjusted(cx) {
+ for selection in self.selections.all_adjusted(&self.display_snapshot(cx)) {
let selection_is_empty = selection.is_empty();
let (start, end) = if selection_is_empty {
@@ -11683,7 +11716,7 @@ impl Editor {
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let buffer = display_map.buffer_snapshot();
- let selections = self.selections.all::<Point>(cx);
+ let selections = self.selections.all::<Point>(&display_map);
let mut edits = Vec::new();
let mut selections_iter = selections.iter().peekable();
@@ -11791,7 +11824,7 @@ impl Editor {
let mut unfold_ranges = Vec::new();
let mut refold_creases = Vec::new();
- let selections = self.selections.all::<Point>(cx);
+ let selections = self.selections.all::<Point>(&display_map);
let mut selections = selections.iter().peekable();
let mut contiguous_row_selections = Vec::new();
let mut new_selections = Vec::new();
@@ -11902,7 +11935,7 @@ impl Editor {
let mut unfold_ranges = Vec::new();
let mut refold_creases = Vec::new();
- let selections = self.selections.all::<Point>(cx);
+ let selections = self.selections.all::<Point>(&display_map);
let mut selections = selections.iter().peekable();
let mut contiguous_row_selections = Vec::new();
let mut new_selections = Vec::new();
@@ -12035,7 +12068,7 @@ impl Editor {
});
this.buffer
.update(cx, |buffer, cx| buffer.edit(edits, None, cx));
- let selections = this.selections.all::<usize>(cx);
+ let selections = this.selections.all::<usize>(&this.display_snapshot(cx));
this.change_selections(Default::default(), window, cx, |s| {
s.select(selections);
});
@@ -12054,7 +12087,7 @@ impl Editor {
pub fn rewrap_impl(&mut self, options: RewrapOptions, cx: &mut Context<Self>) {
let buffer = self.buffer.read(cx).snapshot(cx);
- let selections = self.selections.all::<Point>(cx);
+ let selections = self.selections.all::<Point>(&self.display_snapshot(cx));
#[derive(Clone, Debug, PartialEq)]
enum CommentFormat {
@@ -12430,7 +12463,7 @@ impl Editor {
) -> ClipboardItem {
let mut text = String::new();
let buffer = self.buffer.read(cx).snapshot(cx);
- let mut selections = self.selections.all::<Point>(cx);
+ let mut selections = self.selections.all::<Point>(&self.display_snapshot(cx));
let mut clipboard_selections = Vec::with_capacity(selections.len());
{
let max_point = buffer.max_point();
@@ -12526,7 +12559,7 @@ impl Editor {
}
fn do_copy(&self, strip_leading_indents: bool, cx: &mut Context<Self>) {
- let selections = self.selections.all::<Point>(cx);
+ let selections = self.selections.all::<Point>(&self.display_snapshot(cx));
let buffer = self.buffer.read(cx).read(cx);
let mut text = String::new();
@@ -12637,8 +12670,9 @@ impl Editor {
self.transact(window, cx, |this, window, cx| {
let had_active_edit_prediction = this.has_active_edit_prediction();
- let old_selections = this.selections.all::<usize>(cx);
- let cursor_offset = this.selections.last::<usize>(cx).head();
+ let display_map = this.display_snapshot(cx);
+ let old_selections = this.selections.all::<usize>(&display_map);
+ let cursor_offset = this.selections.last::<usize>(&display_map).head();
if let Some(mut clipboard_selections) = clipboard_selections {
let all_selections_were_entire_line =
@@ -12719,7 +12753,7 @@ impl Editor {
);
});
- let selections = this.selections.all::<usize>(cx);
+ let selections = this.selections.all::<usize>(&this.display_snapshot(cx));
this.change_selections(Default::default(), window, cx, |s| s.select(selections));
} else {
let url = url::Url::parse(&clipboard_text).ok();
@@ -12784,7 +12818,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
- let selections = self.selections.all::<usize>(cx);
+ let selections = self.selections.all::<usize>(&self.display_snapshot(cx));
if selections.is_empty() {
log::warn!("There should always be at least one selection in Zed. This is a bug.");
@@ -14047,7 +14081,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
- let mut selection = self.selections.last::<Point>(cx);
+ let mut selection = self.selections.last::<Point>(&self.display_snapshot(cx));
selection.set_head(Point::zero(), SelectionGoal::None);
self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
self.change_selections(Default::default(), window, cx, |s| {
@@ -14126,7 +14160,7 @@ impl Editor {
pub fn select_to_end(&mut self, _: &SelectToEnd, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
let buffer = self.buffer.read(cx).snapshot(cx);
- let mut selection = self.selections.first::<usize>(cx);
+ let mut selection = self.selections.first::<usize>(&self.display_snapshot(cx));
selection.set_head(buffer.len(), SelectionGoal::None);
self.change_selections(Default::default(), window, cx, |s| {
s.select(vec![selection]);
@@ -14144,7 +14178,7 @@ impl Editor {
pub fn select_line(&mut self, _: &SelectLine, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
- let mut selections = self.selections.all::<Point>(cx);
+ let mut selections = self.selections.all::<Point>(&display_map);
let max_point = display_map.buffer_snapshot().max_point();
for selection in &mut selections {
let rows = selection.spanned_rows(true, &display_map);
@@ -14165,7 +14199,7 @@ impl Editor {
) {
let selections = self
.selections
- .all::<Point>(cx)
+ .all::<Point>(&self.display_snapshot(cx))
.into_iter()
.map(|selection| selection.start..selection.end)
.collect::<Vec<_>>();
@@ -14244,7 +14278,7 @@ impl Editor {
self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
- let all_selections = self.selections.all::<Point>(cx);
+ let all_selections = self.selections.all::<Point>(&display_map);
let text_layout_details = self.text_layout_details(window);
let (mut columnar_selections, new_selections_to_columnarize) = {
@@ -14378,7 +14412,7 @@ impl Editor {
let final_selection_ids: HashSet<_> = self
.selections
- .all::<Point>(cx)
+ .all::<Point>(&display_map)
.iter()
.map(|s| s.id)
.collect();
@@ -14436,7 +14470,7 @@ impl Editor {
cx: &mut Context<Self>,
) -> Result<()> {
let buffer = display_map.buffer_snapshot();
- let mut selections = self.selections.all::<usize>(cx);
+ let mut selections = self.selections.all::<usize>(&display_map);
if let Some(mut select_next_state) = self.select_next_state.take() {
let query = &select_next_state.query;
if !select_next_state.done {
@@ -14610,7 +14644,7 @@ impl Editor {
let mut new_selections = Vec::new();
- let reversed = self.selections.oldest::<usize>(cx).reversed;
+ let reversed = self.selections.oldest::<usize>(&display_map).reversed;
let buffer = display_map.buffer_snapshot();
let query_matches = select_next_state
.query
@@ -14674,7 +14708,7 @@ impl Editor {
self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let buffer = display_map.buffer_snapshot();
- let mut selections = self.selections.all::<usize>(cx);
+ let mut selections = self.selections.all::<usize>(&display_map);
if let Some(mut select_prev_state) = self.select_prev_state.take() {
let query = &select_prev_state.query;
if !select_prev_state.done {
@@ -14862,7 +14896,9 @@ impl Editor {
self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx);
let text_layout_details = &self.text_layout_details(window);
self.transact(window, cx, |this, window, cx| {
- let mut selections = this.selections.all::<MultiBufferPoint>(cx);
+ let mut selections = this
+ .selections
+ .all::<MultiBufferPoint>(&this.display_snapshot(cx));
let mut edits = Vec::new();
let mut selection_edit_ranges = Vec::new();
let mut last_toggled_row = None;
@@ -15093,7 +15129,7 @@ impl Editor {
// Adjust selections so that they end before any comment suffixes that
// were inserted.
let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
- let mut selections = this.selections.all::<Point>(cx);
+ let mut selections = this.selections.all::<Point>(&this.display_snapshot(cx));
let snapshot = this.buffer.read(cx).read(cx);
for selection in &mut selections {
while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
@@ -15119,7 +15155,7 @@ impl Editor {
drop(snapshot);
this.change_selections(Default::default(), window, cx, |s| s.select(selections));
- let selections = this.selections.all::<Point>(cx);
+ let selections = this.selections.all::<Point>(&this.display_snapshot(cx));
let selections_on_single_row = selections.windows(2).all(|selections| {
selections[0].start.row == selections[1].start.row
&& selections[0].end.row == selections[1].end.row
@@ -15163,7 +15199,10 @@ impl Editor {
self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
let buffer = self.buffer.read(cx).snapshot(cx);
- let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
+ let old_selections = self
+ .selections
+ .all::<usize>(&self.display_snapshot(cx))
+ .into_boxed_slice();
fn update_selection(
selection: &Selection<usize>,
@@ -15218,7 +15257,10 @@ impl Editor {
let Some(visible_row_count) = self.visible_row_count() else {
return;
};
- let old_selections: Box<[_]> = self.selections.all::<usize>(cx).into();
+ let old_selections: Box<[_]> = self
+ .selections
+ .all::<usize>(&self.display_snapshot(cx))
+ .into();
if old_selections.is_empty() {
return;
}
@@ -15376,7 +15418,7 @@ impl Editor {
let buffer = self.buffer.read(cx).snapshot(cx);
let selections = self
.selections
- .all::<usize>(cx)
+ .all::<usize>(&self.display_snapshot(cx))
.into_iter()
// subtracting the offset requires sorting
.sorted_by_key(|i| i.start);
@@ -15448,7 +15490,10 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
- let old_selections: Box<[_]> = self.selections.all::<usize>(cx).into();
+ let old_selections: Box<[_]> = self
+ .selections
+ .all::<usize>(&self.display_snapshot(cx))
+ .into();
if old_selections.is_empty() {
return;
}
@@ -15497,7 +15542,10 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
- let old_selections: Box<[_]> = self.selections.all::<usize>(cx).into();
+ let old_selections: Box<[_]> = self
+ .selections
+ .all::<usize>(&self.display_snapshot(cx))
+ .into();
if old_selections.is_empty() {
return;
}
@@ -16046,7 +16094,7 @@ impl Editor {
cx: &mut Context<Self>,
) {
let buffer = self.buffer.read(cx).snapshot(cx);
- let selection = self.selections.newest::<usize>(cx);
+ let selection = self.selections.newest::<usize>(&self.display_snapshot(cx));
let mut active_group_id = None;
if let ActiveDiagnostic::Group(active_group) = &self.active_diagnostics
@@ -16127,7 +16175,7 @@ impl Editor {
pub fn go_to_next_hunk(&mut self, _: &GoToHunk, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
let snapshot = self.snapshot(window, cx);
- let selection = self.selections.newest::<Point>(cx);
+ let selection = self.selections.newest::<Point>(&self.display_snapshot(cx));
self.go_to_hunk_before_or_after_position(
&snapshot,
selection.head(),
@@ -16188,7 +16236,7 @@ impl Editor {
) {
self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
let snapshot = self.snapshot(window, cx);
- let selection = self.selections.newest::<Point>(cx);
+ let selection = self.selections.newest::<Point>(&snapshot.display_snapshot);
self.go_to_hunk_before_or_after_position(
&snapshot,
selection.head(),
@@ -16278,7 +16326,10 @@ impl Editor {
self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
let snapshot = self.snapshot(window, cx);
let buffer = &snapshot.buffer_snapshot();
- let position = self.selections.newest::<Point>(cx).head();
+ let position = self
+ .selections
+ .newest::<Point>(&snapshot.display_snapshot)
+ .head();
let anchor_position = buffer.anchor_after(position);
// Get all document highlights (both read and write)
@@ -16461,7 +16512,10 @@ impl Editor {
let Some(provider) = self.semantics_provider.clone() else {
return Task::ready(Ok(Navigated::No));
};
- let head = self.selections.newest::<usize>(cx).head();
+ let head = self
+ .selections
+ .newest::<usize>(&self.display_snapshot(cx))
+ .head();
let buffer = self.buffer.read(cx);
let Some((buffer, head)) = buffer.text_anchor_for_position(head, cx) else {
return Task::ready(Ok(Navigated::No));
@@ -16792,7 +16846,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) -> Option<Task<Result<Navigated>>> {
- let selection = self.selections.newest::<usize>(cx);
+ let selection = self.selections.newest::<usize>(&self.display_snapshot(cx));
let multi_buffer = self.buffer.read(cx);
let head = selection.head();
@@ -17267,7 +17321,10 @@ impl Editor {
if moving_cursor {
let cursor_in_rename_editor = rename.editor.update(cx, |editor, cx| {
- editor.selections.newest::<usize>(cx).head()
+ editor
+ .selections
+ .newest::<usize>(&editor.display_snapshot(cx))
+ .head()
});
// Update the selection to match the position of the selection inside
@@ -17330,7 +17387,7 @@ impl Editor {
let ranges = self
.selections
- .all_adjusted(cx)
+ .all_adjusted(&self.display_snapshot(cx))
.into_iter()
.map(|selection| selection.range())
.collect_vec();
@@ -18029,9 +18086,9 @@ impl Editor {
cx: &mut Context<Self>,
) {
if self.buffer_kind(cx) == ItemBufferKind::Singleton {
- let selection = self.selections.newest::<Point>(cx);
-
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+ let selection = self.selections.newest::<Point>(&display_map);
+
let range = if selection.is_empty() {
let point = selection.head().to_display_point(&display_map);
let start = DisplayPoint::new(point.row(), 0).to_point(&display_map);
@@ -18074,7 +18131,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
- let selection = self.selections.newest::<Point>(cx);
+ let selection = self.selections.newest::<Point>(&self.display_snapshot(cx));
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let range = if selection.is_empty() {
@@ -18097,7 +18154,7 @@ impl Editor {
if self.buffer_kind(cx) == ItemBufferKind::Singleton {
let mut to_fold = Vec::new();
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
- let selections = self.selections.all_adjusted(cx);
+ let selections = self.selections.all_adjusted(&display_map);
for selection in selections {
let range = selection.range().sorted();
@@ -18204,7 +18261,7 @@ impl Editor {
let row_ranges_to_keep: Vec<Range<u32>> = self
.selections
- .all::<Point>(cx)
+ .all::<Point>(&self.display_snapshot(cx))
.into_iter()
.map(|sel| sel.start.row..sel.end.row)
.collect();
@@ -18379,7 +18436,7 @@ impl Editor {
) {
let mut to_fold = Vec::new();
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
- let selections = self.selections.all_adjusted(cx);
+ let selections = self.selections.all_adjusted(&display_map);
for selection in selections {
let range = selection.range().sorted();
@@ -18423,7 +18480,7 @@ impl Editor {
if let Some(crease) = display_map.crease_for_buffer_row(buffer_row) {
let autoscroll = self
.selections
- .all::<Point>(cx)
+ .all::<Point>(&display_map)
.iter()
.any(|selection| crease.range().overlaps(&selection.range()));
@@ -18435,7 +18492,7 @@ impl Editor {
if self.buffer_kind(cx) == ItemBufferKind::Singleton {
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let buffer = display_map.buffer_snapshot();
- let selections = self.selections.all::<Point>(cx);
+ let selections = self.selections.all::<Point>(&display_map);
let ranges = selections
.iter()
.map(|s| {
@@ -18469,7 +18526,7 @@ impl Editor {
cx: &mut Context<Self>,
) {
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
- let selections = self.selections.all::<Point>(cx);
+ let selections = self.selections.all::<Point>(&display_map);
let ranges = selections
.iter()
.map(|s| {
@@ -18501,7 +18558,7 @@ impl Editor {
let autoscroll = self
.selections
- .all::<Point>(cx)
+ .all::<Point>(&display_map)
.iter()
.any(|selection| RangeExt::overlaps(&selection.range(), &intersection_range));
@@ -18536,8 +18593,8 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
- let selections = self.selections.all_adjusted(cx);
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+ let selections = self.selections.all_adjusted(&display_map);
let ranges = selections
.into_iter()
.map(|s| Crease::simple(s.range(), display_map.fold_placeholder.clone()))
@@ -18870,7 +18927,10 @@ impl Editor {
self.stage_or_unstage_diff_hunks(stage, ranges, cx);
let snapshot = self.snapshot(window, cx);
- let position = self.selections.newest::<Point>(cx).head();
+ let position = self
+ .selections
+ .newest::<Point>(&snapshot.display_snapshot)
+ .head();
let mut row = snapshot
.buffer_snapshot()
.diff_hunks_in_range(position..snapshot.buffer_snapshot().max_point())
@@ -19018,7 +19078,7 @@ impl Editor {
let snapshot = self.snapshot(window, cx);
let hunks = snapshot.hunks_for_ranges(
self.selections
- .all(cx)
+ .all(&snapshot.display_snapshot)
.into_iter()
.map(|selection| selection.range()),
);
@@ -19754,7 +19814,10 @@ impl Editor {
) -> Option<()> {
let blame = self.blame.as_ref()?;
let snapshot = self.snapshot(window, cx);
- let cursor = self.selections.newest::<Point>(cx).head();
+ let cursor = self
+ .selections
+ .newest::<Point>(&snapshot.display_snapshot)
+ .head();
let (buffer, point, _) = snapshot.buffer_snapshot().point_to_buffer_point(cursor)?;
let (_, blame_entry) = blame
.update(cx, |blame, cx| {
@@ -19896,7 +19959,7 @@ impl Editor {
fn get_permalink_to_line(&self, cx: &mut Context<Self>) -> Task<Result<url::Url>> {
let buffer_and_selection = maybe!({
- let selection = self.selections.newest::<Point>(cx);
+ let selection = self.selections.newest::<Point>(&self.display_snapshot(cx));
let selection_range = selection.range();
let multi_buffer = self.buffer().read(cx);
@@ -19974,7 +20037,12 @@ impl Editor {
_: &mut Window,
cx: &mut Context<Self>,
) {
- let selection = self.selections.newest::<Point>(cx).start.row + 1;
+ let selection = self
+ .selections
+ .newest::<Point>(&self.display_snapshot(cx))
+ .start
+ .row
+ + 1;
if let Some(file) = self.target_file(cx) {
let path = file.path().display(file.path_style(cx));
cx.write_to_clipboard(ClipboardItem::new_string(format!("{path}:{selection}")));
@@ -20045,7 +20113,7 @@ impl Editor {
self.transact(window, cx, |this, window, cx| {
let edits = this
.selections
- .all::<Point>(cx)
+ .all::<Point>(&this.display_snapshot(cx))
.into_iter()
.map(|selection| {
let uuid = match version {
@@ -21131,7 +21199,7 @@ impl Editor {
return;
};
- let selections = self.selections.all::<usize>(cx);
+ let selections = self.selections.all::<usize>(&self.display_snapshot(cx));
let multi_buffer = self.buffer.read(cx);
let multi_buffer_snapshot = multi_buffer.snapshot(cx);
let mut new_selections_by_buffer = HashMap::default();
@@ -21255,7 +21323,7 @@ impl Editor {
}
}
None => {
- let selections = self.selections.all::<usize>(cx);
+ let selections = self.selections.all::<usize>(&self.display_snapshot(cx));
let multi_buffer = self.buffer.read(cx);
for selection in selections {
for (snapshot, range, _, anchor) in multi_buffer
@@ -21393,7 +21461,9 @@ impl Editor {
range: Range<OffsetUtf16>,
cx: &mut App,
) -> Vec<Range<OffsetUtf16>> {
- let selections = self.selections.all::<OffsetUtf16>(cx);
+ let selections = self
+ .selections
+ .all::<OffsetUtf16>(&self.display_snapshot(cx));
let newest_selection = selections
.iter()
.max_by_key(|selection| selection.id)
@@ -21556,7 +21626,10 @@ impl Editor {
cx: &mut Context<Self>,
) {
self.request_autoscroll(Autoscroll::newest(), cx);
- let position = self.selections.newest_display(cx).start;
+ let position = self
+ .selections
+ .newest_display(&self.display_snapshot(cx))
+ .start;
mouse_context_menu::deploy_context_menu(self, None, position, window, cx);
}
@@ -21576,7 +21649,9 @@ impl Editor {
return;
}
if let Some(relative_utf16_range) = relative_utf16_range {
- let selections = self.selections.all::<OffsetUtf16>(cx);
+ let selections = self
+ .selections
+ .all::<OffsetUtf16>(&self.display_snapshot(cx));
self.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
let new_ranges = selections.into_iter().map(|range| {
let start = OffsetUtf16(
@@ -21716,7 +21791,7 @@ impl Editor {
}
let transaction =
self.transact(window, cx, |this, window, cx| {
- let selections = this.selections.all::<usize>(cx);
+ let selections = this.selections.all::<usize>(&this.display_snapshot(cx));
let edits = selections
.iter()
.map(|selection| (selection.end..selection.end, pending.clone()));
@@ -21735,7 +21810,7 @@ impl Editor {
let snapshot = self.snapshot(window, cx);
let ranges = self
.selections
- .all::<usize>(cx)
+ .all::<usize>(&snapshot.display_snapshot)
.into_iter()
.map(|selection| {
snapshot.buffer_snapshot().anchor_after(selection.end)
@@ -23867,7 +23942,9 @@ impl EntityInputHandler for Editor {
return None;
}
- let selection = self.selections.newest::<OffsetUtf16>(cx);
+ let selection = self
+ .selections
+ .newest::<OffsetUtf16>(&self.display_snapshot(cx));
let range = selection.range();
Some(UTF16Selection {
@@ -23910,7 +23987,7 @@ impl EntityInputHandler for Editor {
let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
let newest_selection_id = this.selections.newest_anchor().id;
this.selections
- .all::<OffsetUtf16>(cx)
+ .all::<OffsetUtf16>(&this.display_snapshot(cx))
.iter()
.zip(ranges_to_replace.iter())
.find_map(|(selection, range)| {
@@ -23985,7 +24062,7 @@ impl EntityInputHandler for Editor {
let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
let newest_selection_id = this.selections.newest_anchor().id;
this.selections
- .all::<OffsetUtf16>(cx)
+ .all::<OffsetUtf16>(&this.display_snapshot(cx))
.iter()
.zip(ranges_to_replace.iter())
.find_map(|(selection, range)| {
@@ -219,7 +219,10 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) {
editor.insert("cd", window, cx);
editor.end_transaction_at(now, cx);
assert_eq!(editor.text(cx), "12cd56");
- assert_eq!(editor.selections.ranges(cx), vec![4..4]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ vec![4..4]
+ );
editor.start_transaction_at(now, window, cx);
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
@@ -228,7 +231,10 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) {
editor.insert("e", window, cx);
editor.end_transaction_at(now, cx);
assert_eq!(editor.text(cx), "12cde6");
- assert_eq!(editor.selections.ranges(cx), vec![5..5]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ vec![5..5]
+ );
now += group_interval + Duration::from_millis(1);
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
@@ -244,30 +250,45 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) {
});
assert_eq!(editor.text(cx), "ab2cde6");
- assert_eq!(editor.selections.ranges(cx), vec![3..3]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ vec![3..3]
+ );
// Last transaction happened past the group interval in a different editor.
// Undo it individually and don't restore selections.
editor.undo(&Undo, window, cx);
assert_eq!(editor.text(cx), "12cde6");
- assert_eq!(editor.selections.ranges(cx), vec![2..2]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ vec![2..2]
+ );
// First two transactions happened within the group interval in this editor.
// Undo them together and restore selections.
editor.undo(&Undo, window, cx);
editor.undo(&Undo, window, cx); // Undo stack is empty here, so this is a no-op.
assert_eq!(editor.text(cx), "123456");
- assert_eq!(editor.selections.ranges(cx), vec![0..0]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ vec![0..0]
+ );
// Redo the first two transactions together.
editor.redo(&Redo, window, cx);
assert_eq!(editor.text(cx), "12cde6");
- assert_eq!(editor.selections.ranges(cx), vec![5..5]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ vec![5..5]
+ );
// Redo the last transaction on its own.
editor.redo(&Redo, window, cx);
assert_eq!(editor.text(cx), "ab2cde6");
- assert_eq!(editor.selections.ranges(cx), vec![6..6]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ vec![6..6]
+ );
// Test empty transactions.
editor.start_transaction_at(now, window, cx);
@@ -770,10 +791,14 @@ fn test_clone(cx: &mut TestAppContext) {
);
assert_set_eq!(
cloned_editor
- .update(cx, |editor, _, cx| editor.selections.ranges::<Point>(cx))
+ .update(cx, |editor, _, cx| editor
+ .selections
+ .ranges::<Point>(&editor.display_snapshot(cx)))
.unwrap(),
editor
- .update(cx, |editor, _, cx| editor.selections.ranges(cx))
+ .update(cx, |editor, _, cx| editor
+ .selections
+ .ranges(&editor.display_snapshot(cx)))
.unwrap()
);
assert_set_eq!(
@@ -3161,7 +3186,7 @@ fn test_newline_with_old_selections(cx: &mut TestAppContext) {
);
});
assert_eq!(
- editor.selections.ranges(cx),
+ editor.selections.ranges(&editor.display_snapshot(cx)),
&[
Point::new(1, 2)..Point::new(1, 2),
Point::new(2, 2)..Point::new(2, 2),
@@ -3183,7 +3208,7 @@ fn test_newline_with_old_selections(cx: &mut TestAppContext) {
// The selections are moved after the inserted newlines
assert_eq!(
- editor.selections.ranges(cx),
+ editor.selections.ranges(&editor.display_snapshot(cx)),
&[
Point::new(2, 0)..Point::new(2, 0),
Point::new(4, 0)..Point::new(4, 0),
@@ -3673,13 +3698,19 @@ fn test_insert_with_old_selections(cx: &mut TestAppContext) {
buffer.edit([(2..5, ""), (10..13, ""), (18..21, "")], None, cx);
assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
});
- assert_eq!(editor.selections.ranges(cx), &[2..2, 7..7, 12..12],);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ &[2..2, 7..7, 12..12],
+ );
editor.insert("Z", window, cx);
assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
// The selections are moved after the inserted characters
- assert_eq!(editor.selections.ranges(cx), &[3..3, 9..9, 15..15],);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ &[3..3, 9..9, 15..15],
+ );
});
}
@@ -4439,7 +4470,9 @@ fn test_join_lines_with_single_selection(cx: &mut TestAppContext) {
let buffer = buffer.read(cx).as_singleton().unwrap();
assert_eq!(
- editor.selections.ranges::<Point>(cx),
+ editor
+ .selections
+ .ranges::<Point>(&editor.display_snapshot(cx)),
&[Point::new(0, 0)..Point::new(0, 0)]
);
@@ -4447,7 +4480,9 @@ fn test_join_lines_with_single_selection(cx: &mut TestAppContext) {
editor.join_lines(&JoinLines, window, cx);
assert_eq!(buffer.read(cx).text(), "aaa bbb\nccc\nddd\n\n");
assert_eq!(
- editor.selections.ranges::<Point>(cx),
+ editor
+ .selections
+ .ranges::<Point>(&editor.display_snapshot(cx)),
&[Point::new(0, 3)..Point::new(0, 3)]
);
@@ -4458,7 +4493,9 @@ fn test_join_lines_with_single_selection(cx: &mut TestAppContext) {
editor.join_lines(&JoinLines, window, cx);
assert_eq!(buffer.read(cx).text(), "aaa bbb ccc ddd\n\n");
assert_eq!(
- editor.selections.ranges::<Point>(cx),
+ editor
+ .selections
+ .ranges::<Point>(&editor.display_snapshot(cx)),
&[Point::new(0, 11)..Point::new(0, 11)]
);
@@ -4466,7 +4503,9 @@ fn test_join_lines_with_single_selection(cx: &mut TestAppContext) {
editor.undo(&Undo, window, cx);
assert_eq!(buffer.read(cx).text(), "aaa bbb\nccc\nddd\n\n");
assert_eq!(
- editor.selections.ranges::<Point>(cx),
+ editor
+ .selections
+ .ranges::<Point>(&editor.display_snapshot(cx)),
&[Point::new(0, 5)..Point::new(2, 2)]
);
@@ -4477,7 +4516,9 @@ fn test_join_lines_with_single_selection(cx: &mut TestAppContext) {
editor.join_lines(&JoinLines, window, cx);
assert_eq!(buffer.read(cx).text(), "aaa bbb\nccc\nddd\n");
assert_eq!(
- editor.selections.ranges::<Point>(cx),
+ editor
+ .selections
+ .ranges::<Point>(&editor.display_snapshot(cx)),
[Point::new(2, 3)..Point::new(2, 3)]
);
@@ -4485,7 +4526,9 @@ fn test_join_lines_with_single_selection(cx: &mut TestAppContext) {
editor.join_lines(&JoinLines, window, cx);
assert_eq!(buffer.read(cx).text(), "aaa bbb\nccc\nddd");
assert_eq!(
- editor.selections.ranges::<Point>(cx),
+ editor
+ .selections
+ .ranges::<Point>(&editor.display_snapshot(cx)),
[Point::new(2, 3)..Point::new(2, 3)]
);
@@ -4493,7 +4536,9 @@ fn test_join_lines_with_single_selection(cx: &mut TestAppContext) {
editor.join_lines(&JoinLines, window, cx);
assert_eq!(buffer.read(cx).text(), "aaa bbb\nccc\nddd");
assert_eq!(
- editor.selections.ranges::<Point>(cx),
+ editor
+ .selections
+ .ranges::<Point>(&editor.display_snapshot(cx)),
[Point::new(2, 3)..Point::new(2, 3)]
);
@@ -4550,7 +4595,9 @@ fn test_join_lines_with_multi_selection(cx: &mut TestAppContext) {
assert_eq!(buffer.read(cx).text(), "aaa bbb ccc\nddd\n");
assert_eq!(
- editor.selections.ranges::<Point>(cx),
+ editor
+ .selections
+ .ranges::<Point>(&editor.display_snapshot(cx)),
[
Point::new(0, 7)..Point::new(0, 7),
Point::new(1, 3)..Point::new(1, 3)
@@ -5908,15 +5955,24 @@ fn test_transpose(cx: &mut TestAppContext) {
});
editor.transpose(&Default::default(), window, cx);
assert_eq!(editor.text(cx), "bac");
- assert_eq!(editor.selections.ranges(cx), [2..2]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ [2..2]
+ );
editor.transpose(&Default::default(), window, cx);
assert_eq!(editor.text(cx), "bca");
- assert_eq!(editor.selections.ranges(cx), [3..3]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ [3..3]
+ );
editor.transpose(&Default::default(), window, cx);
assert_eq!(editor.text(cx), "bac");
- assert_eq!(editor.selections.ranges(cx), [3..3]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ [3..3]
+ );
editor
});
@@ -5929,22 +5985,34 @@ fn test_transpose(cx: &mut TestAppContext) {
});
editor.transpose(&Default::default(), window, cx);
assert_eq!(editor.text(cx), "acb\nde");
- assert_eq!(editor.selections.ranges(cx), [3..3]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ [3..3]
+ );
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
s.select_ranges([4..4])
});
editor.transpose(&Default::default(), window, cx);
assert_eq!(editor.text(cx), "acbd\ne");
- assert_eq!(editor.selections.ranges(cx), [5..5]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ [5..5]
+ );
editor.transpose(&Default::default(), window, cx);
assert_eq!(editor.text(cx), "acbde\n");
- assert_eq!(editor.selections.ranges(cx), [6..6]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ [6..6]
+ );
editor.transpose(&Default::default(), window, cx);
assert_eq!(editor.text(cx), "acbd\ne");
- assert_eq!(editor.selections.ranges(cx), [6..6]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ [6..6]
+ );
editor
});
@@ -5957,23 +6025,38 @@ fn test_transpose(cx: &mut TestAppContext) {
});
editor.transpose(&Default::default(), window, cx);
assert_eq!(editor.text(cx), "bacd\ne");
- assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ [2..2, 3..3, 5..5]
+ );
editor.transpose(&Default::default(), window, cx);
assert_eq!(editor.text(cx), "bcade\n");
- assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ [3..3, 4..4, 6..6]
+ );
editor.transpose(&Default::default(), window, cx);
assert_eq!(editor.text(cx), "bcda\ne");
- assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ [4..4, 6..6]
+ );
editor.transpose(&Default::default(), window, cx);
assert_eq!(editor.text(cx), "bcade\n");
- assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ [4..4, 6..6]
+ );
editor.transpose(&Default::default(), window, cx);
assert_eq!(editor.text(cx), "bcaed\n");
- assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ [5..5, 6..6]
+ );
editor
});
@@ -5986,15 +6069,24 @@ fn test_transpose(cx: &mut TestAppContext) {
});
editor.transpose(&Default::default(), window, cx);
assert_eq!(editor.text(cx), "🏀🍐✋");
- assert_eq!(editor.selections.ranges(cx), [8..8]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ [8..8]
+ );
editor.transpose(&Default::default(), window, cx);
assert_eq!(editor.text(cx), "🏀✋🍐");
- assert_eq!(editor.selections.ranges(cx), [11..11]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ [11..11]
+ );
editor.transpose(&Default::default(), window, cx);
assert_eq!(editor.text(cx), "🏀🍐✋");
- assert_eq!(editor.selections.ranges(cx), [11..11]);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ [11..11]
+ );
editor
});
@@ -9540,7 +9632,7 @@ async fn test_autoindent(cx: &mut TestAppContext) {
editor.newline(&Newline, window, cx);
assert_eq!(editor.text(cx), "fn a(\n \n) {\n \n}\n");
assert_eq!(
- editor.selections.ranges(cx),
+ editor.selections.ranges(&editor.display_snapshot(cx)),
&[
Point::new(1, 4)..Point::new(1, 4),
Point::new(3, 4)..Point::new(3, 4),
@@ -9616,7 +9708,7 @@ async fn test_autoindent_disabled(cx: &mut TestAppContext) {
)
);
assert_eq!(
- editor.selections.ranges(cx),
+ editor.selections.ranges(&editor.display_snapshot(cx)),
&[
Point::new(1, 0)..Point::new(1, 0),
Point::new(3, 0)..Point::new(3, 0),
@@ -10255,7 +10347,9 @@ async fn test_autoclose_with_embedded_language(cx: &mut TestAppContext) {
// Precondition: different languages are active at different locations.
cx.update_editor(|editor, window, cx| {
let snapshot = editor.snapshot(window, cx);
- let cursors = editor.selections.ranges::<usize>(cx);
+ let cursors = editor
+ .selections
+ .ranges::<usize>(&editor.display_snapshot(cx));
let languages = cursors
.iter()
.map(|c| snapshot.language_at(c.start).unwrap().name())
@@ -10700,7 +10794,9 @@ async fn test_delete_autoclose_pair(cx: &mut TestAppContext) {
.unindent()
);
assert_eq!(
- editor.selections.ranges::<Point>(cx),
+ editor
+ .selections
+ .ranges::<Point>(&editor.display_snapshot(cx)),
[
Point::new(0, 4)..Point::new(0, 4),
Point::new(1, 4)..Point::new(1, 4),
@@ -10720,7 +10816,9 @@ async fn test_delete_autoclose_pair(cx: &mut TestAppContext) {
.unindent()
);
assert_eq!(
- editor.selections.ranges::<Point>(cx),
+ editor
+ .selections
+ .ranges::<Point>(&editor.display_snapshot(cx)),
[
Point::new(0, 2)..Point::new(0, 2),
Point::new(1, 2)..Point::new(1, 2),
@@ -10739,7 +10837,9 @@ async fn test_delete_autoclose_pair(cx: &mut TestAppContext) {
.unindent()
);
assert_eq!(
- editor.selections.ranges::<Point>(cx),
+ editor
+ .selections
+ .ranges::<Point>(&editor.display_snapshot(cx)),
[
Point::new(0, 1)..Point::new(0, 1),
Point::new(1, 1)..Point::new(1, 1),
@@ -10945,7 +11045,12 @@ async fn test_snippet_placeholder_choices(cx: &mut TestAppContext) {
fn assert(editor: &mut Editor, cx: &mut Context<Editor>, marked_text: &str) {
let (expected_text, selection_ranges) = marked_text_ranges(marked_text, false);
assert_eq!(editor.text(cx), expected_text);
- assert_eq!(editor.selections.ranges::<usize>(cx), selection_ranges);
+ assert_eq!(
+ editor
+ .selections
+ .ranges::<usize>(&editor.display_snapshot(cx)),
+ selection_ranges
+ );
}
assert(
@@ -10976,7 +11081,7 @@ async fn test_snippets(cx: &mut TestAppContext) {
let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
let insertion_ranges = editor
.selections
- .all(cx)
+ .all(&editor.display_snapshot(cx))
.iter()
.map(|s| s.range())
.collect::<Vec<_>>();
@@ -11056,7 +11161,7 @@ async fn test_snippet_indentation(cx: &mut TestAppContext) {
.unwrap();
let insertion_ranges = editor
.selections
- .all(cx)
+ .all(&editor.display_snapshot(cx))
.iter()
.map(|s| s.range())
.collect::<Vec<_>>();
@@ -15945,7 +16050,7 @@ fn test_editing_disjoint_excerpts(cx: &mut TestAppContext) {
editor.handle_input("X", window, cx);
assert_eq!(editor.text(cx), "Xaaaa\nXbbbb");
assert_eq!(
- editor.selections.ranges(cx),
+ editor.selections.ranges(&editor.display_snapshot(cx)),
[
Point::new(0, 1)..Point::new(0, 1),
Point::new(1, 1)..Point::new(1, 1),
@@ -15959,7 +16064,7 @@ fn test_editing_disjoint_excerpts(cx: &mut TestAppContext) {
editor.backspace(&Default::default(), window, cx);
assert_eq!(editor.text(cx), "Xa\nbbb");
assert_eq!(
- editor.selections.ranges(cx),
+ editor.selections.ranges(&editor.display_snapshot(cx)),
[Point::new(1, 0)..Point::new(1, 0)]
);
@@ -15969,7 +16074,7 @@ fn test_editing_disjoint_excerpts(cx: &mut TestAppContext) {
editor.backspace(&Default::default(), window, cx);
assert_eq!(editor.text(cx), "X\nbb");
assert_eq!(
- editor.selections.ranges(cx),
+ editor.selections.ranges(&editor.display_snapshot(cx)),
[Point::new(0, 1)..Point::new(0, 1)]
);
});
@@ -16027,7 +16132,10 @@ fn test_editing_overlapping_excerpts(cx: &mut TestAppContext) {
false,
);
assert_eq!(editor.text(cx), expected_text);
- assert_eq!(editor.selections.ranges(cx), expected_selections);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ expected_selections
+ );
editor.newline(&Newline, window, cx);
let (expected_text, expected_selections) = marked_text_ranges(
@@ -16044,7 +16152,10 @@ fn test_editing_overlapping_excerpts(cx: &mut TestAppContext) {
false,
);
assert_eq!(editor.text(cx), expected_text);
- assert_eq!(editor.selections.ranges(cx), expected_selections);
+ assert_eq!(
+ editor.selections.ranges(&editor.display_snapshot(cx)),
+ expected_selections
+ );
});
}
@@ -16085,7 +16196,7 @@ fn test_refresh_selections(cx: &mut TestAppContext) {
cx,
);
assert_eq!(
- editor.selections.ranges(cx),
+ editor.selections.ranges(&editor.display_snapshot(cx)),
[
Point::new(1, 3)..Point::new(1, 3),
Point::new(2, 1)..Point::new(2, 1),
@@ -16098,7 +16209,7 @@ fn test_refresh_selections(cx: &mut TestAppContext) {
_ = editor.update(cx, |editor, window, cx| {
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| s.refresh());
assert_eq!(
- editor.selections.ranges(cx),
+ editor.selections.ranges(&editor.display_snapshot(cx)),
[
Point::new(1, 3)..Point::new(1, 3),
Point::new(2, 1)..Point::new(2, 1),
@@ -16112,7 +16223,7 @@ fn test_refresh_selections(cx: &mut TestAppContext) {
_ = editor.update(cx, |editor, window, cx| {
// Removing an excerpt causes the first selection to become degenerate.
assert_eq!(
- editor.selections.ranges(cx),
+ editor.selections.ranges(&editor.display_snapshot(cx)),
[
Point::new(0, 0)..Point::new(0, 0),
Point::new(0, 1)..Point::new(0, 1)
@@ -16123,7 +16234,7 @@ fn test_refresh_selections(cx: &mut TestAppContext) {
// location.
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| s.refresh());
assert_eq!(
- editor.selections.ranges(cx),
+ editor.selections.ranges(&editor.display_snapshot(cx)),
[
Point::new(0, 1)..Point::new(0, 1),
Point::new(0, 3)..Point::new(0, 3)
@@ -16167,7 +16278,7 @@ fn test_refresh_selections_while_selecting_with_mouse(cx: &mut TestAppContext) {
cx,
);
assert_eq!(
- editor.selections.ranges(cx),
+ editor.selections.ranges(&editor.display_snapshot(cx)),
[Point::new(1, 3)..Point::new(1, 3)]
);
editor
@@ -16178,14 +16289,14 @@ fn test_refresh_selections_while_selecting_with_mouse(cx: &mut TestAppContext) {
});
_ = editor.update(cx, |editor, window, cx| {
assert_eq!(
- editor.selections.ranges(cx),
+ editor.selections.ranges(&editor.display_snapshot(cx)),
[Point::new(0, 0)..Point::new(0, 0)]
);
// Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| s.refresh());
assert_eq!(
- editor.selections.ranges(cx),
+ editor.selections.ranges(&editor.display_snapshot(cx)),
[Point::new(0, 3)..Point::new(0, 3)]
);
assert!(editor.selections.pending_anchor().is_some());
@@ -16435,7 +16546,10 @@ async fn test_following(cx: &mut TestAppContext) {
.await
.unwrap();
_ = follower.update(cx, |follower, _, cx| {
- assert_eq!(follower.selections.ranges(cx), vec![1..1]);
+ assert_eq!(
+ follower.selections.ranges(&follower.display_snapshot(cx)),
+ vec![1..1]
+ );
});
assert!(*is_still_following.borrow());
assert_eq!(*follower_edit_event_count.borrow(), 0);
@@ -16488,7 +16602,10 @@ async fn test_following(cx: &mut TestAppContext) {
.unwrap();
_ = follower.update(cx, |follower, _, cx| {
assert_eq!(follower.scroll_position(cx), gpui::Point::new(1.5, 0.0));
- assert_eq!(follower.selections.ranges(cx), vec![0..0]);
+ assert_eq!(
+ follower.selections.ranges(&follower.display_snapshot(cx)),
+ vec![0..0]
+ );
});
assert!(*is_still_following.borrow());
@@ -16512,7 +16629,10 @@ async fn test_following(cx: &mut TestAppContext) {
.await
.unwrap();
_ = follower.update(cx, |follower, _, cx| {
- assert_eq!(follower.selections.ranges(cx), vec![0..0, 1..1]);
+ assert_eq!(
+ follower.selections.ranges(&follower.display_snapshot(cx)),
+ vec![0..0, 1..1]
+ );
});
assert!(*is_still_following.borrow());
@@ -16533,7 +16653,10 @@ async fn test_following(cx: &mut TestAppContext) {
.await
.unwrap();
_ = follower.update(cx, |follower, _, cx| {
- assert_eq!(follower.selections.ranges(cx), vec![0..2]);
+ assert_eq!(
+ follower.selections.ranges(&follower.display_snapshot(cx)),
+ vec![0..2]
+ );
});
// Scrolling locally breaks the follow
@@ -22668,11 +22791,11 @@ fn add_log_breakpoint_at_cursor(
.first()
.and_then(|(anchor, bp)| bp.as_ref().map(|bp| (*anchor, bp.clone())))
.unwrap_or_else(|| {
- let cursor_position: Point = editor.selections.newest(cx).head();
+ let snapshot = editor.snapshot(window, cx);
+ let cursor_position: Point =
+ editor.selections.newest(&snapshot.display_snapshot).head();
- let breakpoint_position = editor
- .snapshot(window, cx)
- .display_snapshot
+ let breakpoint_position = snapshot
.buffer_snapshot()
.anchor_before(Point::new(cursor_position.row, 0));
@@ -23619,7 +23742,7 @@ println!("5");
assert_eq!(
editor
.selections
- .all::<Point>(cx)
+ .all::<Point>(&editor.display_snapshot(cx))
.into_iter()
.map(|s| s.range())
.collect::<Vec<_>>(),
@@ -23662,7 +23785,7 @@ println!("5");
assert_eq!(
editor
.selections
- .all::<Point>(cx)
+ .all::<Point>(&editor.display_snapshot(cx))
.into_iter()
.map(|s| s.range())
.collect::<Vec<_>>(),
@@ -23788,7 +23911,7 @@ println!("5");
assert_eq!(
editor
.selections
- .all::<Point>(cx)
+ .all::<Point>(&editor.display_snapshot(cx))
.into_iter()
.map(|s| s.range())
.collect::<Vec<_>>(),
@@ -23814,7 +23937,7 @@ println!("5");
assert_eq!(
editor
.selections
- .all::<Point>(cx)
+ .all::<Point>(&editor.display_snapshot(cx))
.into_iter()
.map(|s| s.range())
.collect::<Vec<_>>(),
@@ -25211,7 +25334,7 @@ fn assert_selection_ranges(marked_text: &str, editor: &mut Editor, cx: &mut Cont
let (text, ranges) = marked_text_ranges(marked_text, true);
assert_eq!(editor.text(cx), text);
assert_eq!(
- editor.selections.ranges(cx),
+ editor.selections.ranges(&editor.display_snapshot(cx)),
ranges,
"Assert selections are {}",
marked_text
@@ -1377,7 +1377,7 @@ impl EditorElement {
editor_with_selections.update(cx, |editor, cx| {
if editor.show_local_selections {
let mut layouts = Vec::new();
- let newest = editor.selections.newest(cx);
+ let newest = editor.selections.newest(&editor.display_snapshot(cx));
for selection in local_selections.iter().cloned() {
let is_empty = selection.start == selection.end;
let is_newest = selection == newest;
@@ -3195,7 +3195,9 @@ impl EditorElement {
let (newest_selection_head, is_relative) = self.editor.update(cx, |editor, cx| {
let newest_selection_head = newest_selection_head.unwrap_or_else(|| {
- let newest = editor.selections.newest::<Point>(cx);
+ let newest = editor
+ .selections
+ .newest::<Point>(&editor.display_snapshot(cx));
SelectionLayout::new(
newest,
editor.selections.line_mode(),
@@ -8793,7 +8795,8 @@ impl Element for EditorElement {
.editor_with_selections(cx)
.map(|editor| {
editor.update(cx, |editor, cx| {
- let all_selections = editor.selections.all::<Point>(cx);
+ let all_selections =
+ editor.selections.all::<Point>(&snapshot.display_snapshot);
let selected_buffer_ids =
if editor.buffer_kind(cx) == ItemBufferKind::Singleton {
Vec::new()
@@ -8815,10 +8818,12 @@ impl Element for EditorElement {
selected_buffer_ids
};
- let mut selections = editor
- .selections
- .disjoint_in_range(start_anchor..end_anchor, cx);
- selections.extend(editor.selections.pending(cx));
+ let mut selections = editor.selections.disjoint_in_range(
+ start_anchor..end_anchor,
+ &snapshot.display_snapshot,
+ );
+ selections
+ .extend(editor.selections.pending(&snapshot.display_snapshot));
(selections, selected_buffer_ids)
})
@@ -69,7 +69,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Editor>,
) -> Option<HashSet<usize>> {
- let selection = self.selections.newest::<Point>(cx);
+ let selection = self.selections.newest::<Point>(&self.display_snapshot(cx));
let cursor_row = MultiBufferRow(selection.head().row);
let state = &mut self.active_indent_guides_state;
@@ -594,7 +594,7 @@ impl Item for Editor {
cx: &mut Context<Self>,
) -> bool {
if let Ok(data) = data.downcast::<NavigationData>() {
- let newest_selection = self.selections.newest::<Point>(cx);
+ let newest_selection = self.selections.newest::<Point>(&self.display_snapshot(cx));
let buffer = self.buffer.read(cx).read(cx);
let offset = if buffer.can_resolve(&data.cursor_anchor) {
data.cursor_anchor.to_point(&buffer)
@@ -1539,13 +1539,13 @@ impl SearchableItem for Editor {
fn query_suggestion(&mut self, window: &mut Window, cx: &mut Context<Self>) -> String {
let setting = EditorSettings::get_global(cx).seed_search_query_from_cursor;
let snapshot = self.snapshot(window, cx);
- let snapshot = snapshot.buffer_snapshot();
- let selection = self.selections.newest_adjusted(cx);
+ let selection = self.selections.newest_adjusted(&snapshot.display_snapshot);
+ let buffer_snapshot = snapshot.buffer_snapshot();
match setting {
SeedQuerySetting::Never => String::new(),
SeedQuerySetting::Selection | SeedQuerySetting::Always if !selection.is_empty() => {
- let text: String = snapshot
+ let text: String = buffer_snapshot
.text_for_range(selection.start..selection.end)
.collect();
if text.contains('\n') {
@@ -1556,10 +1556,10 @@ impl SearchableItem for Editor {
}
SeedQuerySetting::Selection => String::new(),
SeedQuerySetting::Always => {
- let (range, kind) =
- snapshot.surrounding_word(selection.start, Some(CharScopeContext::Completion));
+ let (range, kind) = buffer_snapshot
+ .surrounding_word(selection.start, Some(CharScopeContext::Completion));
if kind == Some(CharKind::Word) {
- let text: String = snapshot.text_for_range(range).collect();
+ let text: String = buffer_snapshot.text_for_range(range).collect();
if !text.trim().is_empty() {
return text;
}
@@ -59,7 +59,7 @@ pub(super) fn refresh_linked_ranges(
let mut applicable_selections = Vec::new();
editor
.update(cx, |editor, cx| {
- let selections = editor.selections.all::<usize>(cx);
+ let selections = editor.selections.all::<usize>(&editor.display_snapshot(cx));
let snapshot = editor.buffer.read(cx).snapshot(cx);
let buffer = editor.buffer.read(cx);
for selection in selections {
@@ -154,7 +154,7 @@ pub fn deploy_context_menu(
return;
}
- let display_map = editor.selections.display_map(cx);
+ let display_map = editor.display_snapshot(cx);
let source_anchor = display_map.display_point_to_anchor(point, text::Bias::Right);
let context_menu = if let Some(custom) = editor.custom_context_menu.take() {
let menu = custom(editor, point, window, cx);
@@ -169,8 +169,8 @@ pub fn deploy_context_menu(
return;
};
- let display_map = editor.selections.display_map(cx);
let snapshot = editor.snapshot(window, cx);
+ let display_map = editor.display_snapshot(cx);
let buffer = snapshot.buffer_snapshot();
let anchor = buffer.anchor_before(point.to_point(&display_map));
if !display_ranges(&display_map, &editor.selections).any(|r| r.contains(&point)) {
@@ -185,7 +185,7 @@ pub fn deploy_context_menu(
let has_reveal_target = editor.target_file(cx).is_some();
let has_selections = editor
.selections
- .all::<PointUtf16>(cx)
+ .all::<PointUtf16>(&display_map)
.into_iter()
.any(|s| !s.is_empty());
let has_git_repo = buffer
@@ -72,7 +72,12 @@ impl Editor {
cx: &mut Context<Editor>,
) {
let scroll_margin_rows = self.vertical_scroll_margin() as u32;
- let new_screen_top = self.selections.newest_display(cx).head().row().0;
+ let new_screen_top = self
+ .selections
+ .newest_display(&self.display_snapshot(cx))
+ .head()
+ .row()
+ .0;
let new_screen_top = new_screen_top.saturating_sub(scroll_margin_rows);
self.set_scroll_top_row(DisplayRow(new_screen_top), window, cx);
}
@@ -86,7 +91,12 @@ impl Editor {
let Some(visible_rows) = self.visible_line_count().map(|count| count as u32) else {
return;
};
- let new_screen_top = self.selections.newest_display(cx).head().row().0;
+ let new_screen_top = self
+ .selections
+ .newest_display(&self.display_snapshot(cx))
+ .head()
+ .row()
+ .0;
let new_screen_top = new_screen_top.saturating_sub(visible_rows / 2);
self.set_scroll_top_row(DisplayRow(new_screen_top), window, cx);
}
@@ -101,7 +111,12 @@ impl Editor {
let Some(visible_rows) = self.visible_line_count().map(|count| count as u32) else {
return;
};
- let new_screen_top = self.selections.newest_display(cx).head().row().0;
+ let new_screen_top = self
+ .selections
+ .newest_display(&self.display_snapshot(cx))
+ .head()
+ .row()
+ .0;
let new_screen_top =
new_screen_top.saturating_sub(visible_rows.saturating_sub(scroll_margin_rows));
self.set_scroll_top_row(DisplayRow(new_screen_top), window, cx);
@@ -148,7 +148,7 @@ impl Editor {
target_top = first_highlighted_row.as_f64();
target_bottom = target_top + 1.;
} else {
- let selections = self.selections.all::<Point>(cx);
+ let selections = self.selections.all::<Point>(&display_map);
target_top = selections
.first()
@@ -293,7 +293,7 @@ impl Editor {
let scroll_width = ScrollOffset::from(scroll_width);
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
- let selections = self.selections.all::<Point>(cx);
+ let selections = self.selections.all::<Point>(&display_map);
let mut scroll_position = self.scroll_manager.scroll_position(&display_map);
let mut target_left;
@@ -110,7 +110,7 @@ impl SelectionsCollection {
if self.pending.is_none() {
self.disjoint_anchors_arc()
} else {
- let all_offset_selections = self.all::<usize>(cx);
+ let all_offset_selections = self.all::<usize>(&self.display_map(cx));
let buffer = self.buffer(cx);
all_offset_selections
.into_iter()
@@ -129,25 +129,23 @@ impl SelectionsCollection {
pub fn pending<D: TextDimension + Ord + Sub<D, Output = D>>(
&self,
- cx: &mut App,
+ snapshot: &DisplaySnapshot,
) -> Option<Selection<D>> {
- let map = self.display_map(cx);
-
- resolve_selections(self.pending_anchor(), &map).next()
+ resolve_selections(self.pending_anchor(), &snapshot).next()
}
pub(crate) fn pending_mode(&self) -> Option<SelectMode> {
self.pending.as_ref().map(|pending| pending.mode.clone())
}
- pub fn all<'a, D>(&self, cx: &mut App) -> Vec<Selection<D>>
+ pub fn all<'a, D>(&self, snapshot: &DisplaySnapshot) -> Vec<Selection<D>>
where
D: 'a + TextDimension + Ord + Sub<D, Output = D>,
{
- let map = self.display_map(cx);
let disjoint_anchors = &self.disjoint;
- let mut disjoint = resolve_selections::<D, _>(disjoint_anchors.iter(), &map).peekable();
- let mut pending_opt = self.pending::<D>(cx);
+ let mut disjoint =
+ resolve_selections::<D, _>(disjoint_anchors.iter(), &snapshot).peekable();
+ let mut pending_opt = self.pending::<D>(&snapshot);
iter::from_fn(move || {
if let Some(pending) = pending_opt.as_mut() {
while let Some(next_selection) = disjoint.peek() {
@@ -175,12 +173,11 @@ impl SelectionsCollection {
}
/// Returns all of the selections, adjusted to take into account the selection line_mode
- pub fn all_adjusted(&self, cx: &mut App) -> Vec<Selection<Point>> {
- let mut selections = self.all::<Point>(cx);
+ pub fn all_adjusted(&self, snapshot: &DisplaySnapshot) -> Vec<Selection<Point>> {
+ let mut selections = self.all::<Point>(&snapshot);
if self.line_mode {
- let map = self.display_map(cx);
for selection in &mut selections {
- let new_range = map.expand_to_line(selection.range());
+ let new_range = snapshot.expand_to_line(selection.range());
selection.start = new_range.start;
selection.end = new_range.end;
}
@@ -210,11 +207,10 @@ impl SelectionsCollection {
}
/// Returns the newest selection, adjusted to take into account the selection line_mode
- pub fn newest_adjusted(&self, cx: &mut App) -> Selection<Point> {
- let mut selection = self.newest::<Point>(cx);
+ pub fn newest_adjusted(&self, snapshot: &DisplaySnapshot) -> Selection<Point> {
+ let mut selection = self.newest::<Point>(&snapshot);
if self.line_mode {
- let map = self.display_map(cx);
- let new_range = map.expand_to_line(selection.range());
+ let new_range = snapshot.expand_to_line(selection.range());
selection.start = new_range.start;
selection.end = new_range.end;
}
@@ -223,53 +219,55 @@ impl SelectionsCollection {
pub fn all_adjusted_display(
&self,
- cx: &mut App,
- ) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) {
+ display_map: &DisplaySnapshot,
+ ) -> Vec<Selection<DisplayPoint>> {
if self.line_mode {
- let selections = self.all::<Point>(cx);
- let map = self.display_map(cx);
+ let selections = self.all::<Point>(&display_map);
let result = selections
.into_iter()
.map(|mut selection| {
- let new_range = map.expand_to_line(selection.range());
+ let new_range = display_map.expand_to_line(selection.range());
selection.start = new_range.start;
selection.end = new_range.end;
- selection.map(|point| point.to_display_point(&map))
+ selection.map(|point| point.to_display_point(&display_map))
})
.collect();
- (map, result)
+ result
} else {
- self.all_display(cx)
+ self.all_display(display_map)
}
}
- pub fn disjoint_in_range<'a, D>(&self, range: Range<Anchor>, cx: &mut App) -> Vec<Selection<D>>
+ pub fn disjoint_in_range<'a, D>(
+ &self,
+ range: Range<Anchor>,
+ snapshot: &DisplaySnapshot,
+ ) -> Vec<Selection<D>>
where
D: 'a + TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug,
{
- let map = self.display_map(cx);
let start_ix = match self
.disjoint
- .binary_search_by(|probe| probe.end.cmp(&range.start, map.buffer_snapshot()))
+ .binary_search_by(|probe| probe.end.cmp(&range.start, snapshot.buffer_snapshot()))
{
Ok(ix) | Err(ix) => ix,
};
let end_ix = match self
.disjoint
- .binary_search_by(|probe| probe.start.cmp(&range.end, map.buffer_snapshot()))
+ .binary_search_by(|probe| probe.start.cmp(&range.end, snapshot.buffer_snapshot()))
{
Ok(ix) => ix + 1,
Err(ix) => ix,
};
- resolve_selections(&self.disjoint[start_ix..end_ix], &map).collect()
+ resolve_selections(&self.disjoint[start_ix..end_ix], snapshot).collect()
}
- pub fn all_display(&self, cx: &mut App) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) {
- let map = self.display_map(cx);
+ pub fn all_display(&self, snapshot: &DisplaySnapshot) -> Vec<Selection<DisplayPoint>> {
let disjoint_anchors = &self.disjoint;
- let mut disjoint = resolve_selections_display(disjoint_anchors.iter(), &map).peekable();
- let mut pending_opt = resolve_selections_display(self.pending_anchor(), &map).next();
- let selections = iter::from_fn(move || {
+ let mut disjoint =
+ resolve_selections_display(disjoint_anchors.iter(), &snapshot).peekable();
+ let mut pending_opt = resolve_selections_display(self.pending_anchor(), &snapshot).next();
+ iter::from_fn(move || {
if let Some(pending) = pending_opt.as_mut() {
while let Some(next_selection) = disjoint.peek() {
if pending.start <= next_selection.end && pending.end >= next_selection.start {
@@ -292,8 +290,7 @@ impl SelectionsCollection {
disjoint.next()
}
})
- .collect();
- (map, selections)
+ .collect()
}
pub fn newest_anchor(&self) -> &Selection<Anchor> {
@@ -306,19 +303,15 @@ impl SelectionsCollection {
pub fn newest<D: TextDimension + Ord + Sub<D, Output = D>>(
&self,
- cx: &mut App,
+ snapshot: &DisplaySnapshot,
) -> Selection<D> {
- let map = self.display_map(cx);
-
- resolve_selections([self.newest_anchor()], &map)
+ resolve_selections([self.newest_anchor()], &snapshot)
.next()
.unwrap()
}
- pub fn newest_display(&self, cx: &mut App) -> Selection<DisplayPoint> {
- let map = self.display_map(cx);
-
- resolve_selections_display([self.newest_anchor()], &map)
+ pub fn newest_display(&self, snapshot: &DisplaySnapshot) -> Selection<DisplayPoint> {
+ resolve_selections_display([self.newest_anchor()], &snapshot)
.next()
.unwrap()
}
@@ -333,11 +326,9 @@ impl SelectionsCollection {
pub fn oldest<D: TextDimension + Ord + Sub<D, Output = D>>(
&self,
- cx: &mut App,
+ snapshot: &DisplaySnapshot,
) -> Selection<D> {
- let map = self.display_map(cx);
-
- resolve_selections([self.oldest_anchor()], &map)
+ resolve_selections([self.oldest_anchor()], &snapshot)
.next()
.unwrap()
}
@@ -349,12 +340,18 @@ impl SelectionsCollection {
.unwrap_or_else(|| self.disjoint.first().cloned().unwrap())
}
- pub fn first<D: TextDimension + Ord + Sub<D, Output = D>>(&self, cx: &mut App) -> Selection<D> {
- self.all(cx).first().unwrap().clone()
+ pub fn first<D: TextDimension + Ord + Sub<D, Output = D>>(
+ &self,
+ snapshot: &DisplaySnapshot,
+ ) -> Selection<D> {
+ self.all(snapshot).first().unwrap().clone()
}
- pub fn last<D: TextDimension + Ord + Sub<D, Output = D>>(&self, cx: &mut App) -> Selection<D> {
- self.all(cx).last().unwrap().clone()
+ pub fn last<D: TextDimension + Ord + Sub<D, Output = D>>(
+ &self,
+ snapshot: &DisplaySnapshot,
+ ) -> Selection<D> {
+ self.all(snapshot).last().unwrap().clone()
}
/// Returns a list of (potentially backwards!) ranges representing the selections.
@@ -362,9 +359,9 @@ impl SelectionsCollection {
#[cfg(any(test, feature = "test-support"))]
pub fn ranges<D: TextDimension + Ord + Sub<D, Output = D>>(
&self,
- cx: &mut App,
+ snapshot: &DisplaySnapshot,
) -> Vec<Range<D>> {
- self.all::<D>(cx)
+ self.all::<D>(snapshot)
.iter()
.map(|s| {
if s.reversed {
@@ -596,7 +593,8 @@ impl<'a> MutableSelectionsCollection<'a> {
where
T: 'a + ToOffset + ToPoint + TextDimension + Ord + Sub<T, Output = T> + std::marker::Copy,
{
- let mut selections = self.collection.all(self.cx);
+ let display_map = self.display_map();
+ 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 reversed = if start > end {
@@ -790,7 +788,7 @@ impl<'a> MutableSelectionsCollection<'a> {
) {
let mut changed = false;
let display_map = self.display_map();
- let (_, selections) = self.collection.all_display(self.cx);
+ let selections = self.collection.all_display(&display_map);
let selections = selections
.into_iter()
.map(|selection| {
@@ -814,9 +812,10 @@ impl<'a> MutableSelectionsCollection<'a> {
) {
let mut changed = false;
let snapshot = self.buffer().clone();
+ let display_map = self.display_map();
let selections = self
.collection
- .all::<usize>(self.cx)
+ .all::<usize>(&display_map)
.into_iter()
.map(|selection| {
let mut moved_selection = selection.clone();
@@ -82,7 +82,7 @@ impl Editor {
if !(self.signature_help_state.is_shown() || self.auto_signature_help_enabled(cx)) {
return false;
}
- let newest_selection = self.selections.newest::<usize>(cx);
+ let newest_selection = self.selections.newest::<usize>(&self.display_snapshot(cx));
let head = newest_selection.head();
if !newest_selection.is_empty() && head != newest_selection.tail() {
@@ -14,7 +14,7 @@ impl Editor {
return Task::ready(None);
};
let (selection, buffer, editor_snapshot) = {
- let selection = self.selections.newest_adjusted(cx);
+ let selection = self.selections.newest_adjusted(&self.display_snapshot(cx));
let Some((buffer, _)) = self
.buffer()
.read(cx)
@@ -108,7 +108,7 @@ pub fn assert_text_with_selections(
assert_eq!(editor.text(cx), unmarked_text, "text doesn't match");
let actual = generate_marked_text(
&editor.text(cx),
- &editor.selections.ranges(cx),
+ &editor.selections.ranges(&editor.display_snapshot(cx)),
marked_text.contains("«"),
);
assert_eq!(actual, marked_text, "Selections don't match");
@@ -265,7 +265,10 @@ impl EditorTestContext {
pub fn pixel_position_for(&mut self, display_point: DisplayPoint) -> Point<Pixels> {
self.update_editor(|editor, window, cx| {
- let newest_point = editor.selections.newest_display(cx).head();
+ let newest_point = editor
+ .selections
+ .newest_display(&editor.display_snapshot(cx))
+ .head();
let pixel_position = editor.pixel_position_of_newest_cursor.unwrap();
let line_height = editor
.style()
@@ -590,7 +593,7 @@ impl EditorTestContext {
fn editor_selections(&mut self) -> Vec<Range<usize>> {
self.editor
.update(&mut self.cx, |editor, cx| {
- editor.selections.all::<usize>(cx)
+ editor.selections.all::<usize>(&editor.display_snapshot(cx))
})
.into_iter()
.map(|s| {
@@ -688,9 +691,12 @@ pub fn assert_state_with_diff(
expected_diff_text: &str,
) {
let (snapshot, selections) = editor.update_in(cx, |editor, window, cx| {
+ let snapshot = editor.snapshot(window, cx);
(
- editor.snapshot(window, cx).buffer_snapshot().clone(),
- editor.selections.ranges::<usize>(cx),
+ snapshot.buffer_snapshot().clone(),
+ editor
+ .selections
+ .ranges::<usize>(&snapshot.display_snapshot),
)
});
@@ -490,7 +490,7 @@ async fn test_row_column_numbers_query_inside_file(cx: &mut TestAppContext) {
cx.executor().advance_clock(Duration::from_secs(2));
editor.update(cx, |editor, cx| {
- let all_selections = editor.selections.all_adjusted(cx);
+ let all_selections = editor.selections.all_adjusted(&editor.display_snapshot(cx));
assert_eq!(
all_selections.len(),
1,
@@ -565,7 +565,7 @@ async fn test_row_column_numbers_query_outside_file(cx: &mut TestAppContext) {
cx.executor().advance_clock(Duration::from_secs(2));
editor.update(cx, |editor, cx| {
- let all_selections = editor.selections.all_adjusted(cx);
+ let all_selections = editor.selections.all_adjusted(&editor.display_snapshot(cx));
assert_eq!(
all_selections.len(),
1,
@@ -49,7 +49,7 @@ impl TextDiffView {
let selection_data = source_editor.update(cx, |editor, cx| {
let multibuffer = editor.buffer().read(cx);
let source_buffer = multibuffer.as_singleton()?;
- let selections = editor.selections.all::<Point>(cx);
+ let selections = editor.selections.all::<Point>(&editor.display_snapshot(cx));
let buffer_snapshot = source_buffer.read(cx);
let first_selection = selections.first()?;
let max_point = buffer_snapshot.max_point();
@@ -74,7 +74,9 @@ impl GoToLine {
) -> Self {
let (user_caret, last_line, scroll_position) = active_editor.update(cx, |editor, cx| {
let user_caret = UserCaretPosition::at_selection_end(
- &editor.selections.last::<Point>(cx),
+ &editor
+ .selections
+ .last::<Point>(&editor.display_snapshot(cx)),
&editor.buffer().read(cx).snapshot(cx),
);
@@ -739,7 +741,7 @@ mod tests {
let selections = editor.update(cx, |editor, cx| {
editor
.selections
- .all::<rope::Point>(cx)
+ .all::<rope::Point>(&editor.display_snapshot(cx))
.into_iter()
.map(|s| s.start..s.end)
.collect::<Vec<_>>()
@@ -229,8 +229,11 @@ impl LspLogView {
log_view.editor.update(cx, |editor, cx| {
editor.set_read_only(false);
let last_offset = editor.buffer().read(cx).len(cx);
- let newest_cursor_is_at_end =
- editor.selections.newest::<usize>(cx).start >= last_offset;
+ let newest_cursor_is_at_end = editor
+ .selections
+ .newest::<usize>(&editor.display_snapshot(cx))
+ .start
+ >= last_offset;
editor.edit(
vec![
(last_offset..last_offset, text.as_str()),
@@ -252,7 +252,10 @@ impl SyntaxTreeView {
.editor
.update(cx, |editor, cx| editor.snapshot(window, cx));
let (buffer, range, excerpt_id) = editor_state.editor.update(cx, |editor, cx| {
- let selection_range = editor.selections.last::<usize>(cx).range();
+ let selection_range = editor
+ .selections
+ .last::<usize>(&editor.display_snapshot(cx))
+ .range();
let multi_buffer = editor.buffer().read(cx);
let (buffer, range, excerpt_id) = snapshot
.buffer_snapshot()
@@ -278,8 +278,12 @@ impl MarkdownPreviewView {
this.parse_markdown_from_active_editor(true, window, cx);
}
EditorEvent::SelectionsChanged { .. } => {
- let selection_range = editor
- .update(cx, |editor, cx| editor.selections.last::<usize>(cx).range());
+ let selection_range = editor.update(cx, |editor, cx| {
+ editor
+ .selections
+ .last::<usize>(&editor.display_snapshot(cx))
+ .range()
+ });
this.selected_block = this.get_block_index_under_cursor(selection_range);
this.list_state.scroll_to_reveal_item(this.selected_block);
cx.notify();
@@ -245,7 +245,10 @@ impl PickerDelegate for OutlineViewDelegate {
let (buffer, cursor_offset) = self.active_editor.update(cx, |editor, cx| {
let buffer = editor.buffer().read(cx).snapshot(cx);
- let cursor_offset = editor.selections.newest::<usize>(cx).head();
+ let cursor_offset = editor
+ .selections
+ .newest::<usize>(&editor.display_snapshot(cx))
+ .head();
(buffer, cursor_offset)
});
selected_index = self
@@ -673,7 +676,7 @@ mod tests {
let selections = editor.update(cx, |editor, cx| {
editor
.selections
- .all::<rope::Point>(cx)
+ .all::<rope::Point>(&editor.display_snapshot(cx))
.into_iter()
.map(|s| s.start..s.end)
.collect::<Vec<_>>()
@@ -3099,7 +3099,10 @@ impl OutlinePanel {
cx: &mut Context<Self>,
) -> Option<PanelEntry> {
let selection = editor.update(cx, |editor, cx| {
- editor.selections.newest::<language::Point>(cx).head()
+ editor
+ .selections
+ .newest::<language::Point>(&editor.display_snapshot(cx))
+ .head()
});
let editor_snapshot = editor.update(cx, |editor, cx| editor.snapshot(window, cx));
let multi_buffer = editor.read(cx).buffer();
@@ -6957,13 +6960,13 @@ outline: struct OutlineEntryExcerpt
fn selected_row_text(editor: &Entity<Editor>, cx: &mut App) -> String {
editor.update(cx, |editor, cx| {
- let selections = editor.selections.all::<language::Point>(cx);
- assert_eq!(selections.len(), 1, "Active editor should have exactly one selection after any outline panel interactions");
- let selection = selections.first().unwrap();
- let multi_buffer_snapshot = editor.buffer().read(cx).snapshot(cx);
- let line_start = language::Point::new(selection.start.row, 0);
- let line_end = multi_buffer_snapshot.clip_point(language::Point::new(selection.end.row, u32::MAX), language::Bias::Right);
- multi_buffer_snapshot.text_for_range(line_start..line_end).collect::<String>().trim().to_owned()
+ let selections = editor.selections.all::<language::Point>(&editor.display_snapshot(cx));
+ assert_eq!(selections.len(), 1, "Active editor should have exactly one selection after any outline panel interactions");
+ let selection = selections.first().unwrap();
+ let multi_buffer_snapshot = editor.buffer().read(cx).snapshot(cx);
+ let line_start = language::Point::new(selection.start.row, 0);
+ let line_end = multi_buffer_snapshot.clip_point(language::Point::new(selection.end.row, u32::MAX), language::Bias::Right);
+ multi_buffer_snapshot.text_for_range(line_start..line_end).collect::<String>().trim().to_owned()
})
}
@@ -657,7 +657,7 @@ async fn test_editing_files(cx: &mut gpui::TestAppContext) {
let confirm = panel.update_in(cx, |panel, window, cx| {
panel.filename_editor.update(cx, |editor, cx| {
- let file_name_selections = editor.selections.all::<usize>(cx);
+ let file_name_selections = editor.selections.all::<usize>(&editor.display_snapshot(cx));
assert_eq!(
file_name_selections.len(),
1,
@@ -731,7 +731,7 @@ async fn test_editing_files(cx: &mut gpui::TestAppContext) {
panel.update_in(cx, |panel, window, cx| {
panel.filename_editor.update(cx, |editor, cx| {
- let file_name_selections = editor.selections.all::<usize>(cx);
+ let file_name_selections = editor.selections.all::<usize>(&editor.display_snapshot(cx));
assert_eq!(file_name_selections.len(), 1, "File editing should have a single selection, but got: {file_name_selections:?}");
let file_name_selection = &file_name_selections[0];
assert_eq!(file_name_selection.start, 0, "Should select the file name from the start");
@@ -1214,7 +1214,7 @@ async fn test_copy_paste(cx: &mut gpui::TestAppContext) {
panel.update_in(cx, |panel, window, cx| {
panel.filename_editor.update(cx, |editor, cx| {
- let file_name_selections = editor.selections.all::<usize>(cx);
+ let file_name_selections = editor.selections.all::<usize>(&editor.display_snapshot(cx));
assert_eq!(
file_name_selections.len(),
1,
@@ -85,7 +85,11 @@ pub fn run(
let editor = editor.upgrade().context("editor was dropped")?;
let selected_range = editor
- .update(cx, |editor, cx| editor.selections.newest_adjusted(cx))
+ .update(cx, |editor, cx| {
+ editor
+ .selections
+ .newest_adjusted(&editor.display_snapshot(cx))
+ })
.range();
let multibuffer = editor.read(cx).buffer().clone();
let Some(buffer) = multibuffer.read(cx).as_singleton() else {
@@ -473,7 +477,9 @@ fn language_supported(language: &Arc<Language>, cx: &mut App) -> bool {
fn get_language(editor: WeakEntity<Editor>, cx: &mut App) -> Option<Arc<Language>> {
editor
.update(cx, |editor, cx| {
- let selection = editor.selections.newest::<usize>(cx);
+ let selection = editor
+ .selections
+ .newest::<usize>(&editor.display_snapshot(cx));
let buffer = editor.buffer().read(cx).snapshot(cx);
buffer.language_at(selection.head()).cloned()
})
@@ -50,7 +50,8 @@ impl Vim {
pub(crate) fn push_to_change_list(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let Some((new_positions, buffer)) = self.update_editor(cx, |vim, editor, cx| {
- let (map, selections) = editor.selections.all_adjusted_display(cx);
+ let display_map = editor.display_snapshot(cx);
+ let selections = editor.selections.all_adjusted_display(&display_map);
let buffer = editor.buffer().clone();
let pop_state = editor
@@ -59,7 +60,7 @@ impl Vim {
.map(|previous| {
previous.len() == selections.len()
&& previous.iter().enumerate().all(|(ix, p)| {
- p.to_display_point(&map).row() == selections[ix].head().row()
+ p.to_display_point(&display_map).row() == selections[ix].head().row()
})
})
.unwrap_or(false);
@@ -68,11 +69,11 @@ impl Vim {
.into_iter()
.map(|s| {
let point = if vim.mode == Mode::Insert {
- movement::saturating_left(&map, s.head())
+ movement::saturating_left(&display_map, s.head())
} else {
s.head()
};
- map.display_point_to_anchor(point, Bias::Left)
+ display_map.display_point_to_anchor(point, Bias::Left)
})
.collect::<Vec<_>>();
@@ -606,7 +606,9 @@ pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
let result = vim.update_editor(cx, |vim, editor, cx| {
let snapshot = editor.snapshot(window, cx);
let buffer_row = action.range.head().buffer_row(vim, editor, window, cx)?;
- let current = editor.selections.newest::<Point>(cx);
+ let current = editor
+ .selections
+ .newest::<Point>(&editor.display_snapshot(cx));
let target = snapshot
.buffer_snapshot()
.clip_point(Point::new(buffer_row.0, current.head().column), Bias::Left);
@@ -1903,7 +1905,9 @@ impl OnMatchingLines {
});
window.dispatch_action(action, cx);
cx.defer_in(window, move |editor, window, cx| {
- let newest = editor.selections.newest::<Point>(cx);
+ let newest = editor
+ .selections
+ .newest::<Point>(&editor.display_snapshot(cx));
editor.change_selections(
SelectionEffects::no_scroll(),
window,
@@ -2000,7 +2004,9 @@ impl Vim {
};
let command = self.update_editor(cx, |_, editor, cx| {
let snapshot = editor.snapshot(window, cx);
- let start = editor.selections.newest_display(cx);
+ let start = editor
+ .selections
+ .newest_display(&editor.display_snapshot(cx));
let text_layout_details = editor.text_layout_details(window);
let (mut range, _) = motion
.range(
@@ -2047,7 +2053,9 @@ impl Vim {
};
let command = self.update_editor(cx, |_, editor, cx| {
let snapshot = editor.snapshot(window, cx);
- let start = editor.selections.newest_display(cx);
+ let start = editor
+ .selections
+ .newest_display(&editor.display_snapshot(cx));
let range = object
.range(&snapshot, start.clone(), around, None)
.unwrap_or(start.range());
@@ -2156,7 +2164,11 @@ impl ShellExec {
Point::new(range.start.0, 0)
..snapshot.clip_point(Point::new(range.end.0 + 1, 0), Bias::Right)
} else {
- let mut end = editor.selections.newest::<Point>(cx).range().end;
+ let mut end = editor
+ .selections
+ .newest::<Point>(&editor.display_snapshot(cx))
+ .range()
+ .end;
end = snapshot.clip_point(Point::new(end.row + 1, 0), Bias::Right);
needs_newline_prefix = end == snapshot.max_point();
end..end
@@ -345,7 +345,7 @@ impl Vim {
self.update_editor(cx, |vim, editor, cx| {
let has_selection = editor
.selections
- .all_adjusted(cx)
+ .all_adjusted(&editor.display_snapshot(cx))
.iter()
.any(|selection| !selection.is_empty());
@@ -478,19 +478,20 @@ impl Vim {
pub fn helix_replace(&mut self, text: &str, window: &mut Window, cx: &mut Context<Self>) {
self.update_editor(cx, |_, editor, cx| {
editor.transact(window, cx, |editor, window, cx| {
- let (map, selections) = editor.selections.all_display(cx);
+ let display_map = editor.display_snapshot(cx);
+ let selections = editor.selections.all_display(&display_map);
// Store selection info for positioning after edit
let selection_info: Vec<_> = selections
.iter()
.map(|selection| {
let range = selection.range();
- let start_offset = range.start.to_offset(&map, Bias::Left);
- let end_offset = range.end.to_offset(&map, Bias::Left);
+ let start_offset = range.start.to_offset(&display_map, Bias::Left);
+ let end_offset = range.end.to_offset(&display_map, Bias::Left);
let was_empty = range.is_empty();
let was_reversed = selection.reversed;
(
- map.buffer_snapshot().anchor_before(start_offset),
+ display_map.buffer_snapshot().anchor_before(start_offset),
end_offset - start_offset,
was_empty,
was_reversed,
@@ -504,11 +505,11 @@ impl Vim {
// For empty selections, extend to replace one character
if range.is_empty() {
- range.end = movement::saturating_right(&map, range.start);
+ range.end = movement::saturating_right(&display_map, range.start);
}
- let byte_range = range.start.to_offset(&map, Bias::Left)
- ..range.end.to_offset(&map, Bias::Left);
+ let byte_range = range.start.to_offset(&display_map, Bias::Left)
+ ..range.end.to_offset(&display_map, Bias::Left);
if !byte_range.is_empty() {
let replacement_text = text.repeat(byte_range.len());
@@ -568,7 +569,7 @@ impl Vim {
self.update_editor(cx, |_, editor, cx| {
editor.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
let display_map = editor.display_map.update(cx, |map, cx| map.snapshot(cx));
- let mut selections = editor.selections.all::<Point>(cx);
+ let mut selections = editor.selections.all::<Point>(&display_map);
let max_point = display_map.buffer_snapshot().max_point();
let buffer_snapshot = &display_map.buffer_snapshot();
@@ -606,7 +607,9 @@ impl Vim {
cx: &mut Context<Self>,
) {
self.update_editor(cx, |_, editor, cx| {
- let newest = editor.selections.newest::<usize>(cx);
+ let newest = editor
+ .selections
+ .newest::<usize>(&editor.display_snapshot(cx));
editor.change_selections(Default::default(), window, cx, |s| s.select(vec![newest]));
});
}
@@ -633,7 +636,10 @@ impl Vim {
if yank {
vim.copy_selections_content(editor, MotionKind::Exclusive, window, cx);
}
- let selections = editor.selections.all::<Point>(cx).into_iter();
+ let selections = editor
+ .selections
+ .all::<Point>(&editor.display_snapshot(cx))
+ .into_iter();
let edits = selections.map(|selection| (selection.start..selection.end, ""));
editor.edit(edits, cx);
});
@@ -56,7 +56,8 @@ impl Vim {
let times = times.unwrap_or(1);
self.update_editor(cx, |_, editor, cx| {
let mut selections = Vec::new();
- let (map, mut original_selections) = editor.selections.all_display(cx);
+ let map = editor.display_snapshot(cx);
+ let mut original_selections = editor.selections.all_display(&map);
// The order matters, because it is recorded when the selections are added.
if above {
original_selections.reverse();
@@ -44,7 +44,8 @@ impl Vim {
return;
};
- let (display_map, current_selections) = editor.selections.all_adjusted_display(cx);
+ let display_map = editor.display_snapshot(cx);
+ let current_selections = editor.selections.all_adjusted_display(&display_map);
// The clipboard can have multiple selections, and there can
// be multiple selections. Helix zips them together, so the first
@@ -84,7 +84,7 @@ impl Vim {
self.update_editor(cx, |_, editor, cx| {
let snapshot = editor.buffer().read(cx).snapshot(cx);
let mut edits = Vec::new();
- for selection in editor.selections.all::<Point>(cx) {
+ for selection in editor.selections.all::<Point>(&editor.display_snapshot(cx)) {
let point = selection.head();
let new_row = match direction {
Direction::Next => point.row + 1,
@@ -657,7 +657,7 @@ impl Vim {
self.switch_mode(Mode::Insert, false, window, cx);
self.update_editor(cx, |_, editor, cx| {
editor.transact(window, cx, |editor, window, cx| {
- let selections = editor.selections.all::<Point>(cx);
+ let selections = editor.selections.all::<Point>(&editor.display_snapshot(cx));
let snapshot = editor.buffer().read(cx).snapshot(cx);
let selection_start_rows: BTreeSet<u32> = selections
@@ -699,7 +699,7 @@ impl Vim {
self.update_editor(cx, |_, editor, cx| {
let text_layout_details = editor.text_layout_details(window);
editor.transact(window, cx, |editor, window, cx| {
- let selections = editor.selections.all::<Point>(cx);
+ let selections = editor.selections.all::<Point>(&editor.display_snapshot(cx));
let snapshot = editor.buffer().read(cx).snapshot(cx);
let selection_end_rows: BTreeSet<u32> = selections
@@ -745,7 +745,7 @@ impl Vim {
Vim::take_forced_motion(cx);
self.update_editor(cx, |_, editor, cx| {
editor.transact(window, cx, |editor, _, cx| {
- let selections = editor.selections.all::<Point>(cx);
+ let selections = editor.selections.all::<Point>(&editor.display_snapshot(cx));
let selection_start_rows: BTreeSet<u32> = selections
.into_iter()
@@ -774,9 +774,10 @@ impl Vim {
Vim::take_forced_motion(cx);
self.update_editor(cx, |_, editor, cx| {
editor.transact(window, cx, |editor, window, cx| {
- let selections = editor.selections.all::<Point>(cx);
+ let display_map = editor.display_snapshot(cx);
+ let selections = editor.selections.all::<Point>(&display_map);
let snapshot = editor.buffer().read(cx).snapshot(cx);
- let (_map, display_selections) = editor.selections.all_display(cx);
+ let display_selections = editor.selections.all_display(&display_map);
let original_positions = display_selections
.iter()
.map(|s| (s.id, s.head()))
@@ -937,13 +938,14 @@ impl Vim {
self.update_editor(cx, |_, editor, cx| {
editor.transact(window, cx, |editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
- let (map, display_selections) = editor.selections.all_display(cx);
+ let display_map = editor.display_snapshot(cx);
+ let display_selections = editor.selections.all_display(&display_map);
- let mut edits = Vec::new();
+ let mut edits = Vec::with_capacity(display_selections.len());
for selection in &display_selections {
let mut range = selection.range();
for _ in 0..count {
- let new_point = movement::saturating_right(&map, range.end);
+ let new_point = movement::saturating_right(&display_map, range.end);
if range.end == new_point {
return;
}
@@ -951,8 +953,8 @@ impl Vim {
}
edits.push((
- range.start.to_offset(&map, Bias::Left)
- ..range.end.to_offset(&map, Bias::Left),
+ range.start.to_offset(&display_map, Bias::Left)
+ ..range.end.to_offset(&display_map, Bias::Left),
text.repeat(if is_return_char { 0 } else { count }),
));
}
@@ -976,16 +978,16 @@ impl Vim {
pub fn save_selection_starts(
&self,
editor: &Editor,
-
cx: &mut Context<Editor>,
) -> HashMap<usize, Anchor> {
- let (map, selections) = editor.selections.all_display(cx);
+ let display_map = editor.display_snapshot(cx);
+ let selections = editor.selections.all_display(&display_map);
selections
.iter()
.map(|selection| {
(
selection.id,
- map.display_point_to_anchor(selection.start, Bias::Right),
+ display_map.display_point_to_anchor(selection.start, Bias::Right),
)
})
.collect::<HashMap<_, _>>()
@@ -199,7 +199,7 @@ impl Vim {
let mut ranges = Vec::new();
let mut cursor_positions = Vec::new();
let snapshot = editor.buffer().read(cx).snapshot(cx);
- for selection in editor.selections.all_adjusted(cx) {
+ for selection in editor.selections.all_adjusted(&editor.display_snapshot(cx)) {
match vim.mode {
Mode::Visual | Mode::VisualLine => {
ranges.push(selection.start..selection.end);
@@ -58,7 +58,7 @@ impl Vim {
let mut new_anchors = Vec::new();
let snapshot = editor.buffer().read(cx).snapshot(cx);
- for selection in editor.selections.all_adjusted(cx) {
+ for selection in editor.selections.all_adjusted(&editor.display_snapshot(cx)) {
if !selection.is_empty()
&& (vim.mode != Mode::VisualBlock || new_anchors.is_empty())
{
@@ -50,16 +50,19 @@ impl Vim {
let mut reversed = vec![];
self.update_editor(cx, |vim, editor, cx| {
- let (map, selections) = editor.selections.all_display(cx);
+ let display_map = editor.display_snapshot(cx);
+ let selections = editor.selections.all_display(&display_map);
for selection in selections {
- let end = movement::saturating_left(&map, selection.end);
+ let end = movement::saturating_left(&display_map, selection.end);
ends.push(
- map.buffer_snapshot()
- .anchor_before(end.to_offset(&map, Bias::Left)),
+ display_map
+ .buffer_snapshot()
+ .anchor_before(end.to_offset(&display_map, Bias::Left)),
);
starts.push(
- map.buffer_snapshot()
- .anchor_before(selection.start.to_offset(&map, Bias::Left)),
+ display_map
+ .buffer_snapshot()
+ .anchor_before(selection.start.to_offset(&display_map, Bias::Left)),
);
reversed.push(selection.reversed)
}
@@ -301,19 +304,21 @@ impl Vim {
name = "'";
}
if matches!(name, "{" | "}" | "(" | ")") {
- let (map, selections) = editor.selections.all_display(cx);
+ let display_map = editor.display_snapshot(cx);
+ let selections = editor.selections.all_display(&display_map);
let anchors = selections
.into_iter()
.map(|selection| {
let point = match name {
- "{" => movement::start_of_paragraph(&map, selection.head(), 1),
- "}" => movement::end_of_paragraph(&map, selection.head(), 1),
- "(" => motion::sentence_backwards(&map, selection.head(), 1),
- ")" => motion::sentence_forwards(&map, selection.head(), 1),
+ "{" => movement::start_of_paragraph(&display_map, selection.head(), 1),
+ "}" => movement::end_of_paragraph(&display_map, selection.head(), 1),
+ "(" => motion::sentence_backwards(&display_map, selection.head(), 1),
+ ")" => motion::sentence_forwards(&display_map, selection.head(), 1),
_ => unreachable!(),
};
- map.buffer_snapshot()
- .anchor_before(point.to_offset(&map, Bias::Left))
+ display_map
+ .buffer_snapshot()
+ .anchor_before(point.to_offset(&display_map, Bias::Left))
})
.collect::<Vec<Anchor>>();
return Some(Mark::Local(anchors));
@@ -56,7 +56,8 @@ impl Vim {
vim.copy_selections_content(editor, MotionKind::for_mode(vim.mode), window, cx);
}
- let (display_map, current_selections) = editor.selections.all_adjusted_display(cx);
+ let display_map = editor.display_snapshot(cx);
+ let current_selections = editor.selections.all_adjusted_display(&display_map);
// unlike zed, if you have a multi-cursor selection from vim block mode,
// pasting it will paste it on subsequent lines, even if you don't yet
@@ -173,7 +174,7 @@ impl Vim {
original_indent_columns.push(original_indent_column);
}
- let cursor_offset = editor.selections.last::<usize>(cx).head();
+ let cursor_offset = editor.selections.last::<usize>(&display_map).head();
if editor
.buffer()
.read(cx)
@@ -363,7 +363,10 @@ mod test {
point(0., 3.0)
);
assert_eq!(
- editor.selections.newest(cx).range(),
+ editor
+ .selections
+ .newest(&editor.display_snapshot(cx))
+ .range(),
Point::new(6, 0)..Point::new(6, 0)
)
});
@@ -380,7 +383,10 @@ mod test {
point(0., 3.0)
);
assert_eq!(
- editor.selections.newest(cx).range(),
+ editor
+ .selections
+ .newest(&editor.display_snapshot(cx))
+ .range(),
Point::new(0, 0)..Point::new(6, 1)
)
});
@@ -94,7 +94,10 @@ impl Vim {
MotionKind::Exclusive
};
vim.copy_selections_content(editor, kind, window, cx);
- let selections = editor.selections.all::<Point>(cx).into_iter();
+ let selections = editor
+ .selections
+ .all::<Point>(&editor.display_snapshot(cx))
+ .into_iter();
let edits = selections.map(|selection| (selection.start..selection.end, ""));
editor.edit(edits, cx);
});
@@ -106,7 +106,7 @@ impl Vim {
true,
editor
.selections
- .all_adjusted(cx)
+ .all_adjusted(&editor.display_snapshot(cx))
.iter()
.map(|s| s.range())
.collect(),
@@ -128,7 +128,7 @@ impl Vim {
false,
editor
.selections
- .all_adjusted(cx)
+ .all_adjusted(&editor.display_snapshot(cx))
.iter()
.map(|s| s.range())
.collect(),
@@ -53,7 +53,7 @@ impl Vim {
editor.transact(window, cx, |editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
let map = editor.snapshot(window, cx);
- let display_selections = editor.selections.all::<Point>(cx);
+ let display_selections = editor.selections.all::<Point>(&map.display_snapshot);
// Handles all string that require manipulation, including inserts and replaces
let edits = display_selections
@@ -98,7 +98,7 @@ impl Vim {
editor.transact(window, cx, |editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
let map = editor.snapshot(window, cx);
- let selections = editor.selections.all::<Point>(cx);
+ let selections = editor.selections.all::<Point>(&map.display_snapshot);
let mut new_selections = vec![];
let edits: Vec<(Range<Point>, String)> = selections
.into_iter()
@@ -150,7 +150,9 @@ impl Vim {
self.stop_recording(cx);
self.update_editor(cx, |vim, editor, cx| {
editor.set_clip_at_line_ends(false, cx);
- let mut selection = editor.selections.newest_display(cx);
+ let mut selection = editor
+ .selections
+ .newest_display(&editor.display_snapshot(cx));
let snapshot = editor.snapshot(window, cx);
object.expand_selection(&snapshot, &mut selection, around, None);
let start = snapshot
@@ -196,7 +198,9 @@ impl Vim {
self.update_editor(cx, |vim, editor, cx| {
editor.set_clip_at_line_ends(false, cx);
let text_layout_details = editor.text_layout_details(window);
- let mut selection = editor.selections.newest_display(cx);
+ let mut selection = editor
+ .selections
+ .newest_display(&editor.display_snapshot(cx));
let snapshot = editor.snapshot(window, cx);
motion.expand_selection(
&snapshot,
@@ -863,7 +863,9 @@ impl VimGlobals {
}
}
'%' => editor.and_then(|editor| {
- let selection = editor.selections.newest::<Point>(cx);
+ let selection = editor
+ .selections
+ .newest::<Point>(&editor.display_snapshot(cx));
if let Some((_, buffer, _)) = editor
.buffer()
.read(cx)
@@ -45,7 +45,8 @@ impl Vim {
},
};
let surround = pair.end != surround_alias((*text).as_ref());
- let (display_map, display_selections) = editor.selections.all_adjusted_display(cx);
+ let display_map = editor.display_snapshot(cx);
+ let display_selections = editor.selections.all_adjusted_display(&display_map);
let mut edits = Vec::new();
let mut anchors = Vec::new();
@@ -144,7 +145,8 @@ impl Vim {
editor.transact(window, cx, |editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
- let (display_map, display_selections) = editor.selections.all_display(cx);
+ let display_map = editor.display_snapshot(cx);
+ let display_selections = editor.selections.all_display(&display_map);
let mut edits = Vec::new();
let mut anchors = Vec::new();
@@ -256,7 +258,8 @@ impl Vim {
let preserve_space =
will_replace_pair.start == will_replace_pair.end || !opening;
- let (display_map, selections) = editor.selections.all_adjusted_display(cx);
+ let display_map = editor.display_snapshot(cx);
+ let selections = editor.selections.all_adjusted_display(&display_map);
let mut edits = Vec::new();
let mut anchors = Vec::new();
@@ -382,7 +385,8 @@ impl Vim {
self.update_editor(cx, |_, editor, cx| {
editor.transact(window, cx, |editor, window, cx| {
editor.set_clip_at_line_ends(false, cx);
- let (display_map, selections) = editor.selections.all_adjusted_display(cx);
+ let display_map = editor.display_snapshot(cx);
+ let selections = editor.selections.all_adjusted_display(&display_map);
let mut anchors = Vec::new();
for selection in &selections {
@@ -500,7 +504,8 @@ impl Vim {
let mut min_range_size = usize::MAX;
let _ = self.editor.update(cx, |editor, cx| {
- let (display_map, selections) = editor.selections.all_adjusted_display(cx);
+ let display_map = editor.display_snapshot(cx);
+ let selections = editor.selections.all_adjusted_display(&display_map);
// Even if there's multiple cursors, we'll simply rely on
// the first one to understand what bracket pair to map to.
// I believe we could, if worth it, go one step above and
@@ -2295,7 +2295,10 @@ async fn test_clipping_on_mode_change(cx: &mut gpui::TestAppContext) {
let mut pixel_position = cx.update_editor(|editor, window, cx| {
let snapshot = editor.snapshot(window, cx);
- let current_head = editor.selections.newest_display(cx).end;
+ let current_head = editor
+ .selections
+ .newest_display(&snapshot.display_snapshot)
+ .end;
editor.last_bounds().unwrap().origin
+ editor
.display_to_pixel_point(current_head, &snapshot, window)
@@ -1359,7 +1359,10 @@ impl Vim {
return;
};
let newest_selection_empty = editor.update(cx, |editor, cx| {
- editor.selections.newest::<usize>(cx).is_empty()
+ editor
+ .selections
+ .newest::<usize>(&editor.display_snapshot(cx))
+ .is_empty()
});
let editor = editor.read(cx);
let editor_mode = editor.mode();
@@ -1455,9 +1458,11 @@ impl Vim {
cx: &mut Context<Self>,
) -> Option<String> {
self.update_editor(cx, |_, editor, cx| {
- let selection = editor.selections.newest::<usize>(cx);
+ let snapshot = &editor.snapshot(window, cx);
+ let selection = editor
+ .selections
+ .newest::<usize>(&snapshot.display_snapshot);
- let snapshot = editor.snapshot(window, cx);
let snapshot = snapshot.buffer_snapshot();
let (range, kind) =
snapshot.surrounding_word(selection.start, Some(CharScopeContext::Completion));
@@ -1484,9 +1489,11 @@ impl Vim {
let selections = self.editor().map(|editor| {
editor.update(cx, |editor, cx| {
+ let snapshot = editor.display_snapshot(cx);
+
(
- editor.selections.oldest::<Point>(cx),
- editor.selections.newest::<Point>(cx),
+ editor.selections.oldest::<Point>(&snapshot),
+ editor.selections.newest::<Point>(&snapshot),
)
})
});
@@ -747,7 +747,8 @@ impl Vim {
self.stop_recording(cx);
self.update_editor(cx, |_, editor, cx| {
editor.transact(window, cx, |editor, window, cx| {
- let (display_map, selections) = editor.selections.all_adjusted_display(cx);
+ let display_map = editor.display_snapshot(cx);
+ let selections = editor.selections.all_adjusted_display(&display_map);
// Selections are biased right at the start. So we need to store
// anchors that are biased left so that we can restore the selections
@@ -858,7 +859,9 @@ impl Vim {
});
}
self.update_editor(cx, |_, editor, cx| {
- let latest = editor.selections.newest::<usize>(cx);
+ let latest = editor
+ .selections
+ .newest::<usize>(&editor.display_snapshot(cx));
start_selection = latest.start;
end_selection = latest.end;
});
@@ -879,7 +882,9 @@ impl Vim {
return;
}
self.update_editor(cx, |_, editor, cx| {
- let latest = editor.selections.newest::<usize>(cx);
+ let latest = editor
+ .selections
+ .newest::<usize>(&editor.display_snapshot(cx));
if vim_is_normal {
start_selection = latest.start;
end_selection = latest.end;
@@ -54,7 +54,8 @@ impl QuickActionBar {
.count()
.ne(&0)
.then(|| {
- let latest = this.selections.newest_display(cx);
+ let snapshot = this.display_snapshot(cx);
+ let latest = this.selections.newest_display(&snapshot);
!latest.is_empty()
})
.unwrap_or_default()