editor: Fix unwrap_syntax_node panicking by not setting selections (#38329)

Fixes ZED-11T

Release Notes:

- N/A *or* Added/Fixed/Improved ...
This commit is contained in:
Lukas Wirth
2025-09-17 15:10:05 +00:00
committed by GitHub
parent 0f6dd84c98
commit f3b8c619e3
16 changed files with 112 additions and 85 deletions
+2 -2
View File
@@ -477,7 +477,7 @@ impl TextThreadEditor {
return;
}
let selections = self.editor.read(cx).selections.disjoint_anchors();
let selections = self.editor.read(cx).selections.disjoint_anchors_arc();
let mut commands_by_range = HashMap::default();
let workspace = self.workspace.clone();
self.context.update(cx, |context, cx| {
@@ -1823,7 +1823,7 @@ impl TextThreadEditor {
fn split(&mut self, _: &Split, _window: &mut Window, cx: &mut Context<Self>) {
self.context.update(cx, |context, cx| {
let selections = self.editor.read(cx).selections.disjoint_anchors();
let selections = self.editor.read(cx).selections.disjoint_anchors_arc();
for selection in selections.as_ref() {
let buffer = self.editor.read(cx).buffer().read(cx).snapshot(cx);
let range = selection
+52 -38
View File
@@ -2414,14 +2414,10 @@ impl Editor {
pub fn is_range_selected(&mut self, range: &Range<Anchor>, cx: &mut Context<Self>) -> bool {
if self
.selections
.pending
.as_ref()
.pending_anchor()
.is_some_and(|pending_selection| {
let snapshot = self.buffer().read(cx).snapshot(cx);
pending_selection
.selection
.range()
.includes(range, &snapshot)
pending_selection.range().includes(range, &snapshot)
})
{
return true;
@@ -3054,7 +3050,7 @@ impl Editor {
}
}
let selection_anchors = self.selections.disjoint_anchors();
let selection_anchors = self.selections.disjoint_anchors_arc();
if self.focus_handle.is_focused(window) && self.leader_id.is_none() {
self.buffer.update(cx, |buffer, cx| {
@@ -3170,7 +3166,7 @@ impl Editor {
self.blink_manager.update(cx, BlinkManager::pause_blinking);
cx.emit(EditorEvent::SelectionsChanged { local });
let selections = &self.selections.disjoint;
let selections = &self.selections.disjoint_anchors_arc();
if selections.len() == 1 {
cx.emit(SearchEvent::ActiveMatchChanged)
}
@@ -3282,14 +3278,14 @@ impl Editor {
other: Entity<Editor>,
cx: &mut Context<Self>,
) -> gpui::Subscription {
let other_selections = other.read(cx).selections.disjoint.to_vec();
let other_selections = other.read(cx).selections.disjoint_anchors().to_vec();
self.selections.change_with(cx, |selections| {
selections.select_anchors(other_selections);
});
let other_subscription = cx.subscribe(&other, |this, other, other_evt, cx| {
if let EditorEvent::SelectionsChanged { local: true } = other_evt {
let other_selections = other.read(cx).selections.disjoint.to_vec();
let other_selections = other.read(cx).selections.disjoint_anchors().to_vec();
if other_selections.is_empty() {
return;
}
@@ -3301,7 +3297,7 @@ impl Editor {
let this_subscription = cx.subscribe_self::<EditorEvent>(move |this, this_evt, cx| {
if let EditorEvent::SelectionsChanged { local: true } = this_evt {
let these_selections = this.selections.disjoint.to_vec();
let these_selections = this.selections.disjoint_anchors().to_vec();
if these_selections.is_empty() {
return;
}
@@ -3339,7 +3335,7 @@ impl Editor {
effects,
old_cursor_position: self.selections.newest_anchor().head(),
history_entry: SelectionHistoryEntry {
selections: self.selections.disjoint_anchors(),
selections: self.selections.disjoint_anchors_arc(),
select_next_state: self.select_next_state.clone(),
select_prev_state: self.select_prev_state.clone(),
add_selections_state: self.add_selections_state.clone(),
@@ -3499,6 +3495,7 @@ impl Editor {
let mut pending_selection = self
.selections
.pending_anchor()
.cloned()
.expect("extend_selection not called with pending selection");
if position >= tail {
pending_selection.start = tail_anchor;
@@ -3520,7 +3517,7 @@ impl Editor {
};
self.change_selections(effects, window, cx, |s| {
s.set_pending(pending_selection, pending_mode)
s.set_pending(pending_selection.clone(), pending_mode)
});
}
@@ -3595,7 +3592,7 @@ impl Editor {
Some(selected_points[0].id)
} else {
let clicked_point_already_selected =
self.selections.disjoint.iter().find(|selection| {
self.selections.disjoint_anchors().iter().find(|selection| {
selection.start.to_point(buffer) == start.to_point(buffer)
|| selection.end.to_point(buffer) == end.to_point(buffer)
});
@@ -3700,7 +3697,7 @@ impl Editor {
if self.columnar_selection_state.is_some() {
self.select_columns(position, goal_column, &display_map, window, cx);
} else if let Some(mut pending) = self.selections.pending_anchor() {
} else if let Some(mut pending) = self.selections.pending_anchor().cloned() {
let buffer = &display_map.buffer_snapshot;
let head;
let tail;
@@ -3776,7 +3773,7 @@ impl Editor {
}
self.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
s.set_pending(pending, mode);
s.set_pending(pending.clone(), mode);
});
} else {
log::error!("update_selection dispatched with no pending selection");
@@ -3885,7 +3882,8 @@ impl Editor {
};
pending_nonempty_selection
|| (self.columnar_selection_state.is_some() && self.selections.disjoint.len() > 1)
|| (self.columnar_selection_state.is_some()
&& self.selections.disjoint_anchors().len() > 1)
}
pub fn has_pending_selection(&self) -> bool {
@@ -6065,7 +6063,7 @@ impl Editor {
editor.refresh_edit_prediction(true, false, window, cx);
});
self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), &snapshot);
self.invalidate_autoclose_regions(&self.selections.disjoint_anchors_arc(), &snapshot);
let show_new_completions_on_confirm = completion
.confirm
@@ -7472,7 +7470,7 @@ impl Editor {
s.select_anchor_ranges([last_edit_end..last_edit_end]);
});
let selections = self.selections.disjoint_anchors();
let selections = self.selections.disjoint_anchors_arc();
if let Some(transaction_id_now) = self.buffer.read(cx).last_transaction_id(cx) {
let has_new_transaction = transaction_id_prev != Some(transaction_id_now);
if has_new_transaction {
@@ -7717,7 +7715,7 @@ impl Editor {
let Some(mode) = Self::columnar_selection_mode(modifiers, cx) else {
return;
};
if self.selections.pending.is_none() {
if self.selections.pending_anchor().is_none() {
return;
}
@@ -10517,7 +10515,7 @@ impl Editor {
fn enable_wrap_selections_in_tag(&self, cx: &App) -> bool {
let snapshot = self.buffer.read(cx).snapshot(cx);
for selection in self.selections.disjoint_anchors().iter() {
for selection in self.selections.disjoint_anchors_arc().iter() {
if snapshot
.language_at(selection.start)
.and_then(|lang| lang.config().wrap_characters.as_ref())
@@ -10851,7 +10849,7 @@ impl Editor {
let snapshot = self.snapshot(window, cx);
let cursors = self
.selections
.disjoint_anchors()
.disjoint_anchors_arc()
.iter()
.map(|selection| {
let cursor_position: Point = selection.head().to_point(&snapshot.buffer_snapshot);
@@ -14542,7 +14540,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) -> Result<()> {
let selections = self.selections.disjoint_anchors();
let selections = self.selections.disjoint_anchors_arc();
match selections.first() {
Some(first) if selections.len() >= 2 => {
self.change_selections(Default::default(), window, cx, |s| {
@@ -14566,7 +14564,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) -> Result<()> {
let selections = self.selections.disjoint_anchors();
let selections = self.selections.disjoint_anchors_arc();
match selections.last() {
Some(last) if selections.len() >= 2 => {
self.change_selections(Default::default(), window, cx, |s| {
@@ -15123,11 +15121,9 @@ impl Editor {
let full_edits = selections
.into_iter()
.filter_map(|selection| {
// Only requires two branches once if-let-chains stabilize (#53667)
let child = if !selection.is_empty() {
selection.range()
} else if let Some((_, ancestor_range)) =
buffer.syntax_ancestor(selection.start..selection.end)
let child = if selection.is_empty()
&& let Some((_, ancestor_range)) =
buffer.syntax_ancestor(selection.start..selection.end)
{
match ancestor_range {
MultiOrSingleBufferOffsetRange::Single(range) => range,
@@ -15155,6 +15151,9 @@ impl Editor {
Some((selection.id, parent, text))
})
.collect::<Vec<_>>();
if full_edits.is_empty() {
return;
}
self.transact(window, cx, |this, window, cx| {
this.buffer.update(cx, |buffer, cx| {
@@ -15663,7 +15662,7 @@ impl Editor {
cx: &mut Context<Self>,
) {
let selections = self.selections.disjoint_anchors();
let selections = self.selections.disjoint_anchors_arc();
let lines = if lines == 0 {
EditorSettings::get_global(cx).expand_excerpt_lines
@@ -17122,7 +17121,7 @@ impl Editor {
.transaction(transaction_id_prev)
.map(|t| t.0.clone())
})
.unwrap_or_else(|| self.selections.disjoint_anchors());
.unwrap_or_else(|| self.selections.disjoint_anchors_arc());
let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse();
let format = project.update(cx, |project, cx| {
@@ -17662,7 +17661,7 @@ impl Editor {
.update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
{
self.selection_history
.insert_transaction(tx_id, self.selections.disjoint_anchors());
.insert_transaction(tx_id, self.selections.disjoint_anchors_arc());
cx.emit(EditorEvent::TransactionBegun {
transaction_id: tx_id,
});
@@ -17684,7 +17683,7 @@ impl Editor {
if let Some((_, end_selections)) =
self.selection_history.transaction_mut(transaction_id)
{
*end_selections = Some(self.selections.disjoint_anchors());
*end_selections = Some(self.selections.disjoint_anchors_arc());
} else {
log::error!("unexpectedly ended a transaction that wasn't started by this editor");
}
@@ -18354,7 +18353,12 @@ impl Editor {
_window: &mut Window,
cx: &mut Context<Self>,
) {
let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
let ranges: Vec<_> = self
.selections
.disjoint_anchors()
.iter()
.map(|s| s.range())
.collect();
self.toggle_diff_hunks_in_ranges(ranges, cx);
}
@@ -18392,7 +18396,12 @@ impl Editor {
cx: &mut Context<Self>,
) {
let snapshot = self.buffer.read(cx).snapshot(cx);
let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
let ranges: Vec<_> = self
.selections
.disjoint_anchors()
.iter()
.map(|s| s.range())
.collect();
let stage = self.has_stageable_diff_hunks_in_ranges(&ranges, &snapshot);
self.stage_or_unstage_diff_hunks(stage, ranges, cx);
}
@@ -18556,7 +18565,12 @@ impl Editor {
}
pub fn expand_selected_diff_hunks(&mut self, cx: &mut Context<Self>) {
let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
let ranges: Vec<_> = self
.selections
.disjoint_anchors()
.iter()
.map(|s| s.range())
.collect();
self.buffer
.update(cx, |buffer, cx| buffer.expand_diff_hunks(ranges, cx))
}
@@ -21276,7 +21290,7 @@ impl Editor {
buffer.finalize_last_transaction(cx);
if self.leader_id.is_none() {
buffer.set_active_selections(
&self.selections.disjoint_anchors(),
&self.selections.disjoint_anchors_arc(),
self.selections.line_mode,
self.cursor_shape,
cx,
@@ -23572,7 +23586,7 @@ impl EntityInputHandler for Editor {
let marked_ranges = {
let snapshot = this.buffer.read(cx).read(cx);
this.selections
.disjoint_anchors()
.disjoint_anchors_arc()
.iter()
.map(|selection| {
selection.start.bias_left(&snapshot)..selection.end.bias_right(&snapshot)
+8 -4
View File
@@ -1060,7 +1060,7 @@ impl EditorElement {
);
if mouse_down_time.elapsed() >= drag_and_drop_delay {
let drop_cursor = Selection {
id: post_inc(&mut editor.selections.next_selection_id),
id: post_inc(&mut editor.selections.next_selection_id()),
start: drop_anchor,
end: drop_anchor,
reversed: false,
@@ -1547,9 +1547,13 @@ impl EditorElement {
// Local cursors
if !skip_local {
let color = cx.theme().players().local().cursor;
editor.selections.disjoint.iter().for_each(|selection| {
add_cursor(selection.head(), color);
});
editor
.selections
.disjoint_anchors()
.iter()
.for_each(|selection| {
add_cursor(selection.head(), color);
});
if let Some(ref selection) = editor.selections.pending_anchor() {
add_cursor(selection.head(), color);
}
+4 -4
View File
@@ -187,7 +187,7 @@ impl FollowableItem for Editor {
} else if self.focus_handle.is_focused(window) {
self.buffer.update(cx, |buffer, cx| {
buffer.set_active_selections(
&self.selections.disjoint_anchors(),
&self.selections.disjoint_anchors_arc(),
self.selections.line_mode,
self.cursor_shape,
cx,
@@ -231,7 +231,7 @@ impl FollowableItem for Editor {
scroll_y: scroll_anchor.offset.y,
selections: self
.selections
.disjoint_anchors()
.disjoint_anchors_arc()
.iter()
.map(|s| serialize_selection(s, &snapshot))
.collect(),
@@ -310,7 +310,7 @@ impl FollowableItem for Editor {
let snapshot = self.buffer.read(cx).snapshot(cx);
update.selections = self
.selections
.disjoint_anchors()
.disjoint_anchors_arc()
.iter()
.map(|s| serialize_selection(s, &snapshot))
.collect();
@@ -1675,7 +1675,7 @@ impl SearchableItem for Editor {
cx: &mut Context<Self>,
) -> usize {
let buffer = self.buffer().read(cx).snapshot(cx);
let current_index_position = if self.selections.disjoint_anchors().len() == 1 {
let current_index_position = if self.selections.disjoint_anchors_arc().len() == 1 {
self.selections.newest_anchor().head()
} else {
matches[current_index].start
+1 -1
View File
@@ -507,7 +507,7 @@ pub(crate) fn handle_from(
{
let selections = this
.read_with(cx, |this, _| this.selections.disjoint_anchors())
.read_with(cx, |this, _| this.selections.disjoint_anchors_arc())
.ok()?;
for selection in selections.iter() {
let Some(selection_buffer_offset_head) =
+1 -1
View File
@@ -35,7 +35,7 @@ where
let project = editor.project.clone()?;
editor
.selections
.disjoint_anchors()
.disjoint_anchors_arc()
.iter()
.filter_map(|selection| Some((selection.head(), selection.head().buffer_id?)))
.unique_by(|(_, buffer_id)| *buffer_id)
+2 -5
View File
@@ -130,12 +130,9 @@ fn display_ranges<'a>(
display_map: &'a DisplaySnapshot,
selections: &'a SelectionsCollection,
) -> impl Iterator<Item = Range<DisplayPoint>> + 'a {
let pending = selections
.pending
.as_ref()
.map(|pending| &pending.selection);
let pending = selections.pending_anchor();
selections
.disjoint
.disjoint_anchors()
.iter()
.chain(pending)
.map(move |s| s.start.to_display_point(display_map)..s.end.to_display_point(display_map))
+3 -3
View File
@@ -319,7 +319,7 @@ fn cancel_flycheck_action(
};
let buffer_id = editor
.selections
.disjoint_anchors()
.disjoint_anchors_arc()
.iter()
.find_map(|selection| {
let buffer_id = selection.start.buffer_id.or(selection.end.buffer_id)?;
@@ -344,7 +344,7 @@ fn run_flycheck_action(
};
let buffer_id = editor
.selections
.disjoint_anchors()
.disjoint_anchors_arc()
.iter()
.find_map(|selection| {
let buffer_id = selection.start.buffer_id.or(selection.end.buffer_id)?;
@@ -369,7 +369,7 @@ fn clear_flycheck_action(
};
let buffer_id = editor
.selections
.disjoint_anchors()
.disjoint_anchors_arc()
.iter()
.find_map(|selection| {
let buffer_id = selection.start.buffer_id.or(selection.end.buffer_id)?;
+27 -15
View File
@@ -28,13 +28,13 @@ pub struct PendingSelection {
pub struct SelectionsCollection {
display_map: Entity<DisplayMap>,
buffer: Entity<MultiBuffer>,
pub next_selection_id: usize,
next_selection_id: usize,
pub line_mode: bool,
/// The non-pending, non-overlapping selections.
/// The [SelectionsCollection::pending] selection could possibly overlap these
pub disjoint: Arc<[Selection<Anchor>]>,
disjoint: Arc<[Selection<Anchor>]>,
/// A pending selection, such as when the mouse is being dragged
pub pending: Option<PendingSelection>,
pending: Option<PendingSelection>,
}
impl SelectionsCollection {
@@ -84,20 +84,27 @@ impl SelectionsCollection {
/// The non-pending, non-overlapping selections. There could be a pending selection that
/// overlaps these if the mouse is being dragged, etc. This could also be empty if there is a
/// pending selection. Returned as selections over Anchors.
pub fn disjoint_anchors(&self) -> Arc<[Selection<Anchor>]> {
pub fn disjoint_anchors_arc(&self) -> Arc<[Selection<Anchor>]> {
self.disjoint.clone()
}
/// The non-pending, non-overlapping selections. There could be a pending selection that
/// overlaps these if the mouse is being dragged, etc. This could also be empty if there is a
/// pending selection. Returned as selections over Anchors.
pub fn disjoint_anchors(&self) -> &[Selection<Anchor>] {
&self.disjoint
}
pub fn disjoint_anchor_ranges(&self) -> impl Iterator<Item = Range<Anchor>> {
// Mapping the Arc slice would borrow it, whereas indexing captures it.
let disjoint = self.disjoint_anchors();
let disjoint = self.disjoint_anchors_arc();
(0..disjoint.len()).map(move |ix| disjoint[ix].range())
}
/// Non-overlapping selections using anchors, including the pending selection.
pub fn all_anchors(&self, cx: &mut App) -> Arc<[Selection<Anchor>]> {
if self.pending.is_none() {
self.disjoint_anchors()
self.disjoint_anchors_arc()
} else {
let all_offset_selections = self.all::<usize>(cx);
let buffer = self.buffer(cx);
@@ -108,10 +115,12 @@ impl SelectionsCollection {
}
}
pub fn pending_anchor(&self) -> Option<Selection<Anchor>> {
self.pending
.as_ref()
.map(|pending| pending.selection.clone())
pub fn pending_anchor(&self) -> Option<&Selection<Anchor>> {
self.pending.as_ref().map(|pending| &pending.selection)
}
pub fn pending_anchor_mut(&mut self) -> Option<&mut Selection<Anchor>> {
self.pending.as_mut().map(|pending| &mut pending.selection)
}
pub fn pending<D: TextDimension + Ord + Sub<D, Output = D>>(
@@ -120,7 +129,7 @@ impl SelectionsCollection {
) -> Option<Selection<D>> {
let map = self.display_map(cx);
resolve_selections(self.pending_anchor().as_ref(), &map).next()
resolve_selections(self.pending_anchor(), &map).next()
}
pub(crate) fn pending_mode(&self) -> Option<SelectMode> {
@@ -234,8 +243,7 @@ impl SelectionsCollection {
let map = self.display_map(cx);
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().as_ref(), &map).next();
let mut pending_opt = resolve_selections_display(self.pending_anchor(), &map).next();
let selections = iter::from_fn(move || {
if let Some(pending) = pending_opt.as_mut() {
while let Some(next_selection) = disjoint.peek() {
@@ -343,9 +351,9 @@ impl SelectionsCollection {
#[cfg(any(test, feature = "test-support"))]
pub fn display_ranges(&self, cx: &mut App) -> Vec<Range<DisplayPoint>> {
let display_map = self.display_map(cx);
self.disjoint_anchors()
self.disjoint_anchors_arc()
.iter()
.chain(self.pending_anchor().as_ref())
.chain(self.pending_anchor())
.map(|s| {
if s.reversed {
s.end.to_display_point(&display_map)..s.start.to_display_point(&display_map)
@@ -412,6 +420,10 @@ impl SelectionsCollection {
);
(mutable_collection.selections_changed, result)
}
pub fn next_selection_id(&self) -> usize {
self.next_selection_id
}
}
pub struct MutableSelectionsCollection<'a> {
@@ -396,7 +396,7 @@ impl EditorTestContext {
let (multibuffer_snapshot, selections, excerpts) = self.update_editor(|editor, _, cx| {
let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
let selections = editor.selections.disjoint_anchors();
let selections = editor.selections.disjoint_anchors_arc();
let excerpts = multibuffer_snapshot
.excerpts()
.map(|(e_id, snapshot, range)| (e_id, snapshot.clone(), range))
+1 -1
View File
@@ -416,7 +416,7 @@ impl Item for TextDiffView {
pub fn selection_location_text(editor: &Editor, cx: &App) -> Option<String> {
let buffer = editor.buffer().read(cx);
let buffer_snapshot = buffer.snapshot(cx);
let first_selection = editor.selections.disjoint.first()?;
let first_selection = editor.selections.disjoint_anchors().first()?;
let selection_start = first_selection.start.to_point(&buffer_snapshot);
let selection_end = first_selection.end.to_point(&buffer_snapshot);
+2 -2
View File
@@ -463,7 +463,7 @@ pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
.collect();
vim.switch_mode(Mode::Normal, true, window, cx);
let initial_selections =
vim.update_editor(cx, |_, editor, _| editor.selections.disjoint_anchors());
vim.update_editor(cx, |_, editor, _| editor.selections.disjoint_anchors_arc());
if let Some(range) = &action.range {
let result = vim.update_editor(cx, |vim, editor, cx| {
let range = range.buffer_range(vim, editor, window, cx)?;
@@ -515,7 +515,7 @@ pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
.buffer()
.update(cx, |multi, cx| multi.last_transaction_id(cx))
{
let last_sel = editor.selections.disjoint_anchors();
let last_sel = editor.selections.disjoint_anchors_arc();
editor.modify_transaction_selection_history(tx_id, |old| {
old.0 = first_sel;
old.1 = Some(last_sel);
+1 -1
View File
@@ -22,7 +22,7 @@ impl Vim {
self.update_editor(cx, |vim, editor, cx| {
let anchors = editor
.selections
.disjoint_anchors()
.disjoint_anchors_arc()
.iter()
.map(|s| s.head())
.collect::<Vec<_>>();
+1 -1
View File
@@ -326,7 +326,7 @@ impl Vim {
let stable_anchors = editor
.selections
.disjoint_anchors()
.disjoint_anchors_arc()
.iter()
.map(|selection| {
let start = selection.start.bias_left(&display_map.buffer_snapshot);
+5 -5
View File
@@ -1075,16 +1075,16 @@ impl Vim {
}
let snapshot = s.display_map();
if let Some(pending) = s.pending.as_mut()
&& pending.selection.reversed
if let Some(pending) = s.pending_anchor_mut()
&& pending.reversed
&& mode.is_visual()
&& !last_mode.is_visual()
{
let mut end = pending.selection.end.to_point(&snapshot.buffer_snapshot);
let mut end = pending.end.to_point(&snapshot.buffer_snapshot);
end = snapshot
.buffer_snapshot
.clip_point(end + Point::new(0, 1), Bias::Right);
pending.selection.end = snapshot.buffer_snapshot.anchor_before(end);
pending.end = snapshot.buffer_snapshot.anchor_before(end);
}
s.move_with(|map, selection| {
@@ -1332,7 +1332,7 @@ impl Vim {
self.update_editor(cx, |_, editor, _| {
editor
.selections
.disjoint_anchors()
.disjoint_anchors_arc()
.iter()
.map(|selection| selection.tail()..selection.head())
.collect()
+1 -1
View File
@@ -748,7 +748,7 @@ impl Vim {
// after the change
let stable_anchors = editor
.selections
.disjoint_anchors()
.disjoint_anchors_arc()
.iter()
.map(|selection| {
let start = selection.start.bias_left(&display_map.buffer_snapshot);