Passing tests and removed local argument. Also pulled autoscroll argument out to change_selections

Keith Simmons created

Change summary

crates/collab/src/rpc.rs                      |  16 
crates/diagnostics/src/diagnostics.rs         |   8 
crates/editor/src/editor.rs                   | 337 ++++++++++----------
crates/editor/src/items.rs                    |   4 
crates/editor/src/selections_collection.rs    | 101 +----
crates/editor/src/test.rs                     |   2 
crates/go_to_line/src/go_to_line.rs           |   4 
crates/journal/src/journal.rs                 |   4 
crates/outline/src/outline.rs                 |   4 
crates/project_symbols/src/project_symbols.rs |   4 
crates/search/src/buffer_search.rs            |  27 
crates/search/src/project_search.rs           |  12 
crates/vim/src/insert.rs                      |   4 
crates/vim/src/normal.rs                      |  14 
crates/vim/src/normal/change.rs               |   6 
crates/vim/src/normal/delete.rs               |   6 
crates/vim/src/vim_test_context.rs            |   4 
crates/vim/src/visual.rs                      |  10 
crates/zed/src/zed.rs                         |  16 
19 files changed, 271 insertions(+), 312 deletions(-)

Detailed changes

crates/collab/src/rpc.rs šŸ”—

@@ -3001,7 +3001,7 @@ mod tests {
 
         // Type a completion trigger character as the guest.
         editor_b.update(cx_b, |editor, cx| {
-            editor.change_selections(true, cx, |s| s.select_ranges([13..13], None));
+            editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
             editor.handle_input(&Input(".".into()), cx);
             cx.focus(&editor_b);
         });
@@ -4213,8 +4213,8 @@ mod tests {
 
         // Move cursor to a location that contains code actions.
         editor_b.update(cx_b, |editor, cx| {
-            editor.change_selections(true, cx, |s| {
-                s.select_ranges([Point::new(1, 31)..Point::new(1, 31)], None)
+            editor.change_selections(None, cx, |s| {
+                s.select_ranges([Point::new(1, 31)..Point::new(1, 31)])
             });
             cx.focus(&editor_b);
         });
@@ -4452,7 +4452,7 @@ mod tests {
 
         // Move cursor to a location that can be renamed.
         let prepare_rename = editor_b.update(cx_b, |editor, cx| {
-            editor.change_selections(true, cx, |s| s.select_ranges([7..7], None));
+            editor.change_selections(None, cx, |s| s.select_ranges([7..7]));
             editor.rename(&Rename, cx).unwrap()
         });
 
@@ -5473,10 +5473,10 @@ mod tests {
 
         // When client B starts following client A, all visible view states are replicated to client B.
         editor_a1.update(cx_a, |editor, cx| {
-            editor.change_selections(true, cx, |s| s.select_ranges([0..1], None))
+            editor.change_selections(None, cx, |s| s.select_ranges([0..1]))
         });
         editor_a2.update(cx_a, |editor, cx| {
-            editor.change_selections(true, cx, |s| s.select_ranges([2..3], None))
+            editor.change_selections(None, cx, |s| s.select_ranges([2..3]))
         });
         workspace_b
             .update(cx_b, |workspace, cx| {
@@ -5542,7 +5542,7 @@ mod tests {
 
         // Changes to client A's editor are reflected on client B.
         editor_a1.update(cx_a, |editor, cx| {
-            editor.change_selections(true, cx, |s| s.select_ranges([1..1, 2..2], None));
+            editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2]));
         });
         editor_b1
             .condition(cx_b, |editor, cx| {
@@ -5556,7 +5556,7 @@ mod tests {
             .await;
 
         editor_a1.update(cx_a, |editor, cx| {
-            editor.change_selections(true, cx, |s| s.select_ranges([3..3], None));
+            editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
             editor.set_scroll_position(vec2f(0., 100.), cx);
         });
         editor_b1

crates/diagnostics/src/diagnostics.rs šŸ”—

@@ -5,7 +5,7 @@ use collections::{BTreeSet, HashSet};
 use editor::{
     diagnostic_block_renderer,
     display_map::{BlockDisposition, BlockId, BlockProperties, RenderBlock},
-    highlight_diagnostic_message, Editor, ExcerptId, MultiBuffer, ToOffset,
+    highlight_diagnostic_message, Autoscroll, Editor, ExcerptId, MultiBuffer, ToOffset,
 };
 use gpui::{
     actions, elements::*, fonts::TextStyle, serde_json, AnyViewHandle, AppContext, Entity,
@@ -418,7 +418,7 @@ impl ProjectDiagnosticsEditor {
             } else {
                 groups = self.path_states.get(path_ix)?.diagnostic_groups.as_slice();
                 new_excerpt_ids_by_selection_id =
-                    editor.change_selections(true, cx, |s| s.refresh());
+                    editor.change_selections(Some(Autoscroll::Fit), cx, |s| s.refresh());
                 selections = editor
                     .selections
                     .interleaved::<usize>(&editor.buffer().read(cx).read(cx));
@@ -444,8 +444,8 @@ impl ProjectDiagnosticsEditor {
                     }
                 }
             }
-            editor.change_selections(true, cx, |s| {
-                s.select(selections, None);
+            editor.change_selections(None, cx, |s| {
+                s.select(selections);
             });
             Some(())
         });

crates/editor/src/editor.rs šŸ”—

@@ -537,6 +537,7 @@ struct BracketPairState {
     pair: BracketPair,
 }
 
+#[derive(Debug)]
 struct SnippetState {
     ranges: Vec<Vec<Range<Anchor>>>,
     active_index: usize,
@@ -1304,25 +1305,12 @@ impl Editor {
         }
     }
 
-    pub fn change_selections<R>(
+    fn selections_did_change(
         &mut self,
         local: bool,
+        old_cursor_position: &Anchor,
         cx: &mut ViewContext<Self>,
-        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
-    ) -> R {
-        let old_cursor_position = self.selections.newest_anchor().head();
-        self.push_to_selection_history();
-
-        #[allow(deprecated)]
-        // Using deprecated to prevent using change_with outside of this function
-        let (autoscroll, result) =
-            self.selections
-                .change_with(self.display_map.clone(), self.buffer.clone(), cx, change);
-
-        if let Some(autoscroll) = autoscroll {
-            self.request_autoscroll(autoscroll, cx);
-        }
-
+    ) {
         if self.focused && self.leader_replica_id.is_none() {
             self.buffer.update(cx, |buffer, cx| {
                 buffer.set_active_selections(&self.selections.disjoint_anchors(), cx)
@@ -1337,20 +1325,21 @@ impl Editor {
         self.select_next_state = None;
         self.select_larger_syntax_node_stack.clear();
         self.autoclose_stack
-            .invalidate(&self.selections.disjoint_anchors(), &buffer);
+            .invalidate(&self.selections.disjoint_anchors(), buffer);
         self.snippet_stack
-            .invalidate(&self.selections.disjoint_anchors(), &buffer);
+            .invalidate(&self.selections.disjoint_anchors(), buffer);
         self.take_rename(false, cx);
 
         let new_cursor_position = self.selections.newest_anchor().head();
 
         self.push_to_nav_history(
             old_cursor_position.clone(),
-            Some(new_cursor_position.to_point(&buffer)),
+            Some(new_cursor_position.to_point(buffer)),
             cx,
         );
 
         if local {
+            let new_cursor_position = self.selections.newest_anchor().head();
             let completion_menu = match self.context_menu.as_mut() {
                 Some(ContextMenu::Completions(menu)) => Some(menu),
                 _ => {
@@ -1360,13 +1349,13 @@ impl Editor {
             };
 
             if let Some(completion_menu) = completion_menu {
-                let cursor_position = new_cursor_position.to_offset(&buffer);
+                let cursor_position = new_cursor_position.to_offset(buffer);
                 let (word_range, kind) =
                     buffer.surrounding_word(completion_menu.initial_position.clone());
                 if kind == Some(CharKind::Word)
                     && word_range.to_inclusive().contains(&cursor_position)
                 {
-                    let query = Self::completion_query(&buffer, cursor_position);
+                    let query = Self::completion_query(buffer, cursor_position);
                     cx.background()
                         .block(completion_menu.filter(query.as_deref(), cx.background().clone()));
                     self.show_completions(&ShowCompletions, cx);
@@ -1387,6 +1376,25 @@ impl Editor {
         self.pause_cursor_blinking(cx);
         cx.emit(Event::SelectionsChanged { local });
         cx.notify();
+    }
+
+    pub fn change_selections<R>(
+        &mut self,
+        autoscroll: Option<Autoscroll>,
+        cx: &mut ViewContext<Self>,
+        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
+    ) -> R {
+        let old_cursor_position = self.selections.newest_anchor().head();
+        self.push_to_selection_history();
+
+        let result =
+            self.selections
+                .change_with(self.display_map.clone(), self.buffer.clone(), cx, change);
+
+        if let Some(autoscroll) = autoscroll {
+            self.request_autoscroll(autoscroll, cx);
+        }
+        self.selections_did_change(true, &old_cursor_position, cx);
 
         result
     }
@@ -1466,7 +1474,7 @@ impl Editor {
         let position = position.to_offset(&display_map, Bias::Left);
         let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
 
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             let mut pending = s
                 .pending_mut()
                 .as_mut()
@@ -1540,7 +1548,7 @@ impl Editor {
             }
         }
 
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             if add {
                 if click_count > 1 {
                     s.delete(newest_selection.id);
@@ -1664,7 +1672,7 @@ impl Editor {
                 pending.reversed = false;
             }
 
-            self.change_selections(true, cx, |s| {
+            self.change_selections(None, cx, |s| {
                 s.pending_mut().as_mut().unwrap().selection = pending;
             });
         } else {
@@ -1682,8 +1690,8 @@ impl Editor {
             let selections = self
                 .selections
                 .interleaved::<usize>(&self.buffer.read(cx).snapshot(cx));
-            self.change_selections(true, cx, |s| {
-                s.select(selections, None);
+            self.change_selections(None, cx, |s| {
+                s.select(selections);
                 s.clear_pending();
             });
         }
@@ -1723,8 +1731,8 @@ impl Editor {
             })
             .collect::<Vec<_>>();
 
-        self.change_selections(true, cx, |s| {
-            s.select_ranges(selection_ranges, None);
+        self.change_selections(None, cx, |s| {
+            s.select_ranges(selection_ranges);
         });
         cx.notify();
     }
@@ -1752,7 +1760,7 @@ impl Editor {
                 return;
             }
 
-            if self.change_selections(true, cx, |s| s.try_cancel()) {
+            if self.change_selections(None, cx, |s| s.try_cancel()) {
                 self.request_autoscroll(Autoscroll::Fit, cx);
                 return;
             }
@@ -1762,7 +1770,7 @@ impl Editor {
     }
 
     #[cfg(any(test, feature = "test-support"))]
-    pub fn selected_ranges<D: TextDimension + Ord + Sub<D, Output = D>>(
+    pub fn selected_ranges<D: TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug>(
         &self,
         cx: &AppContext,
     ) -> Vec<Range<D>> {
@@ -1893,9 +1901,7 @@ impl Editor {
                 })
                 .collect();
 
-            this.change_selections(true, cx, |s| {
-                s.select(new_selections, Some(Autoscroll::Fit))
-            });
+            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(new_selections));
 
             this.request_autoscroll(Autoscroll::Fit, cx);
         });
@@ -1941,8 +1947,8 @@ impl Editor {
                     .collect()
             };
 
-            this.change_selections(true, cx, |s| {
-                s.select(selections, Some(Autoscroll::Fit));
+            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.select(selections);
             })
         });
     }
@@ -2004,7 +2010,7 @@ impl Editor {
             }
             drop(snapshot);
 
-            self.change_selections(true, cx, |s| s.select_anchors(selections, None));
+            self.change_selections(None, cx, |s| s.select_anchors(selections));
             true
         } else {
             false
@@ -2102,8 +2108,8 @@ impl Editor {
         });
 
         if let Some(new_selections) = new_selections {
-            self.change_selections(true, cx, |s| {
-                s.select(new_selections, None);
+            self.change_selections(None, cx, |s| {
+                s.select(new_selections);
             });
         }
         if let Some(bracket_pair_state) = bracket_pair_state {
@@ -2147,8 +2153,8 @@ impl Editor {
                 })
                 .collect();
             self.autoclose_stack.pop();
-            self.change_selections(true, cx, |s| {
-                s.select(new_selections, Some(Autoscroll::Fit));
+            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.select(new_selections);
             });
             true
         } else {
@@ -2739,8 +2745,8 @@ impl Editor {
         });
 
         if let Some(tabstop) = tabstops.first() {
-            self.change_selections(true, cx, |s| {
-                s.select_ranges(tabstop.iter().cloned(), Some(Autoscroll::Fit));
+            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.select_ranges(tabstop.iter().cloned());
             });
             self.snippet_stack.push(SnippetState {
                 active_index: 0,
@@ -2780,15 +2786,18 @@ impl Editor {
                 }
             }
             if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
-                self.change_selections(true, cx, |s| {
-                    s.select_anchor_ranges(
-                        current_ranges.into_iter().cloned(),
-                        Some(Autoscroll::Fit),
-                    )
-                });
+                let snapshot = self.buffer.read(cx).snapshot(cx);
+                let current_ranges_resolved = current_ranges
+                    .iter()
+                    .map(|range| range.start.to_point(&snapshot)..range.end.to_point(&snapshot))
+                    .collect::<Vec<_>>();
+                dbg!(&current_ranges, current_ranges_resolved);
 
+                self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                    s.select_anchor_ranges(current_ranges.into_iter().cloned())
+                });
                 // If snippet state is not at the last tabstop, push it back on the stack
-                if snippet.active_index + 1 != snippet.ranges.len() {
+                if snippet.active_index + 1 < snippet.ranges.len() {
                     self.snippet_stack.push(snippet);
                 }
                 return true;
@@ -2836,14 +2845,14 @@ impl Editor {
         }
 
         self.transact(cx, |this, cx| {
-            this.change_selections(true, cx, |s| s.select(selections, Some(Autoscroll::Fit)));
+            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
             this.insert("", cx);
         });
     }
 
     pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
         self.transact(cx, |this, cx| {
-            this.change_selections(true, cx, |s| {
+            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
                 s.move_with(|map, selection| {
                     if selection.is_empty() {
                         let cursor = movement::right(map, selection.head());
@@ -2895,8 +2904,8 @@ impl Editor {
                         selection.end = selection.start;
                     }
                 });
-                this.change_selections(true, cx, |s| {
-                    s.select(selections, Some(Autoscroll::Fit));
+                this.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                    s.select(selections);
                 });
             });
         } else {
@@ -2962,8 +2971,8 @@ impl Editor {
                 }
             });
 
-            this.change_selections(true, cx, |s| {
-                s.select(selections, Some(Autoscroll::Fit));
+            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.select(selections);
             });
         });
     }
@@ -3016,8 +3025,8 @@ impl Editor {
                 );
             });
             let snapshot = this.buffer.read(cx).snapshot(cx);
-            this.change_selections(true, cx, |s| {
-                s.select(s.interleaved::<usize>(&snapshot), Some(Autoscroll::Fit))
+            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.select(s.interleaved::<usize>(&snapshot))
             });
         });
     }
@@ -3099,8 +3108,8 @@ impl Editor {
                 })
                 .collect();
 
-            this.change_selections(true, cx, |s| {
-                s.select(new_selections, Some(Autoscroll::Fit));
+            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.select(new_selections);
             });
         });
     }
@@ -3251,8 +3260,8 @@ impl Editor {
                 }
             });
             this.fold_ranges(refold_ranges, cx);
-            this.change_selections(true, cx, |s| {
-                s.select(new_selections, Some(Autoscroll::Fit));
+            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.select(new_selections);
             })
         });
     }
@@ -3356,15 +3365,13 @@ impl Editor {
                 }
             });
             this.fold_ranges(refold_ranges, cx);
-            this.change_selections(true, cx, |s| {
-                s.select(new_selections, Some(Autoscroll::Fit))
-            });
+            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(new_selections));
         });
     }
 
     pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
         self.transact(cx, |this, cx| {
-            let edits = this.change_selections(true, cx, |s| {
+            let edits = this.change_selections(Some(Autoscroll::Fit), cx, |s| {
                 let mut edits: Vec<(Range<usize>, String)> = Default::default();
                 s.move_with(|display_map, selection| {
                     if !selection.is_empty() {
@@ -3406,8 +3413,8 @@ impl Editor {
             });
             this.buffer.update(cx, |buffer, cx| buffer.edit(edits, cx));
             let buffer = this.buffer.read(cx).snapshot(cx);
-            this.change_selections(true, cx, |s| {
-                s.select(s.interleaved::<usize>(&buffer), Some(Autoscroll::Fit));
+            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.select(s.interleaved::<usize>(&buffer));
             });
         });
     }
@@ -3439,8 +3446,8 @@ impl Editor {
         }
 
         self.transact(cx, |this, cx| {
-            this.change_selections(true, cx, |s| {
-                s.select(selections, Some(Autoscroll::Fit));
+            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.select(selections);
             });
             this.insert("", cx);
             cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
@@ -3540,9 +3547,7 @@ impl Editor {
                     let selections = this
                         .selections
                         .interleaved::<usize>(&this.buffer.read(cx).read(cx));
-                    this.change_selections(true, cx, |s| {
-                        s.select(selections, Some(Autoscroll::Fit))
-                    });
+                    this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
                 } else {
                     this.insert(&clipboard_text, cx);
                 }
@@ -3553,10 +3558,10 @@ impl Editor {
     pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
         if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
             if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
-                self.change_selections(true, cx, |s| {
+                self.change_selections(None, cx, |s| {
                     // TODO: move to SelectionsCollection to preserve selection
                     // invariants without rechecking
-                    s.select_anchors(selections.to_vec(), None);
+                    s.select_anchors(selections.to_vec());
                 });
             }
             self.request_autoscroll(Autoscroll::Fit, cx);
@@ -3568,10 +3573,10 @@ impl Editor {
         if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
             if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
             {
-                self.change_selections(true, cx, |s| {
+                self.change_selections(None, cx, |s| {
                     // TODO: move to SelectionsCollection to preserve selection
                     // invariants without rechecking
-                    s.select_anchors(selections.to_vec(), None);
+                    s.select_anchors(selections.to_vec());
                 });
             }
             self.request_autoscroll(Autoscroll::Fit, cx);
@@ -3585,7 +3590,7 @@ impl Editor {
     }
 
     pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_with(|map, selection| {
                 let cursor = if selection.is_empty() {
                     movement::left(map, selection.start)
@@ -3598,13 +3603,13 @@ impl Editor {
     }
 
     pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
         })
     }
 
     pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_with(|map, selection| {
                 let cursor = if selection.is_empty() {
                     movement::right(map, selection.end)
@@ -3617,7 +3622,7 @@ impl Editor {
     }
 
     pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
         })
     }
@@ -3638,7 +3643,7 @@ impl Editor {
             return;
         }
 
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_with(|map, selection| {
                 if !selection.is_empty() {
                     selection.goal = SelectionGoal::None;
@@ -3650,7 +3655,7 @@ impl Editor {
     }
 
     pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
         })
     }
@@ -3669,7 +3674,7 @@ impl Editor {
             return;
         }
 
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_with(|map, selection| {
                 if !selection.is_empty() {
                     selection.goal = SelectionGoal::None;
@@ -3681,7 +3686,7 @@ impl Editor {
     }
 
     pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
         });
     }
@@ -3691,7 +3696,7 @@ impl Editor {
         _: &MoveToPreviousWordStart,
         cx: &mut ViewContext<Self>,
     ) {
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_cursors_with(|map, head, _| {
                 (
                     movement::previous_word_start(map, head),
@@ -3706,7 +3711,7 @@ impl Editor {
         _: &MoveToPreviousSubwordStart,
         cx: &mut ViewContext<Self>,
     ) {
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_cursors_with(|map, head, _| {
                 (
                     movement::previous_subword_start(map, head),
@@ -3721,7 +3726,7 @@ impl Editor {
         _: &SelectToPreviousWordStart,
         cx: &mut ViewContext<Self>,
     ) {
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_heads_with(|map, head, _| {
                 (
                     movement::previous_word_start(map, head),
@@ -3736,7 +3741,7 @@ impl Editor {
         _: &SelectToPreviousSubwordStart,
         cx: &mut ViewContext<Self>,
     ) {
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_heads_with(|map, head, _| {
                 (
                     movement::previous_subword_start(map, head),
@@ -3752,7 +3757,7 @@ impl Editor {
         cx: &mut ViewContext<Self>,
     ) {
         self.transact(cx, |this, cx| {
-            this.change_selections(true, cx, |s| {
+            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
                 s.move_with(|map, selection| {
                     if selection.is_empty() {
                         let cursor = movement::previous_word_start(map, selection.head());
@@ -3770,7 +3775,7 @@ impl Editor {
         cx: &mut ViewContext<Self>,
     ) {
         self.transact(cx, |this, cx| {
-            this.change_selections(true, cx, |s| {
+            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
                 s.move_with(|map, selection| {
                     if selection.is_empty() {
                         let cursor = movement::previous_subword_start(map, selection.head());
@@ -3783,7 +3788,7 @@ impl Editor {
     }
 
     pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_cursors_with(|map, head, _| {
                 (movement::next_word_end(map, head), SelectionGoal::None)
             });
@@ -3795,7 +3800,7 @@ impl Editor {
         _: &MoveToNextSubwordEnd,
         cx: &mut ViewContext<Self>,
     ) {
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_cursors_with(|map, head, _| {
                 (movement::next_subword_end(map, head), SelectionGoal::None)
             });
@@ -3803,7 +3808,7 @@ impl Editor {
     }
 
     pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_heads_with(|map, head, _| {
                 (movement::next_word_end(map, head), SelectionGoal::None)
             });
@@ -3815,7 +3820,7 @@ impl Editor {
         _: &SelectToNextSubwordEnd,
         cx: &mut ViewContext<Self>,
     ) {
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_heads_with(|map, head, _| {
                 (movement::next_subword_end(map, head), SelectionGoal::None)
             });
@@ -3824,7 +3829,7 @@ impl Editor {
 
     pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
         self.transact(cx, |this, cx| {
-            this.change_selections(true, cx, |s| {
+            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
                 s.move_with(|map, selection| {
                     if selection.is_empty() {
                         let cursor = movement::next_word_end(map, selection.head());
@@ -3842,7 +3847,7 @@ impl Editor {
         cx: &mut ViewContext<Self>,
     ) {
         self.transact(cx, |this, cx| {
-            this.change_selections(true, cx, |s| {
+            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
                 s.move_with(|map, selection| {
                     if selection.is_empty() {
                         let cursor = movement::next_subword_end(map, selection.head());
@@ -3859,7 +3864,7 @@ impl Editor {
         _: &MoveToBeginningOfLine,
         cx: &mut ViewContext<Self>,
     ) {
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_cursors_with(|map, head, _| {
                 (
                     movement::line_beginning(map, head, true),
@@ -3874,7 +3879,7 @@ impl Editor {
         action: &SelectToBeginningOfLine,
         cx: &mut ViewContext<Self>,
     ) {
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_heads_with(|map, head, _| {
                 (
                     movement::line_beginning(map, head, action.stop_at_soft_wraps),
@@ -3890,7 +3895,7 @@ impl Editor {
         cx: &mut ViewContext<Self>,
     ) {
         self.transact(cx, |this, cx| {
-            this.change_selections(true, cx, |s| {
+            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
                 s.move_with(|_, selection| {
                     selection.reversed = true;
                 });
@@ -3907,7 +3912,7 @@ impl Editor {
     }
 
     pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_cursors_with(|map, head, _| {
                 (movement::line_end(map, head, true), SelectionGoal::None)
             });
@@ -3919,7 +3924,7 @@ impl Editor {
         action: &SelectToEndOfLine,
         cx: &mut ViewContext<Self>,
     ) {
-        self.change_selections(true, cx, |s| {
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_heads_with(|map, head, _| {
                 (
                     movement::line_end(map, head, action.stop_at_soft_wraps),
@@ -3959,8 +3964,8 @@ impl Editor {
             return;
         }
 
-        self.change_selections(true, cx, |s| {
-            s.select_ranges(vec![0..0], Some(Autoscroll::Fit));
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+            s.select_ranges(vec![0..0]);
         });
     }
 
@@ -3970,8 +3975,8 @@ impl Editor {
             .last::<Point>(&self.buffer.read(cx).read(cx));
         selection.set_head(Point::zero(), SelectionGoal::None);
 
-        self.change_selections(true, cx, |s| {
-            s.select(vec![selection], Some(Autoscroll::Fit));
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+            s.select(vec![selection]);
         });
     }
 
@@ -3982,8 +3987,8 @@ impl Editor {
         }
 
         let cursor = self.buffer.read(cx).read(cx).len();
-        self.change_selections(true, cx, |s| {
-            s.select_ranges(vec![cursor..cursor], Some(Autoscroll::Fit))
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+            s.select_ranges(vec![cursor..cursor])
         });
     }
 
@@ -4028,15 +4033,15 @@ impl Editor {
         let buffer = self.buffer.read(cx).snapshot(cx);
         let mut selection = self.selections.first::<usize>(&buffer);
         selection.set_head(buffer.len(), SelectionGoal::None);
-        self.change_selections(true, cx, |s| {
-            s.select(vec![selection], Some(Autoscroll::Fit));
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+            s.select(vec![selection]);
         });
     }
 
     pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
         let end = self.buffer.read(cx).read(cx).len();
-        self.change_selections(true, cx, |s| {
-            s.select_ranges(vec![0..end], Some(Autoscroll::Fit));
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+            s.select_ranges(vec![0..end]);
         });
     }
 
@@ -4052,8 +4057,8 @@ impl Editor {
             selection.end = cmp::min(max_point, Point::new(rows.end, 0));
             selection.reversed = false;
         }
-        self.change_selections(true, cx, |s| {
-            s.select(selections, Some(Autoscroll::Fit));
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+            s.select(selections);
         });
     }
 
@@ -4077,8 +4082,8 @@ impl Editor {
             }
         }
         self.unfold_ranges(to_unfold, true, cx);
-        self.change_selections(true, cx, |s| {
-            s.select_ranges(new_selection_ranges, Some(Autoscroll::Fit));
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+            s.select_ranges(new_selection_ranges);
         });
     }
 
@@ -4180,8 +4185,8 @@ impl Editor {
             state.stack.pop();
         }
 
-        self.change_selections(true, cx, |s| {
-            s.select(new_selections, Some(Autoscroll::Fit));
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+            s.select(new_selections);
         });
         if state.stack.len() > 1 {
             self.add_selections_state = Some(state);
@@ -4229,11 +4234,11 @@ impl Editor {
 
                 if let Some(next_selected_range) = next_selected_range {
                     self.unfold_ranges([next_selected_range.clone()], false, cx);
-                    self.change_selections(true, cx, |s| {
+                    self.change_selections(Some(Autoscroll::Newest), cx, |s| {
                         if action.replace_newest {
                             s.delete(s.newest_anchor().id);
                         }
-                        s.insert_range(next_selected_range, Some(Autoscroll::Newest));
+                        s.insert_range(next_selected_range);
                     });
                 } else {
                     select_next_state.done = true;
@@ -4262,8 +4267,8 @@ impl Editor {
                     done: false,
                 };
                 self.unfold_ranges([selection.start..selection.end], false, cx);
-                self.change_selections(true, cx, |s| {
-                    s.select(selections, Some(Autoscroll::Newest));
+                self.change_selections(Some(Autoscroll::Newest), cx, |s| {
+                    s.select(selections);
                 });
                 self.select_next_state = Some(select_state);
             } else {
@@ -4388,8 +4393,8 @@ impl Editor {
             let selections = this
                 .selections
                 .interleaved::<usize>(&this.buffer.read(cx).read(cx));
-            this.change_selections(true, cx, |s| {
-                s.select(selections, Some(Autoscroll::Fit));
+            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.select(selections);
             });
         });
     }
@@ -4437,8 +4442,8 @@ impl Editor {
 
         if selected_larger_node {
             stack.push(old_selections);
-            self.change_selections(true, cx, |s| {
-                s.select(new_selections, Some(Autoscroll::Fit));
+            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.select(new_selections);
             });
         }
         self.select_larger_syntax_node_stack = stack;
@@ -4451,8 +4456,8 @@ impl Editor {
     ) {
         let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
         if let Some(selections) = stack.pop() {
-            self.change_selections(true, cx, |s| {
-                s.select(selections.to_vec(), Some(Autoscroll::Fit));
+            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                s.select(selections.to_vec());
             });
         }
         self.select_larger_syntax_node_stack = stack;
@@ -4482,8 +4487,8 @@ impl Editor {
             }
         }
 
-        self.change_selections(true, cx, |s| {
-            s.select(selections, Some(Autoscroll::Fit));
+        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+            s.select(selections);
         });
     }
 
@@ -4491,10 +4496,10 @@ impl Editor {
         self.end_selection(cx);
         self.selection_history.mode = SelectionHistoryMode::Undoing;
         if let Some(entry) = self.selection_history.undo_stack.pop_back() {
-            self.change_selections(true, cx, |s| {
+            self.change_selections(None, cx, |s| {
                 // TODO: Move to selections so selections invariants can be preserved rather than
                 // rechecking them.
-                s.select_anchors(entry.selections.to_vec(), None)
+                s.select_anchors(entry.selections.to_vec())
             });
             self.select_next_state = entry.select_next_state;
             self.add_selections_state = entry.add_selections_state;
@@ -4507,10 +4512,10 @@ impl Editor {
         self.end_selection(cx);
         self.selection_history.mode = SelectionHistoryMode::Redoing;
         if let Some(entry) = self.selection_history.redo_stack.pop_back() {
-            self.change_selections(true, cx, |s| {
+            self.change_selections(None, cx, |s| {
                 // TODO: Move to selections so selections invariants can be preserved rather than
                 // rechecking them.
-                s.select_anchors(entry.selections.to_vec(), None)
+                s.select_anchors(entry.selections.to_vec())
             });
             self.select_next_state = entry.select_next_state;
             self.add_selections_state = entry.add_selections_state;
@@ -4566,17 +4571,14 @@ impl Editor {
 
             if let Some((primary_range, group_id)) = group {
                 self.activate_diagnostics(group_id, cx);
-                self.change_selections(true, cx, |s| {
-                    s.select(
-                        vec![Selection {
-                            id: selection.id,
-                            start: primary_range.start,
-                            end: primary_range.start,
-                            reversed: false,
-                            goal: SelectionGoal::None,
-                        }],
-                        Some(Autoscroll::Center),
-                    );
+                self.change_selections(Some(Autoscroll::Center), cx, |s| {
+                    s.select(vec![Selection {
+                        id: selection.id,
+                        start: primary_range.start,
+                        end: primary_range.start,
+                        reversed: false,
+                        goal: SelectionGoal::None,
+                    }]);
                 });
                 break;
             } else {
@@ -4640,8 +4642,8 @@ impl Editor {
                         if editor_handle != target_editor_handle {
                             nav_history.borrow_mut().disable();
                         }
-                        target_editor.change_selections(true, cx, |s| {
-                            s.select_ranges([range], Some(Autoscroll::Center));
+                        target_editor.change_selections(Some(Autoscroll::Center), cx, |s| {
+                            s.select_ranges([range]);
                         });
 
                         nav_history.borrow_mut().enable();
@@ -4945,7 +4947,7 @@ impl Editor {
                 reversed: false,
                 goal: SelectionGoal::None,
             };
-            self.change_selections(true, cx, |s| s.select(vec![new_selection], None));
+            self.change_selections(None, cx, |s| s.select(vec![new_selection]));
         }
 
         Some(rename)
@@ -5089,9 +5091,12 @@ impl Editor {
         selections: Vec<Selection<Anchor>>,
         cx: &mut ViewContext<Self>,
     ) {
-        self.change_selections(false, cx, |s| {
-            s.select_anchors(selections, None);
-        });
+        let old_cursor_position = self.selections.newest_anchor().head();
+        self.selections
+            .change_with(self.display_map.clone(), self.buffer.clone(), cx, |s| {
+                s.select_anchors(selections);
+            });
+        self.selections_did_change(false, &old_cursor_position, cx);
     }
 
     fn push_to_selection_history(&mut self) {
@@ -5650,8 +5655,8 @@ impl Editor {
             for (buffer, ranges) in new_selections_by_buffer.into_iter() {
                 let editor = workspace.open_project_item::<Self>(buffer, cx);
                 editor.update(cx, |editor, cx| {
-                    editor.change_selections(true, cx, |s| {
-                        s.select_ranges(ranges, Some(Autoscroll::Newest));
+                    editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
+                        s.select_ranges(ranges);
                     });
                 });
             }
@@ -6294,7 +6299,7 @@ mod tests {
 
         // No event is emitted when the mutation is a no-op.
         editor2.update(cx, |editor, cx| {
-            editor.change_selections(true, cx, |s| s.select_ranges([0..0], None));
+            editor.change_selections(None, cx, |s| s.select_ranges([0..0]));
 
             editor.backspace(&Backspace, cx);
         });
@@ -6312,7 +6317,7 @@ mod tests {
 
         editor.update(cx, |editor, cx| {
             editor.start_transaction_at(now, cx);
-            editor.change_selections(true, cx, |s| s.select_ranges([2..4], None));
+            editor.change_selections(None, cx, |s| s.select_ranges([2..4]));
 
             editor.insert("cd", cx);
             editor.end_transaction_at(now, cx);
@@ -6320,14 +6325,14 @@ mod tests {
             assert_eq!(editor.selected_ranges(cx), vec![4..4]);
 
             editor.start_transaction_at(now, cx);
-            editor.change_selections(true, cx, |s| s.select_ranges([4..5], None));
+            editor.change_selections(None, cx, |s| s.select_ranges([4..5]));
             editor.insert("e", cx);
             editor.end_transaction_at(now, cx);
             assert_eq!(editor.text(cx), "12cde6");
             assert_eq!(editor.selected_ranges(cx), vec![5..5]);
 
             now += group_interval + Duration::from_millis(1);
-            editor.change_selections(true, cx, |s| s.select_ranges([2..2], None));
+            editor.change_selections(None, cx, |s| s.select_ranges([2..2]));
 
             // Simulate an edit in another editor
             buffer.update(cx, |buffer, cx| {
@@ -6481,17 +6486,17 @@ mod tests {
 
             // Move the cursor a small distance.
             // Nothing is added to the navigation history.
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(None, cx, |s| {
                 s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
             });
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(None, cx, |s| {
                 s.select_display_ranges([DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)])
             });
             assert!(nav_history.borrow_mut().pop_backward().is_none());
 
             // Move the cursor a large distance.
             // The history can jump back to the previous position.
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(None, cx, |s| {
                 s.select_display_ranges([DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)])
             });
             let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
@@ -6640,7 +6645,7 @@ mod tests {
         let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 
         view.update(cx, |view, cx| {
-            view.change_selections(true, cx, |s| {
+            view.change_selections(None, cx, |s| {
                 s.select_display_ranges([DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)]);
             });
             view.fold(&Fold, cx);
@@ -6758,7 +6763,7 @@ mod tests {
                 &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
             );
 
-            view.change_selections(true, cx, |s| {
+            view.change_selections(None, cx, |s| {
                 s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]);
             });
             view.select_to_beginning(&SelectToBeginning, cx);
@@ -6882,7 +6887,7 @@ mod tests {
         let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
         let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
         view.update(cx, |view, cx| {
-            view.change_selections(true, cx, |s| {
+            view.change_selections(None, cx, |s| {
                 s.select_display_ranges([empty_range(0, "ⓐⓑⓒⓓⓔ".len())]);
             });
             view.move_down(&MoveDown, cx);
@@ -6929,7 +6934,7 @@ mod tests {
         let buffer = MultiBuffer::build_simple("abc\n  def", cx);
         let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
         view.update(cx, |view, cx| {
-            view.change_selections(true, cx, |s| {
+            view.change_selections(None, cx, |s| {
                 s.select_display_ranges([
                     DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
                     DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
@@ -7089,7 +7094,7 @@ mod tests {
         let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
         let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
         view.update(cx, |view, cx| {
-            view.change_selections(true, cx, |s| {
+            view.change_selections(None, cx, |s| {
                 s.select_display_ranges([
                     DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
                     DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
@@ -7200,7 +7205,7 @@ mod tests {
                 "use one::{\n    two::three::\n    four::five\n};"
             );
 
-            view.change_selections(true, cx, |s| {
+            view.change_selections(None, cx, |s| {
                 s.select_display_ranges([DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)]);
             });
 
@@ -7251,7 +7256,7 @@ mod tests {
         let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 
         editor.update(cx, |editor, cx| {
-            editor.change_selections(true, cx, |s| s.select_ranges(ranges, None));
+            editor.change_selections(None, cx, |s| s.select_ranges(ranges));
             editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
             assert_eq!(editor.text(cx), " four");
         });

crates/editor/src/items.rs šŸ”—

@@ -276,8 +276,8 @@ impl Item for Editor {
                 let nav_history = self.nav_history.take();
                 self.scroll_position = data.scroll_position;
                 self.scroll_top_anchor = scroll_top_anchor;
-                self.change_selections(true, cx, |s| {
-                    s.select_ranges([offset..offset], Some(Autoscroll::Fit))
+                self.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                    s.select_ranges([offset..offset])
                 });
                 self.nav_history = nav_history;
                 true

crates/editor/src/selections_collection.rs šŸ”—

@@ -12,8 +12,7 @@ use util::post_inc;
 
 use crate::{
     display_map::{DisplayMap, DisplaySnapshot, ToDisplayPoint},
-    Anchor, Autoscroll, DisplayPoint, ExcerptId, MultiBuffer, MultiBufferSnapshot, SelectMode,
-    ToOffset,
+    Anchor, DisplayPoint, ExcerptId, MultiBuffer, MultiBufferSnapshot, SelectMode, ToOffset,
 };
 
 #[derive(Clone)]
@@ -79,10 +78,10 @@ impl SelectionsCollection {
 
     pub fn interleaved<'a, D>(&self, buffer: &MultiBufferSnapshot) -> Vec<Selection<D>>
     where
-        D: 'a + TextDimension + Ord + Sub<D, Output = D>,
+        D: 'a + TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug,
     {
-        let anchor_disjoint = &self.disjoint;
-        let mut disjoint = resolve_multiple::<D, _>(anchor_disjoint.iter(), &buffer).peekable();
+        let disjoint_anchors = &self.disjoint;
+        let mut disjoint = resolve_multiple::<D, _>(disjoint_anchors.iter(), &buffer).peekable();
 
         let mut pending_opt = self.pending::<D>(&buffer);
 
@@ -197,36 +196,31 @@ impl SelectionsCollection {
         self.interleaved(&snapshot).last().unwrap().clone()
     }
 
-    // NOTE do not use. This should only be called from Editor::change_selections.
-    #[deprecated]
-    pub fn change_with<R>(
+    pub(crate) fn change_with<R>(
         &mut self,
         display_map: ModelHandle<DisplayMap>,
         buffer: ModelHandle<MultiBuffer>,
         cx: &mut MutableAppContext,
         change: impl FnOnce(&mut MutableSelectionsCollection) -> R,
-    ) -> (Option<Autoscroll>, R) {
+    ) -> R {
         let mut mutable_collection = MutableSelectionsCollection {
             collection: self,
-            autoscroll: None,
             display_map,
             buffer,
             cx,
         };
 
         let result = change(&mut mutable_collection);
-
         assert!(
             !mutable_collection.disjoint.is_empty() || mutable_collection.pending.is_some(),
             "There must be at least one selection"
         );
-        (mutable_collection.autoscroll, result)
+        result
     }
 }
 
 pub struct MutableSelectionsCollection<'a> {
     collection: &'a mut SelectionsCollection,
-    pub autoscroll: Option<Autoscroll>,
     buffer: ModelHandle<MultiBuffer>,
     display_map: ModelHandle<DisplayMap>,
     cx: &'a mut MutableAppContext,
@@ -307,7 +301,7 @@ impl<'a> MutableSelectionsCollection<'a> {
         }
     }
 
-    pub fn insert_range<T>(&mut self, range: Range<T>, autoscroll: Option<Autoscroll>)
+    pub fn insert_range<T>(&mut self, range: Range<T>)
     where
         T: 'a
             + ToOffset
@@ -335,10 +329,10 @@ impl<'a> MutableSelectionsCollection<'a> {
             reversed,
             goal: SelectionGoal::None,
         });
-        self.select(selections, autoscroll);
+        self.select(selections);
     }
 
-    pub fn select<T>(&mut self, mut selections: Vec<Selection<T>>, autoscroll: Option<Autoscroll>)
+    pub fn select<T>(&mut self, mut selections: Vec<Selection<T>>)
     where
         T: ToOffset + ToPoint + Ord + std::marker::Copy + std::fmt::Debug,
     {
@@ -360,8 +354,6 @@ impl<'a> MutableSelectionsCollection<'a> {
             }
         }
 
-        self.autoscroll = autoscroll.or(self.autoscroll.take());
-
         self.collection.disjoint = Arc::from_iter(selections.into_iter().map(|selection| {
             let end_bias = if selection.end > selection.start {
                 Bias::Left
@@ -380,46 +372,14 @@ impl<'a> MutableSelectionsCollection<'a> {
         self.collection.pending = None;
     }
 
-    pub fn select_anchors(
-        &mut self,
-        mut selections: Vec<Selection<Anchor>>,
-        autoscroll: Option<Autoscroll>,
-    ) {
+    pub fn select_anchors(&mut self, selections: Vec<Selection<Anchor>>) {
         let buffer = self.buffer.read(self.cx).snapshot(self.cx);
-        selections.sort_unstable_by(|a, b| a.start.cmp(&b.start, &buffer));
-
-        // Merge overlapping selections.
-        let mut i = 1;
-        while i < selections.len() {
-            if selections[i - 1]
-                .end
-                .cmp(&selections[i].start, &buffer)
-                .is_ge()
-            {
-                let removed = selections.remove(i);
-                if removed.start.cmp(&selections[i - 1].start, &buffer).is_lt() {
-                    selections[i - 1].start = removed.start;
-                }
-                if removed.end.cmp(&selections[i - 1].end, &buffer).is_gt() {
-                    selections[i - 1].end = removed.end;
-                }
-            } else {
-                i += 1;
-            }
-        }
-
-        self.autoscroll = autoscroll.or(self.autoscroll.take());
-
-        self.collection.disjoint = Arc::from_iter(
-            selections
-                .into_iter()
-                .map(|selection| reset_biases(selection, &buffer)),
-        );
-
-        self.collection.pending = None;
+        let resolved_selections =
+            resolve_multiple::<usize, _>(&selections, &buffer).collect::<Vec<_>>();
+        self.select(resolved_selections);
     }
 
-    pub fn select_ranges<I, T>(&mut self, ranges: I, autoscroll: Option<Autoscroll>)
+    pub fn select_ranges<I, T>(&mut self, ranges: I)
     where
         I: IntoIterator<Item = Range<T>>,
         T: ToOffset,
@@ -446,14 +406,10 @@ impl<'a> MutableSelectionsCollection<'a> {
             })
             .collect::<Vec<_>>();
 
-        self.select(selections, autoscroll)
+        self.select(selections)
     }
 
-    pub fn select_anchor_ranges<I: IntoIterator<Item = Range<Anchor>>>(
-        &mut self,
-        ranges: I,
-        autoscroll: Option<Autoscroll>,
-    ) {
+    pub fn select_anchor_ranges<I: IntoIterator<Item = Range<Anchor>>>(&mut self, ranges: I) {
         let buffer = self.buffer.read(self.cx).snapshot(self.cx);
         let selections = ranges
             .into_iter()
@@ -476,7 +432,7 @@ impl<'a> MutableSelectionsCollection<'a> {
             })
             .collect::<Vec<_>>();
 
-        self.select_anchors(selections, autoscroll)
+        self.select_anchors(selections)
     }
 
     #[cfg(any(test, feature = "test-support"))]
@@ -505,7 +461,7 @@ impl<'a> MutableSelectionsCollection<'a> {
                 }
             })
             .collect();
-        self.select(selections, None);
+        self.select(selections);
     }
 
     pub fn move_with(
@@ -523,7 +479,7 @@ impl<'a> MutableSelectionsCollection<'a> {
             })
             .collect();
 
-        self.select(selections, Some(Autoscroll::Fit))
+        self.select(selections)
     }
 
     pub fn move_heads_with(
@@ -572,7 +528,7 @@ impl<'a> MutableSelectionsCollection<'a> {
                 }
             })
             .collect();
-        self.select(new_selections, None);
+        self.select(new_selections);
     }
 
     /// Compute new ranges for any selections that were located in excerpts that have
@@ -620,10 +576,7 @@ impl<'a> MutableSelectionsCollection<'a> {
             .collect();
 
         if !adjusted_disjoint.is_empty() {
-            self.select::<usize>(
-                resolve_multiple(adjusted_disjoint.iter(), &buffer).collect(),
-                None,
-            );
+            self.select::<usize>(resolve_multiple(adjusted_disjoint.iter(), &buffer).collect());
         }
 
         if let Some(pending) = pending.as_mut() {
@@ -665,12 +618,16 @@ pub fn resolve_multiple<'a, D, I>(
     snapshot: &MultiBufferSnapshot,
 ) -> impl 'a + Iterator<Item = Selection<D>>
 where
-    D: TextDimension + Ord + Sub<D, Output = D>,
+    D: TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug,
     I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
 {
     let (to_summarize, selections) = selections.into_iter().tee();
     let mut summaries = snapshot
-        .summaries_for_anchors::<D, _>(to_summarize.flat_map(|s| [&s.start, &s.end]))
+        .summaries_for_anchors::<D, _>(
+            to_summarize
+                .flat_map(|s| [&s.start, &s.end])
+                .collect::<Vec<_>>(),
+        )
         .into_iter();
     selections.map(move |s| Selection {
         id: s.id,
@@ -692,7 +649,7 @@ fn reset_biases(
     mut selection: Selection<Anchor>,
     buffer: &MultiBufferSnapshot,
 ) -> Selection<Anchor> {
-    let end_bias = if selection.end.cmp(&selection.start, buffer).is_gt() {
+    let end_bias = if selection.end.to_offset(buffer) > selection.start.to_offset(buffer) {
         Bias::Left
     } else {
         Bias::Right

crates/editor/src/test.rs šŸ”—

@@ -43,7 +43,7 @@ pub fn marked_display_snapshot(
 pub fn select_ranges(editor: &mut Editor, marked_text: &str, cx: &mut ViewContext<Editor>) {
     let (umarked_text, text_ranges) = marked_text_ranges(marked_text);
     assert_eq!(editor.text(cx), umarked_text);
-    editor.change_selections(true, cx, |s| s.select_ranges(text_ranges, None));
+    editor.change_selections(None, cx, |s| s.select_ranges(text_ranges));
 }
 
 pub fn assert_text_with_selections(

crates/go_to_line/src/go_to_line.rs šŸ”—

@@ -80,8 +80,8 @@ impl GoToLine {
             if let Some(rows) = active_editor.highlighted_rows() {
                 let snapshot = active_editor.snapshot(cx).display_snapshot;
                 let position = DisplayPoint::new(rows.start, 0).to_point(&snapshot);
-                active_editor.change_selections(true, cx, |s| {
-                    s.select_ranges([position..position], Some(Autoscroll::Center))
+                active_editor.change_selections(Some(Autoscroll::Center), cx, |s| {
+                    s.select_ranges([position..position])
                 });
             }
         });

crates/journal/src/journal.rs šŸ”—

@@ -57,8 +57,8 @@ pub fn new_journal_entry(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
                 if let Some(editor) = item.downcast::<Editor>() {
                     editor.update(&mut cx, |editor, cx| {
                         let len = editor.buffer().read(cx).read(cx).len();
-                        editor.change_selections(true, cx, |s| {
-                            s.select_ranges([len..len], Some(Autoscroll::Center))
+                        editor.change_selections(Some(Autoscroll::Center), cx, |s| {
+                            s.select_ranges([len..len])
                         });
                         if len > 0 {
                             editor.insert("\n\n", cx);

crates/outline/src/outline.rs šŸ”—

@@ -215,8 +215,8 @@ impl PickerDelegate for OutlineView {
             if let Some(rows) = active_editor.highlighted_rows() {
                 let snapshot = active_editor.snapshot(cx).display_snapshot;
                 let position = DisplayPoint::new(rows.start, 0).to_point(&snapshot);
-                active_editor.change_selections(true, cx, |s| {
-                    s.select_ranges([position..position], Some(Autoscroll::Center))
+                active_editor.change_selections(Some(Autoscroll::Center), cx, |s| {
+                    s.select_ranges([position..position])
                 });
             }
         });

crates/project_symbols/src/project_symbols.rs šŸ”—

@@ -145,8 +145,8 @@ impl ProjectSymbolsView {
 
                         let editor = workspace.open_project_item::<Editor>(buffer, cx);
                         editor.update(cx, |editor, cx| {
-                            editor.change_selections(true, cx, |s| {
-                                s.select_ranges([position..position], Some(Autoscroll::Center))
+                            editor.change_selections(Some(Autoscroll::Center), cx, |s| {
+                                s.select_ranges([position..position])
                             });
                         });
                     });

crates/search/src/buffer_search.rs šŸ”—

@@ -395,8 +395,8 @@ impl BufferSearchBar {
                         );
                         let range_to_select = ranges[new_index].clone();
                         editor.unfold_ranges([range_to_select.clone()], false, cx);
-                        editor.change_selections(true, cx, |s| {
-                            s.select_ranges([range_to_select], Some(Autoscroll::Fit))
+                        editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                            s.select_ranges([range_to_select])
                         });
                     }
                 });
@@ -538,12 +538,11 @@ impl BufferSearchBar {
                                 editor.update(cx, |editor, cx| {
                                     if select_closest_match {
                                         if let Some(match_ix) = this.active_match_index {
-                                            editor.change_selections(true, cx, |s| {
-                                                s.select_ranges(
-                                                    [ranges[match_ix].clone()],
-                                                    Some(Autoscroll::Fit),
-                                                )
-                                            });
+                                            editor.change_selections(
+                                                Some(Autoscroll::Fit),
+                                                cx,
+                                                |s| s.select_ranges([ranges[match_ix].clone()]),
+                                            );
                                         }
                                     }
 
@@ -725,7 +724,7 @@ mod tests {
         });
 
         editor.update(cx, |editor, cx| {
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(None, cx, |s| {
                 s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)])
             });
         });
@@ -810,7 +809,7 @@ mod tests {
         // Park the cursor in between matches and ensure that going to the previous match selects
         // the closest match to the left.
         editor.update(cx, |editor, cx| {
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(None, cx, |s| {
                 s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
             });
         });
@@ -829,7 +828,7 @@ mod tests {
         // Park the cursor in between matches and ensure that going to the next match selects the
         // closest match to the right.
         editor.update(cx, |editor, cx| {
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(None, cx, |s| {
                 s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
             });
         });
@@ -848,7 +847,7 @@ mod tests {
         // Park the cursor after the last match and ensure that going to the previous match selects
         // the last match.
         editor.update(cx, |editor, cx| {
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(None, cx, |s| {
                 s.select_display_ranges([DisplayPoint::new(3, 60)..DisplayPoint::new(3, 60)])
             });
         });
@@ -867,7 +866,7 @@ mod tests {
         // Park the cursor after the last match and ensure that going to the next match selects the
         // first match.
         editor.update(cx, |editor, cx| {
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(None, cx, |s| {
                 s.select_display_ranges([DisplayPoint::new(3, 60)..DisplayPoint::new(3, 60)])
             });
         });
@@ -886,7 +885,7 @@ mod tests {
         // Park the cursor before the first match and ensure that going to the previous match
         // selects the last match.
         editor.update(cx, |editor, cx| {
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(None, cx, |s| {
                 s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)])
             });
         });

crates/search/src/project_search.rs šŸ”—

@@ -462,8 +462,8 @@ impl ProjectSearchView {
             let range_to_select = model.match_ranges[new_index].clone();
             self.results_editor.update(cx, |editor, cx| {
                 editor.unfold_ranges([range_to_select.clone()], false, cx);
-                editor.change_selections(true, cx, |s| {
-                    s.select_ranges([range_to_select], Some(Autoscroll::Fit))
+                editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                    s.select_ranges([range_to_select])
                 });
             });
         }
@@ -479,9 +479,7 @@ impl ProjectSearchView {
     fn focus_results_editor(&self, cx: &mut ViewContext<Self>) {
         self.query_editor.update(cx, |query_editor, cx| {
             let cursor = query_editor.selections.newest_anchor().head();
-            query_editor.change_selections(true, cx, |s| {
-                s.select_ranges([cursor.clone()..cursor], None)
-            });
+            query_editor.change_selections(None, cx, |s| s.select_ranges([cursor.clone()..cursor]));
         });
         cx.focus(&self.results_editor);
     }
@@ -493,8 +491,8 @@ impl ProjectSearchView {
         } else {
             self.results_editor.update(cx, |editor, cx| {
                 if reset_selections {
-                    editor.change_selections(true, cx, |s| {
-                        s.select_ranges(match_ranges.first().cloned(), Some(Autoscroll::Fit))
+                    editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
+                        s.select_ranges(match_ranges.first().cloned())
                     });
                 }
                 editor.highlight_background::<Self>(

crates/vim/src/insert.rs šŸ”—

@@ -1,5 +1,5 @@
 use crate::{state::Mode, Vim};
-use editor::Bias;
+use editor::{Autoscroll, Bias};
 use gpui::{actions, MutableAppContext, ViewContext};
 use language::SelectionGoal;
 use workspace::Workspace;
@@ -13,7 +13,7 @@ pub fn init(cx: &mut MutableAppContext) {
 fn normal_before(_: &mut Workspace, _: &NormalBefore, cx: &mut ViewContext<Workspace>) {
     Vim::update(cx, |state, cx| {
         state.update_active_editor(cx, |editor, cx| {
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
                 s.move_cursors_with(|map, mut cursor, _| {
                     *cursor.column_mut() = cursor.column().saturating_sub(1);
                     (map.clip_point(cursor, Bias::Left), SelectionGoal::None)

crates/vim/src/normal.rs šŸ”—

@@ -8,7 +8,7 @@ use crate::{
 };
 use change::init as change_init;
 use collections::HashSet;
-use editor::{Bias, DisplayPoint};
+use editor::{Autoscroll, Bias, DisplayPoint};
 use gpui::{actions, MutableAppContext, ViewContext};
 use language::SelectionGoal;
 use workspace::Workspace;
@@ -76,7 +76,7 @@ pub fn normal_motion(motion: Motion, cx: &mut MutableAppContext) {
 
 fn move_cursor(vim: &mut Vim, motion: Motion, cx: &mut MutableAppContext) {
     vim.update_active_editor(cx, |editor, cx| {
-        editor.change_selections(true, cx, |s| {
+        editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
             s.move_cursors_with(|map, cursor, goal| motion.move_point(map, cursor, goal))
         })
     });
@@ -86,7 +86,7 @@ fn insert_after(_: &mut Workspace, _: &InsertAfter, cx: &mut ViewContext<Workspa
     Vim::update(cx, |vim, cx| {
         vim.switch_mode(Mode::Insert, cx);
         vim.update_active_editor(cx, |editor, cx| {
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
                 s.move_cursors_with(|map, cursor, goal| {
                     Motion::Right.move_point(map, cursor, goal)
                 });
@@ -103,7 +103,7 @@ fn insert_first_non_whitespace(
     Vim::update(cx, |vim, cx| {
         vim.switch_mode(Mode::Insert, cx);
         vim.update_active_editor(cx, |editor, cx| {
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
                 s.move_cursors_with(|map, cursor, goal| {
                     Motion::FirstNonWhitespace.move_point(map, cursor, goal)
                 });
@@ -116,7 +116,7 @@ fn insert_end_of_line(_: &mut Workspace, _: &InsertEndOfLine, cx: &mut ViewConte
     Vim::update(cx, |vim, cx| {
         vim.switch_mode(Mode::Insert, cx);
         vim.update_active_editor(cx, |editor, cx| {
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
                 s.move_cursors_with(|map, cursor, goal| {
                     Motion::EndOfLine.move_point(map, cursor, goal)
                 });
@@ -145,7 +145,7 @@ fn insert_line_above(_: &mut Workspace, _: &InsertLineAbove, cx: &mut ViewContex
                     (start_of_line..start_of_line, new_text)
                 });
                 editor.edit_with_autoindent(edits, cx);
-                editor.change_selections(true, cx, |s| {
+                editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
                     s.move_cursors_with(|map, mut cursor, _| {
                         *cursor.row_mut() -= 1;
                         *cursor.column_mut() = map.line_len(cursor.row());
@@ -176,7 +176,7 @@ fn insert_line_below(_: &mut Workspace, _: &InsertLineBelow, cx: &mut ViewContex
                     new_text.push_str(&" ".repeat(indent as usize));
                     (end_of_line..end_of_line, new_text)
                 });
-                editor.change_selections(true, cx, |s| {
+                editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
                     s.move_cursors_with(|map, cursor, goal| {
                         Motion::EndOfLine.move_point(map, cursor, goal)
                     });

crates/vim/src/normal/change.rs šŸ”—

@@ -1,5 +1,5 @@
 use crate::{motion::Motion, state::Mode, Vim};
-use editor::{char_kind, movement};
+use editor::{char_kind, movement, Autoscroll};
 use gpui::{impl_actions, MutableAppContext, ViewContext};
 use serde::Deserialize;
 use workspace::Workspace;
@@ -22,7 +22,7 @@ pub fn change_over(vim: &mut Vim, motion: Motion, cx: &mut MutableAppContext) {
         editor.transact(cx, |editor, cx| {
             // We are swapping to insert mode anyway. Just set the line end clipping behavior now
             editor.set_clip_at_line_ends(false, cx);
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
                 s.move_with(|map, selection| {
                     motion.expand_selection(map, selection, false);
                 });
@@ -48,7 +48,7 @@ fn change_word(
             editor.transact(cx, |editor, cx| {
                 // We are swapping to insert mode anyway. Just set the line end clipping behavior now
                 editor.set_clip_at_line_ends(false, cx);
-                editor.change_selections(true, cx, |s| {
+                editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
                     s.move_with(|map, selection| {
                         if selection.end.column() == map.line_len(selection.end.row()) {
                             return;

crates/vim/src/normal/delete.rs šŸ”—

@@ -1,6 +1,6 @@
 use crate::{motion::Motion, Vim};
 use collections::HashMap;
-use editor::Bias;
+use editor::{Autoscroll, Bias};
 use gpui::MutableAppContext;
 
 pub fn delete_over(vim: &mut Vim, motion: Motion, cx: &mut MutableAppContext) {
@@ -8,7 +8,7 @@ pub fn delete_over(vim: &mut Vim, motion: Motion, cx: &mut MutableAppContext) {
         editor.transact(cx, |editor, cx| {
             editor.set_clip_at_line_ends(false, cx);
             let mut original_columns: HashMap<_, _> = Default::default();
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
                 s.move_with(|map, selection| {
                     let original_head = selection.head();
                     motion.expand_selection(map, selection, true);
@@ -19,7 +19,7 @@ pub fn delete_over(vim: &mut Vim, motion: Motion, cx: &mut MutableAppContext) {
 
             // Fixup cursor position after the deletion
             editor.set_clip_at_line_ends(true, cx);
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
                 s.move_with(|map, selection| {
                     let mut cursor = selection.head();
                     if motion.linewise() {

crates/vim/src/vim_test_context.rs šŸ”—

@@ -3,7 +3,7 @@ use std::ops::{Deref, Range};
 use collections::BTreeMap;
 use itertools::{Either, Itertools};
 
-use editor::display_map::ToDisplayPoint;
+use editor::{display_map::ToDisplayPoint, Autoscroll};
 use gpui::{json::json, keymap::Keystroke, ViewHandle};
 use indoc::indoc;
 use language::Selection;
@@ -128,7 +128,7 @@ impl<'a> VimTestContext<'a> {
             let (unmarked_text, markers) = marked_text(&text);
             editor.set_text(unmarked_text, cx);
             let cursor_offset = markers[0];
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
                 s.replace_cursors_with(|map| vec![cursor_offset.to_display_point(map)])
             });
         })

crates/vim/src/visual.rs šŸ”—

@@ -1,4 +1,4 @@
-use editor::Bias;
+use editor::{Autoscroll, Bias};
 use gpui::{actions, MutableAppContext, ViewContext};
 use workspace::Workspace;
 
@@ -14,7 +14,7 @@ pub fn init(cx: &mut MutableAppContext) {
 pub fn visual_motion(motion: Motion, cx: &mut MutableAppContext) {
     Vim::update(cx, |vim, cx| {
         vim.update_active_editor(cx, |editor, cx| {
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
                 s.move_with(|map, selection| {
                     let (new_head, goal) = motion.move_point(map, selection.head(), selection.goal);
                     let new_head = map.clip_at_line_end(new_head);
@@ -42,7 +42,7 @@ pub fn change(_: &mut Workspace, _: &VisualChange, cx: &mut ViewContext<Workspac
     Vim::update(cx, |vim, cx| {
         vim.update_active_editor(cx, |editor, cx| {
             editor.set_clip_at_line_ends(false, cx);
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
                 s.move_with(|map, selection| {
                     if !selection.reversed {
                         // Head was at the end of the selection, and now is at the start. We need to move the end
@@ -63,7 +63,7 @@ pub fn delete(_: &mut Workspace, _: &VisualDelete, cx: &mut ViewContext<Workspac
         vim.switch_mode(Mode::Normal, cx);
         vim.update_active_editor(cx, |editor, cx| {
             editor.set_clip_at_line_ends(false, cx);
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
                 s.move_with(|map, selection| {
                     if !selection.reversed {
                         // Head was at the end of the selection, and now is at the start. We need to move the end
@@ -77,7 +77,7 @@ pub fn delete(_: &mut Workspace, _: &VisualDelete, cx: &mut ViewContext<Workspac
 
             // Fixup cursor position after the deletion
             editor.set_clip_at_line_ends(true, cx);
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
                 s.move_with(|map, selection| {
                     let mut cursor = selection.head();
                     cursor = map.clip_point(cursor, Bias::Left);

crates/zed/src/zed.rs šŸ”—

@@ -309,7 +309,7 @@ fn open_config_file(
 mod tests {
     use super::*;
     use assets::Assets;
-    use editor::{DisplayPoint, Editor};
+    use editor::{Autoscroll, DisplayPoint, Editor};
     use gpui::{AssetSource, MutableAppContext, TestAppContext, ViewHandle};
     use project::{Fs, ProjectPath};
     use serde_json::json;
@@ -962,7 +962,7 @@ mod tests {
             .downcast::<Editor>()
             .unwrap();
         editor1.update(cx, |editor, cx| {
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
                 s.select_display_ranges([DisplayPoint::new(10, 0)..DisplayPoint::new(10, 0)])
             });
         });
@@ -981,7 +981,7 @@ mod tests {
 
         editor3
             .update(cx, |editor, cx| {
-                editor.change_selections(true, cx, |s| {
+                editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
                     s.select_display_ranges([DisplayPoint::new(12, 0)..DisplayPoint::new(12, 0)])
                 });
                 editor.newline(&Default::default(), cx);
@@ -1124,19 +1124,19 @@ mod tests {
         // Modify file to collapse multiple nav history entries into the same location.
         // Ensure we don't visit the same location twice when navigating.
         editor1.update(cx, |editor, cx| {
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(None, cx, |s| {
                 s.select_display_ranges([DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)])
             })
         });
 
         for _ in 0..5 {
             editor1.update(cx, |editor, cx| {
-                editor.change_selections(true, cx, |s| {
+                editor.change_selections(None, cx, |s| {
                     s.select_display_ranges([DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)])
                 });
             });
             editor1.update(cx, |editor, cx| {
-                editor.change_selections(true, cx, |s| {
+                editor.change_selections(None, cx, |s| {
                     s.select_display_ranges([DisplayPoint::new(13, 0)..DisplayPoint::new(13, 0)])
                 })
             });
@@ -1144,7 +1144,7 @@ mod tests {
 
         editor1.update(cx, |editor, cx| {
             editor.transact(cx, |editor, cx| {
-                editor.change_selections(true, cx, |s| {
+                editor.change_selections(None, cx, |s| {
                     s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(14, 0)])
                 });
                 editor.insert("", cx);
@@ -1152,7 +1152,7 @@ mod tests {
         });
 
         editor1.update(cx, |editor, cx| {
-            editor.change_selections(true, cx, |s| {
+            editor.change_selections(None, cx, |s| {
                 s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
             })
         });