Make `SelectionsCollection::disjoint_anchor_ranges` return an iterator (#22948)

Michael Sloan created

This helps discourage unnecessary collection to Vec

Release Notes:

- N/A

Change summary

crates/editor/src/editor.rs                | 29 ++++++++---------------
crates/editor/src/items.rs                 |  4 +-
crates/editor/src/selections_collection.rs | 13 ++++-----
crates/vim/src/command.rs                  |  9 ++++--
4 files changed, 24 insertions(+), 31 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -2559,7 +2559,7 @@ impl Editor {
             if start_offset > buffer_snapshot.len() || end_offset > buffer_snapshot.len() {
                 continue;
             }
-            if self.selections.disjoint_anchor_ranges().iter().any(|s| {
+            if self.selections.disjoint_anchor_ranges().any(|s| {
                 if s.start.buffer_id != selection.start.buffer_id
                     || s.end.buffer_id != selection.end.buffer_id
                 {
@@ -10567,12 +10567,9 @@ impl Editor {
         } else {
             let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
             let mut toggled_buffers = HashSet::default();
-            for (_, buffer_snapshot, _) in multi_buffer_snapshot.excerpts_in_ranges(
-                self.selections
-                    .disjoint_anchors()
-                    .into_iter()
-                    .map(|selection| selection.range()),
-            ) {
+            for (_, buffer_snapshot, _) in
+                multi_buffer_snapshot.excerpts_in_ranges(self.selections.disjoint_anchor_ranges())
+            {
                 let buffer_id = buffer_snapshot.remote_id();
                 if toggled_buffers.insert(buffer_id) {
                     if self.buffer_folded(buffer_id, cx) {
@@ -10653,12 +10650,9 @@ impl Editor {
         } else {
             let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
             let mut folded_buffers = HashSet::default();
-            for (_, buffer_snapshot, _) in multi_buffer_snapshot.excerpts_in_ranges(
-                self.selections
-                    .disjoint_anchors()
-                    .into_iter()
-                    .map(|selection| selection.range()),
-            ) {
+            for (_, buffer_snapshot, _) in
+                multi_buffer_snapshot.excerpts_in_ranges(self.selections.disjoint_anchor_ranges())
+            {
                 let buffer_id = buffer_snapshot.remote_id();
                 if folded_buffers.insert(buffer_id) {
                     self.fold_buffer(buffer_id, cx);
@@ -10819,12 +10813,9 @@ impl Editor {
         } else {
             let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
             let mut unfolded_buffers = HashSet::default();
-            for (_, buffer_snapshot, _) in multi_buffer_snapshot.excerpts_in_ranges(
-                self.selections
-                    .disjoint_anchors()
-                    .into_iter()
-                    .map(|selection| selection.range()),
-            ) {
+            for (_, buffer_snapshot, _) in
+                multi_buffer_snapshot.excerpts_in_ranges(self.selections.disjoint_anchor_ranges())
+            {
                 let buffer_id = buffer_snapshot.remote_id();
                 if unfolded_buffers.insert(buffer_id) {
                     self.unfold_buffer(buffer_id, cx);

crates/editor/src/items.rs 🔗

@@ -1260,8 +1260,8 @@ impl SearchableItem for Editor {
             return;
         }
 
-        let ranges = self.selections.disjoint_anchor_ranges();
-        if ranges.iter().any(|range| range.start != range.end) {
+        let ranges = self.selections.disjoint_anchor_ranges().collect::<Vec<_>>();
+        if ranges.iter().any(|s| s.start != s.end) {
             self.set_search_within_ranges(&ranges, cx);
         } else if let Some(previous_search_ranges) = self.previous_search_ranges.take() {
             self.set_search_within_ranges(&previous_search_ranges, cx)

crates/editor/src/selections_collection.rs 🔗

@@ -88,6 +88,12 @@ impl SelectionsCollection {
         self.disjoint.clone()
     }
 
+    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();
+        (0..disjoint.len()).map(move |ix| disjoint[ix].range())
+    }
+
     pub fn pending_anchor(&self) -> Option<Selection<Anchor>> {
         self.pending
             .as_ref()
@@ -317,13 +323,6 @@ impl SelectionsCollection {
         self.all(cx).last().unwrap().clone()
     }
 
-    pub fn disjoint_anchor_ranges(&self) -> Vec<Range<Anchor>> {
-        self.disjoint_anchors()
-            .iter()
-            .map(|s| s.start..s.end)
-            .collect()
-    }
-
     #[cfg(any(test, feature = "test-support"))]
     pub fn ranges<D: TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug>(
         &self,

crates/vim/src/command.rs 🔗

@@ -185,9 +185,12 @@ pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
 
         let previous_selections = vim
             .update_editor(cx, |_, editor, cx| {
-                let selections = action
-                    .restore_selection
-                    .then(|| editor.selections.disjoint_anchor_ranges());
+                let selections = action.restore_selection.then(|| {
+                    editor
+                        .selections
+                        .disjoint_anchor_ranges()
+                        .collect::<Vec<_>>()
+                });
                 editor.change_selections(None, cx, |s| {
                     let end = Point::new(range.end.0, s.buffer().line_len(range.end));
                     s.select_ranges([end..Point::new(range.start.0, 0)]);