Flush pending selection before performing any action on all selections

Max Brunsfeld , Antonio Scandurra , and Nathan Sobo created

Closes #155

Co-Authored-By: Antonio Scandurra <me@as-cii.com>
Co-Authored-By: Nathan Sobo <nathan@zed.dev>

Change summary

zed/src/editor.rs | 108 ++++++++++++++++++++++++------------------------
1 file changed, 55 insertions(+), 53 deletions(-)

Detailed changes

zed/src/editor.rs 🔗

@@ -298,7 +298,7 @@ pub struct Editor {
     pending_selection: Option<Selection>,
     next_selection_id: usize,
     add_selections_state: Option<AddSelectionsState>,
-    select_larger_syntax_node_stack: Vec<Vec<Selection>>,
+    select_larger_syntax_node_stack: Vec<Arc<[Selection]>>,
     scroll_position: Vector2F,
     scroll_top_anchor: Anchor,
     autoscroll_requested: bool,
@@ -510,15 +510,14 @@ impl Editor {
             return false;
         }
 
-        let first_cursor_top = self
-            .selections(cx)
+        let selections = self.selections(cx);
+        let first_cursor_top = selections
             .first()
             .unwrap()
             .head()
             .to_display_point(&display_map, Bias::Left)
             .row() as f32;
-        let last_cursor_bottom = self
-            .selections(cx)
+        let last_cursor_bottom = selections
             .last()
             .unwrap()
             .head()
@@ -560,12 +559,13 @@ impl Editor {
         scroll_width: f32,
         max_glyph_width: f32,
         layouts: &[text_layout::Line],
-        cx: &mut MutableAppContext,
+        cx: &mut ViewContext<Self>,
     ) -> bool {
+        let selections = self.selections(cx);
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let mut target_left = std::f32::INFINITY;
         let mut target_right = 0.0_f32;
-        for selection in self.selections(cx) {
+        for selection in selections.iter() {
             let head = selection.head().to_display_point(&display_map, Bias::Left);
             let start_column = head.column().saturating_sub(3);
             let end_column = cmp::min(display_map.line_len(head.row()), head.column() + 3);
@@ -654,12 +654,10 @@ impl Editor {
 
     fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
         if let Some(selection) = self.pending_selection.take() {
-            let mut selections = self.selections(cx.as_ref()).to_vec();
+            let mut selections = self.selections(cx).to_vec();
             let ix = self.selection_insertion_index(&selections, &selection.start, cx.as_ref());
             selections.insert(ix, selection);
             self.update_selections(selections, false, cx);
-        } else {
-            log::error!("end_selection dispatched with no pending selection");
         }
     }
 
@@ -668,12 +666,13 @@ impl Editor {
     }
 
     pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
-        let selections = self.selections(cx.as_ref());
         if let Some(pending_selection) = self.pending_selection.take() {
+            let selections = self.selections(cx);
             if selections.is_empty() {
                 self.update_selections(vec![pending_selection], true, cx);
             }
         } else {
+            let selections = self.selections(cx);
             let mut oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
             if selections.len() == 1 {
                 oldest_selection.start = oldest_selection.head().clone();
@@ -742,8 +741,9 @@ impl Editor {
     pub fn insert(&mut self, action: &Insert, cx: &mut ViewContext<Self>) {
         let mut old_selections = SmallVec::<[_; 32]>::new();
         {
+            let selections = self.selections(cx);
             let buffer = self.buffer.read(cx);
-            for selection in self.selections(cx.as_ref()) {
+            for selection in selections.iter() {
                 let start = selection.start.to_offset(buffer);
                 let end = selection.end.to_offset(buffer);
                 old_selections.push((selection.id, start..end));
@@ -789,7 +789,7 @@ impl Editor {
 
     pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
-        let mut selections = self.selections(cx.as_ref()).to_vec();
+        let mut selections = self.selections(cx).to_vec();
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         {
             let buffer = self.buffer.read(cx);
@@ -813,7 +813,7 @@ impl Editor {
     pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections(cx.as_ref()).to_vec();
+        let mut selections = self.selections(cx).to_vec();
         {
             let buffer = self.buffer.read(cx);
             for selection in &mut selections {
@@ -836,14 +836,14 @@ impl Editor {
     pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
 
+        let selections = self.selections(cx);
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let app = cx.as_ref();
-        let buffer = self.buffer.read(app);
+        let buffer = self.buffer.read(cx);
 
         let mut new_cursors = Vec::new();
         let mut edit_ranges = Vec::new();
 
-        let mut selections = self.selections(app).iter().peekable();
+        let mut selections = selections.iter().peekable();
         while let Some(selection) = selections.next() {
             let mut rows = selection.spanned_rows(false, &display_map).buffer_rows;
             let goal_display_column = selection
@@ -913,7 +913,7 @@ impl Editor {
     pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
 
-        let mut selections = self.selections(cx.as_ref()).to_vec();
+        let mut selections = self.selections(cx).to_vec();
         {
             // Temporarily bias selections right to allow newly duplicate lines to push them down
             // when the selections are at the beginning of a line.
@@ -973,8 +973,8 @@ impl Editor {
     pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
 
+        let selections = self.selections(cx);
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let app = cx.as_ref();
         let buffer = self.buffer.read(cx);
 
         let mut edits = Vec::new();
@@ -982,7 +982,7 @@ impl Editor {
         let mut old_folds = Vec::new();
         let mut new_folds = Vec::new();
 
-        let mut selections = self.selections(app).iter().peekable();
+        let mut selections = selections.iter().peekable();
         let mut contiguous_selections = Vec::new();
         while let Some(selection) = selections.next() {
             // Accumulate contiguous regions of rows that we want to move.
@@ -1063,8 +1063,8 @@ impl Editor {
     pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
 
+        let selections = self.selections(cx);
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let app = cx.as_ref();
         let buffer = self.buffer.read(cx);
 
         let mut edits = Vec::new();
@@ -1072,7 +1072,7 @@ impl Editor {
         let mut old_folds = Vec::new();
         let mut new_folds = Vec::new();
 
-        let mut selections = self.selections(app).iter().peekable();
+        let mut selections = selections.iter().peekable();
         let mut contiguous_selections = Vec::new();
         while let Some(selection) = selections.next() {
             // Accumulate contiguous regions of rows that we want to move.
@@ -1150,7 +1150,7 @@ impl Editor {
     pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
         let mut text = String::new();
-        let mut selections = self.selections(cx.as_ref()).to_vec();
+        let mut selections = self.selections(cx).to_vec();
         let mut clipboard_selections = Vec::with_capacity(selections.len());
         {
             let buffer = self.buffer.read(cx);
@@ -1185,12 +1185,12 @@ impl Editor {
     }
 
     pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
+        let selections = self.selections(cx);
         let buffer = self.buffer.read(cx);
         let max_point = buffer.max_point();
         let mut text = String::new();
-        let selections = self.selections(cx.as_ref());
         let mut clipboard_selections = Vec::with_capacity(selections.len());
-        for selection in selections {
+        for selection in selections.iter() {
             let mut start = selection.start.to_point(buffer);
             let mut end = selection.end.to_point(buffer);
             let is_entire_line = start == end;
@@ -1217,7 +1217,7 @@ impl Editor {
         if let Some(item) = cx.as_mut().read_from_clipboard() {
             let clipboard_text = item.text();
             if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
-                let selections = self.selections(cx.as_ref()).to_vec();
+                let selections = self.selections(cx);
                 let all_selections_were_entire_line =
                     clipboard_selections.iter().all(|s| s.is_entire_line);
                 if clipboard_selections.len() != selections.len() {
@@ -1284,8 +1284,7 @@ impl Editor {
 
     pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let app = cx.as_ref();
-        let mut selections = self.selections(app).to_vec();
+        let mut selections = self.selections(cx).to_vec();
         {
             for selection in &mut selections {
                 let start = selection.start.to_display_point(&display_map, Bias::Left);
@@ -1308,7 +1307,7 @@ impl Editor {
 
     pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections(cx.as_ref()).to_vec();
+        let mut selections = self.selections(cx).to_vec();
         {
             let buffer = self.buffer.read(cx);
             for selection in &mut selections {
@@ -1324,7 +1323,7 @@ impl Editor {
 
     pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections(cx.as_ref()).to_vec();
+        let mut selections = self.selections(cx).to_vec();
         {
             for selection in &mut selections {
                 let start = selection.start.to_display_point(&display_map, Bias::Left);
@@ -1347,7 +1346,7 @@ impl Editor {
 
     pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections(cx.as_ref()).to_vec();
+        let mut selections = self.selections(cx).to_vec();
         {
             let app = cx.as_ref();
             let buffer = self.buffer.read(app);
@@ -1367,7 +1366,7 @@ impl Editor {
         if matches!(self.mode, EditorMode::SingleLine) {
             cx.propagate_action();
         } else {
-            let mut selections = self.selections(cx.as_ref()).to_vec();
+            let mut selections = self.selections(cx).to_vec();
             {
                 for selection in &mut selections {
                     let start = selection.start.to_display_point(&display_map, Bias::Left);
@@ -1390,7 +1389,7 @@ impl Editor {
 
     pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections(cx.as_ref()).to_vec();
+        let mut selections = self.selections(cx).to_vec();
         {
             let app = cx.as_ref();
             let buffer = self.buffer.read(app);
@@ -1409,7 +1408,7 @@ impl Editor {
             cx.propagate_action();
         } else {
             let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-            let mut selections = self.selections(cx.as_ref()).to_vec();
+            let mut selections = self.selections(cx).to_vec();
             {
                 for selection in &mut selections {
                     let start = selection.start.to_display_point(&display_map, Bias::Left);
@@ -1494,7 +1493,7 @@ impl Editor {
     ) {
         self.start_transaction(cx);
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections(cx.as_ref()).to_vec();
+        let mut selections = self.selections(cx).to_vec();
         {
             let buffer = self.buffer.read(cx);
             for selection in &mut selections {
@@ -1564,7 +1563,7 @@ impl Editor {
     ) {
         self.start_transaction(cx);
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections(cx.as_ref()).to_vec();
+        let mut selections = self.selections(cx).to_vec();
         {
             let buffer = self.buffer.read(cx);
             for selection in &mut selections {
@@ -1700,7 +1699,7 @@ impl Editor {
     }
 
     pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
-        let mut selection = self.selections(cx.as_ref()).last().unwrap().clone();
+        let mut selection = self.selections(cx).last().unwrap().clone();
         selection.set_head(self.buffer.read(cx), Anchor::min());
         self.update_selections(vec![selection], true, cx);
     }
@@ -1719,7 +1718,7 @@ impl Editor {
     }
 
     pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
-        let mut selection = self.selections(cx.as_ref()).last().unwrap().clone();
+        let mut selection = self.selections(cx).last().unwrap().clone();
         selection.set_head(self.buffer.read(cx), Anchor::max());
         self.update_selections(vec![selection], true, cx);
     }
@@ -1737,8 +1736,8 @@ impl Editor {
 
     pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let buffer = self.buffer.read(cx);
         let mut selections = self.selections(cx).to_vec();
+        let buffer = self.buffer.read(cx);
         let max_point = buffer.max_point();
         for selection in &mut selections {
             let rows = selection.spanned_rows(true, &display_map).buffer_rows;
@@ -1754,12 +1753,12 @@ impl Editor {
         _: &SplitSelectionIntoLines,
         cx: &mut ViewContext<Self>,
     ) {
-        let app = cx.as_ref();
-        let buffer = self.buffer.read(app);
+        let selections = self.selections(cx);
+        let buffer = self.buffer.read(cx);
 
         let mut to_unfold = Vec::new();
         let mut new_selections = Vec::new();
-        for selection in self.selections(app) {
+        for selection in selections.iter() {
             let range = selection.point_range(buffer).sorted();
             if range.start.row != range.end.row {
                 new_selections.push(Selection {
@@ -1899,14 +1898,14 @@ impl Editor {
         _: &SelectLargerSyntaxNode,
         cx: &mut ViewContext<Self>,
     ) {
+        let old_selections = self.selections(cx);
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let buffer = self.buffer.read(cx);
 
         let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
         let mut selected_larger_node = false;
-        let old_selections = self.selections(cx).to_vec();
         let mut new_selection_ranges = Vec::new();
-        for selection in &old_selections {
+        for selection in old_selections.iter() {
             let old_range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
             let mut new_range = old_range.clone();
             while let Some(containing_range) = buffer.range_for_syntax_ancestor(new_range.clone()) {
@@ -1947,7 +1946,7 @@ impl Editor {
     ) {
         let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
         if let Some(selections) = stack.pop() {
-            self.update_selections(selections, true, cx);
+            self.update_selections(selections.to_vec(), true, cx);
         }
         self.select_larger_syntax_node_stack = stack;
     }
@@ -1957,8 +1956,8 @@ impl Editor {
         _: &MoveToEnclosingBracket,
         cx: &mut ViewContext<Self>,
     ) {
+        let mut selections = self.selections(cx).to_vec();
         let buffer = self.buffer.read(cx.as_ref());
-        let mut selections = self.selections(cx.as_ref()).to_vec();
         for selection in &mut selections {
             let selection_range = selection.offset_range(buffer);
             if let Some((open_range, close_range)) =
@@ -2072,12 +2071,14 @@ impl Editor {
         }
     }
 
-    fn selections<'a>(&self, cx: &'a AppContext) -> &'a [Selection] {
+    fn selections(&mut self, cx: &mut ViewContext<Self>) -> Arc<[Selection]> {
+        self.end_selection(cx);
         let buffer = self.buffer.read(cx);
-        &buffer
+        buffer
             .selection_set(self.selection_set_id)
             .unwrap()
             .selections
+            .clone()
     }
 
     fn update_selections(
@@ -2151,8 +2152,9 @@ impl Editor {
     pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
         let mut fold_ranges = Vec::new();
 
+        let selections = self.selections(cx);
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        for selection in self.selections(cx) {
+        for selection in selections.iter() {
             let range = selection.display_range(&display_map).sorted();
             let buffer_start_row = range.start.to_buffer_point(&display_map, Bias::Left).row;
 
@@ -2173,10 +2175,10 @@ impl Editor {
     }
 
     pub fn unfold(&mut self, _: &Unfold, cx: &mut ViewContext<Self>) {
+        let selections = self.selections(cx);
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let buffer = self.buffer.read(cx);
-        let ranges = self
-            .selections(cx)
+        let ranges = selections
             .iter()
             .map(|s| {
                 let range = s.display_range(&display_map).sorted();
@@ -2234,9 +2236,9 @@ impl Editor {
     }
 
     pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
+        let selections = self.selections(cx);
         let buffer = self.buffer.read(cx);
-        let ranges = self
-            .selections(cx.as_ref())
+        let ranges = selections
             .iter()
             .map(|s| s.point_range(buffer).sorted())
             .collect();