More messy progress towards selections in editors

Nathan Sobo created

Change summary

crates/editor/src/editor.rs                 | 247 ++++++++++++----------
crates/editor/src/items.rs                  |   6 
crates/editor/src/multi_buffer.rs           |  20 +
crates/editor/src/multi_buffer/selection.rs |  85 -------
crates/go_to_line/src/go_to_line.rs         |  13 
crates/language/src/buffer.rs               |  81 +++++++
crates/language/src/proto.rs                | 129 +++--------
crates/rpc/proto/zed.proto                  |  11 
crates/sum_tree/src/tree_map.rs             |  17 +
crates/text/src/selection.rs                |  95 --------
crates/text/src/text.rs                     |  81 -------
11 files changed, 302 insertions(+), 483 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -23,7 +23,7 @@ use gpui::{
 use items::BufferItemHandle;
 use language::{
     BracketPair, Buffer, Diagnostic, DiagnosticSeverity, Language, Point, Selection, SelectionGoal,
-    SelectionSetId, TransactionId,
+    TransactionId,
 };
 pub use multi_buffer::MultiBuffer;
 use multi_buffer::{
@@ -638,11 +638,11 @@ impl Editor {
         let first_cursor_top;
         let last_cursor_bottom;
         if autoscroll == Autoscroll::Newest {
-            let newest_selection = self.newest_selection::<Point>(&display_map.buffer_snapshot, cx);
+            let newest_selection = self.newest_selection::<Point>(&display_map.buffer_snapshot);
             first_cursor_top = newest_selection.head().to_display_point(&display_map).row() as f32;
             last_cursor_bottom = first_cursor_top + 1.;
         } else {
-            let selections = self.selections::<Point>(cx);
+            let selections = self.local_selections::<Point>(cx);
             first_cursor_top = selections
                 .first()
                 .unwrap()
@@ -702,7 +702,7 @@ impl Editor {
         cx: &mut ViewContext<Self>,
     ) -> bool {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let selections = self.selections::<Point>(cx);
+        let selections = self.local_selections::<Point>(cx);
         let mut target_left = std::f32::INFINITY;
         let mut target_right = 0.0_f32;
         for selection in selections {
@@ -772,7 +772,7 @@ impl Editor {
     ) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let tail = self
-            .newest_selection::<usize>(&display_map.buffer_snapshot, cx)
+            .newest_selection::<usize>(&display_map.buffer_snapshot)
             .tail();
         self.begin_selection(position, false, click_count, cx);
 
@@ -855,8 +855,8 @@ impl Editor {
             self.update_selections::<usize>(Vec::new(), None, cx);
         } else if click_count > 1 {
             // Remove the newest selection since it was only added as part of this multi-click.
-            let newest_selection = self.newest_selection::<usize>(buffer, cx);
-            let mut selections = self.selections(cx);
+            let newest_selection = self.newest_selection::<usize>(buffer);
+            let mut selections = self.local_selections(cx);
             selections.retain(|selection| selection.id != newest_selection.id);
             self.update_selections::<usize>(selections, None, cx)
         }
@@ -879,7 +879,7 @@ impl Editor {
 
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let tail = self
-            .newest_selection::<Point>(&display_map.buffer_snapshot, cx)
+            .newest_selection::<Point>(&display_map.buffer_snapshot)
             .tail();
         self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
 
@@ -986,7 +986,7 @@ impl Editor {
     fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
         self.columnar_selection_tail.take();
         if self.pending_selection.is_some() {
-            let selections = self.selections::<usize>(cx);
+            let selections = self.local_selections::<usize>(cx);
             self.update_selections(selections, None, cx);
         }
     }
@@ -1047,13 +1047,13 @@ impl Editor {
                 reversed: selection.reversed,
                 goal: selection.goal,
             };
-            if self.selections::<Point>(cx).is_empty() {
+            if self.local_selections::<Point>(cx).is_empty() {
                 self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
             }
         } else {
             let buffer = self.buffer.read(cx).snapshot(cx);
-            let mut oldest_selection = self.oldest_selection::<usize>(&buffer, cx);
-            if self.selection_count(cx) == 1 {
+            let mut oldest_selection = self.oldest_selection::<usize>(&buffer);
+            if self.selection_count() == 1 {
                 oldest_selection.start = oldest_selection.head().clone();
                 oldest_selection.end = oldest_selection.head().clone();
             }
@@ -1142,7 +1142,7 @@ impl Editor {
         self.start_transaction(cx);
         let mut old_selections = SmallVec::<[_; 32]>::new();
         {
-            let selections = self.selections::<Point>(cx);
+            let selections = self.local_selections::<Point>(cx);
             let buffer = self.buffer.read(cx).snapshot(cx);
             for selection in selections.iter() {
                 let start_point = selection.start;
@@ -1264,7 +1264,7 @@ impl Editor {
 
     fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
-        let old_selections = self.selections::<usize>(cx);
+        let old_selections = self.local_selections::<usize>(cx);
         let mut new_selections = Vec::new();
         self.buffer.update(cx, |buffer, cx| {
             let edit_ranges = old_selections.iter().map(|s| s.start..s.end);
@@ -1295,7 +1295,7 @@ impl Editor {
     }
 
     fn autoclose_pairs(&mut self, cx: &mut ViewContext<Self>) {
-        let selections = self.selections::<usize>(cx);
+        let selections = self.local_selections::<usize>(cx);
         let new_autoclose_pair = self.buffer.update(cx, |buffer, cx| {
             let snapshot = buffer.snapshot(cx);
             let autoclose_pair = snapshot.language().and_then(|language| {
@@ -1356,7 +1356,7 @@ impl Editor {
     }
 
     fn skip_autoclose_end(&mut self, text: &str, cx: &mut ViewContext<Self>) -> bool {
-        let old_selections = self.selections::<usize>(cx);
+        let old_selections = self.local_selections::<usize>(cx);
         let autoclose_pair = if let Some(autoclose_pair) = self.autoclose_stack.last() {
             autoclose_pair
         } else {
@@ -1407,7 +1407,7 @@ impl Editor {
 
     pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
-        let mut selections = self.selections::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         for selection in &mut selections {
             if selection.is_empty() {
@@ -1427,7 +1427,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::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         for selection in &mut selections {
             if selection.is_empty() {
                 let head = selection.head().to_display_point(&display_map);
@@ -1446,7 +1446,7 @@ impl Editor {
     pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
         let tab_size = self.build_settings.borrow()(cx).tab_size;
-        let mut selections = self.selections::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         let mut last_indent = None;
         self.buffer.update(cx, |buffer, cx| {
             for selection in &mut selections {
@@ -1518,7 +1518,7 @@ impl Editor {
     pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
         let tab_size = self.build_settings.borrow()(cx).tab_size;
-        let selections = self.selections::<Point>(cx);
+        let selections = self.local_selections::<Point>(cx);
         let mut deletion_ranges = Vec::new();
         let mut last_outdent = None;
         {
@@ -1558,14 +1558,18 @@ impl Editor {
             buffer.edit(deletion_ranges, "", cx);
         });
 
-        self.update_selections(self.selections::<usize>(cx), Some(Autoscroll::Fit), cx);
+        self.update_selections(
+            self.local_selections::<usize>(cx),
+            Some(Autoscroll::Fit),
+            cx,
+        );
         self.end_transaction(cx);
     }
 
     pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
 
-        let selections = self.selections::<Point>(cx);
+        let selections = self.local_selections::<Point>(cx);
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let buffer = self.buffer.read(cx).snapshot(cx);
 
@@ -1634,7 +1638,7 @@ impl Editor {
     pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
 
-        let mut selections = self.selections::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let buffer = &display_map.buffer_snapshot;
 
@@ -1692,7 +1696,7 @@ impl Editor {
     pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
 
-        let selections = self.selections::<Point>(cx);
+        let selections = self.local_selections::<Point>(cx);
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let buffer = self.buffer.read(cx).snapshot(cx);
 
@@ -1782,7 +1786,7 @@ impl Editor {
     pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
 
-        let selections = self.selections::<Point>(cx);
+        let selections = self.local_selections::<Point>(cx);
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let buffer = self.buffer.read(cx).snapshot(cx);
 
@@ -1869,7 +1873,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::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         let mut clipboard_selections = Vec::with_capacity(selections.len());
         {
             let buffer = self.buffer.read(cx).read(cx);
@@ -1900,7 +1904,7 @@ impl Editor {
     }
 
     pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
-        let selections = self.selections::<Point>(cx);
+        let selections = self.local_selections::<Point>(cx);
         let mut text = String::new();
         let mut clipboard_selections = Vec::with_capacity(selections.len());
         {
@@ -1934,7 +1938,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 mut selections = self.selections::<usize>(cx);
+                let mut selections = self.local_selections::<usize>(cx);
                 let all_selections_were_entire_line =
                     clipboard_selections.iter().all(|s| s.is_entire_line);
                 if clipboard_selections.len() != selections.len() {
@@ -1997,7 +2001,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 mut selections = self.selections::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         for selection in &mut selections {
             let start = selection.start.to_display_point(&display_map);
             let end = selection.end.to_display_point(&display_map);
@@ -2019,7 +2023,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::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         for selection in &mut selections {
             let head = selection.head().to_display_point(&display_map);
             let cursor = movement::left(&display_map, head)
@@ -2033,7 +2037,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::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         for selection in &mut selections {
             let start = selection.start.to_display_point(&display_map);
             let end = selection.end.to_display_point(&display_map);
@@ -2055,7 +2059,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::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         for selection in &mut selections {
             let head = selection.head().to_display_point(&display_map);
             let cursor = movement::right(&display_map, head)
@@ -2074,7 +2078,7 @@ impl Editor {
         }
 
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         for selection in &mut selections {
             let start = selection.start.to_display_point(&display_map);
             let end = selection.end.to_display_point(&display_map);
@@ -2094,7 +2098,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::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         for selection in &mut selections {
             let head = selection.head().to_display_point(&display_map);
             let (head, goal) = movement::up(&display_map, head, selection.goal).unwrap();
@@ -2112,7 +2116,7 @@ impl Editor {
         }
 
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         for selection in &mut selections {
             let start = selection.start.to_display_point(&display_map);
             let end = selection.end.to_display_point(&display_map);
@@ -2132,7 +2136,7 @@ impl Editor {
 
     pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         for selection in &mut selections {
             let head = selection.head().to_display_point(&display_map);
             let (head, goal) = movement::down(&display_map, head, selection.goal).unwrap();
@@ -2149,7 +2153,7 @@ impl Editor {
         cx: &mut ViewContext<Self>,
     ) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         for selection in &mut selections {
             let head = selection.head().to_display_point(&display_map);
             let cursor = movement::prev_word_boundary(&display_map, head).to_point(&display_map);
@@ -2167,7 +2171,7 @@ impl Editor {
         cx: &mut ViewContext<Self>,
     ) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         for selection in &mut selections {
             let head = selection.head().to_display_point(&display_map);
             let cursor = movement::prev_word_boundary(&display_map, head).to_point(&display_map);
@@ -2184,7 +2188,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::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         for selection in &mut selections {
             if selection.is_empty() {
                 let head = selection.head().to_display_point(&display_map);
@@ -2205,7 +2209,7 @@ impl Editor {
         cx: &mut ViewContext<Self>,
     ) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         for selection in &mut selections {
             let head = selection.head().to_display_point(&display_map);
             let cursor = movement::next_word_boundary(&display_map, head).to_point(&display_map);
@@ -2223,7 +2227,7 @@ impl Editor {
         cx: &mut ViewContext<Self>,
     ) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         for selection in &mut selections {
             let head = selection.head().to_display_point(&display_map);
             let cursor = movement::next_word_boundary(&display_map, head).to_point(&display_map);
@@ -2240,7 +2244,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::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         for selection in &mut selections {
             if selection.is_empty() {
                 let head = selection.head().to_display_point(&display_map);
@@ -2261,7 +2265,7 @@ impl Editor {
         cx: &mut ViewContext<Self>,
     ) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         for selection in &mut selections {
             let head = selection.head().to_display_point(&display_map);
             let new_head = movement::line_beginning(&display_map, head, true);
@@ -2280,7 +2284,7 @@ impl Editor {
         cx: &mut ViewContext<Self>,
     ) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         for selection in &mut selections {
             let head = selection.head().to_display_point(&display_map);
             let new_head = movement::line_beginning(&display_map, head, *toggle_indent);
@@ -2303,7 +2307,7 @@ impl Editor {
 
     pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         {
             for selection in &mut selections {
                 let head = selection.head().to_display_point(&display_map);
@@ -2320,7 +2324,7 @@ impl Editor {
 
     pub fn select_to_end_of_line(&mut self, _: &SelectToEndOfLine, cx: &mut ViewContext<Self>) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         for selection in &mut selections {
             let head = selection.head().to_display_point(&display_map);
             let new_head = movement::line_end(&display_map, head);
@@ -2356,7 +2360,7 @@ impl Editor {
     }
 
     pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
-        let mut selection = self.selections::<Point>(cx).last().unwrap().clone();
+        let mut selection = self.local_selections::<Point>(cx).last().unwrap().clone();
         selection.set_head(Point::zero());
         self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
     }
@@ -2374,7 +2378,7 @@ impl Editor {
     }
 
     pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
-        let mut selection = self.selections::<usize>(cx).first().unwrap().clone();
+        let mut selection = self.local_selections::<usize>(cx).first().unwrap().clone();
         selection.set_head(self.buffer.read(cx).read(cx).len());
         self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
     }
@@ -2392,7 +2396,7 @@ 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 mut selections = self.selections::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         let max_point = display_map.buffer_snapshot.max_point();
         for selection in &mut selections {
             let rows = selection.spanned_rows(true, &display_map).buffer_rows;
@@ -2411,7 +2415,7 @@ impl Editor {
         let mut to_unfold = Vec::new();
         let mut new_selections = Vec::new();
         {
-            let selections = self.selections::<Point>(cx);
+            let selections = self.local_selections::<Point>(cx);
             let buffer = self.buffer.read(cx).read(cx);
             for selection in selections {
                 for row in selection.start.row..selection.end.row {
@@ -2448,7 +2452,7 @@ impl Editor {
 
     fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         let mut state = self.add_selections_state.take().unwrap_or_else(|| {
             let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
             let range = oldest_selection.display_range(&display_map).sorted();
@@ -2543,7 +2547,7 @@ impl Editor {
         let replace_newest = action.0;
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let buffer = &display_map.buffer_snapshot;
-        let mut selections = self.selections::<usize>(cx);
+        let mut selections = self.local_selections::<usize>(cx);
         if let Some(mut select_next_state) = self.select_next_state.take() {
             let query = &select_next_state.query;
             if !select_next_state.done {
@@ -2650,7 +2654,7 @@ impl Editor {
         let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 
         self.start_transaction(cx);
-        let mut selections = self.selections::<Point>(cx);
+        let mut selections = self.local_selections::<Point>(cx);
         let mut all_selection_lines_are_comments = true;
         let mut edit_ranges = Vec::new();
         let mut last_toggled_row = None;
@@ -2727,7 +2731,11 @@ impl Editor {
             }
         });
 
-        self.update_selections(self.selections::<usize>(cx), Some(Autoscroll::Fit), cx);
+        self.update_selections(
+            self.local_selections::<usize>(cx),
+            Some(Autoscroll::Fit),
+            cx,
+        );
         self.end_transaction(cx);
     }
 
@@ -2736,7 +2744,7 @@ impl Editor {
         _: &SelectLargerSyntaxNode,
         cx: &mut ViewContext<Self>,
     ) {
-        let old_selections = self.selections::<usize>(cx).into_boxed_slice();
+        let old_selections = self.local_selections::<usize>(cx).into_boxed_slice();
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let buffer = self.buffer.read(cx).snapshot(cx);
 
@@ -2794,7 +2802,7 @@ impl Editor {
         _: &MoveToEnclosingBracket,
         cx: &mut ViewContext<Self>,
     ) {
-        let mut selections = self.selections::<usize>(cx);
+        let mut selections = self.local_selections::<usize>(cx);
         let buffer = self.buffer.read(cx).snapshot(cx);
         for selection in &mut selections {
             if let Some((open_range, close_range)) =
@@ -2818,7 +2826,7 @@ impl Editor {
 
     pub fn show_next_diagnostic(&mut self, _: &ShowNextDiagnostic, cx: &mut ViewContext<Self>) {
         let buffer = self.buffer.read(cx).snapshot(cx);
-        let selection = self.newest_selection::<usize>(&buffer, cx);
+        let selection = self.newest_selection::<usize>(&buffer);
         let active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
             active_diagnostics
                 .primary_range
@@ -2998,54 +3006,65 @@ impl Editor {
         }
     }
 
-    pub fn intersecting_selections<'a>(
+    pub fn all_selections_in_range<'a, D>(
         &'a self,
-        set_id: SelectionSetId,
         range: Range<DisplayPoint>,
         cx: &'a mut MutableAppContext,
-    ) -> Vec<Selection<DisplayPoint>> {
-        todo!()
-        // let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        // let buffer = self.buffer.read(cx);
-
-        // let pending_selection = if set_id == self.selection_set_id {
-        //     self.pending_selection.as_ref().and_then(|pending| {
-        //         let selection_start = pending.selection.start.to_display_point(&display_map);
-        //         let selection_end = pending.selection.end.to_display_point(&display_map);
-        //         if selection_start <= range.end || selection_end <= range.end {
-        //             Some(Selection {
-        //                 id: pending.selection.id,
-        //                 start: selection_start,
-        //                 end: selection_end,
-        //                 reversed: pending.selection.reversed,
-        //                 goal: pending.selection.goal,
-        //             })
-        //         } else {
-        //             None
-        //         }
-        //     })
-        // } else {
-        //     None
-        // };
-
-        // let range = (range.start.to_offset(&display_map, Bias::Left), Bias::Left)
-        //     ..(range.end.to_offset(&display_map, Bias::Left), Bias::Right);
-        // buffer
-        //     .selection_set(set_id, cx)
-        //     .unwrap()
-        //     .intersecting_selections::<Point, _>(range, &buffer.read(cx))
-        //     .map(move |s| Selection {
-        //         id: s.id,
-        //         start: s.start.to_display_point(&display_map),
-        //         end: s.end.to_display_point(&display_map),
-        //         reversed: s.reversed,
-        //         goal: s.goal,
-        //     })
-        //     .chain(pending_selection)
-        //     .collect()
-    }
-
-    pub fn selections<'a, D>(&self, cx: &'a AppContext) -> Vec<Selection<D>>
+    ) -> HashMap<ReplicaId, Vec<Selection<D>>>
+    where
+        D: TextDimension + Ord + Sub<D, Output = D>,
+    {
+        let mut result = HashMap::new();
+
+        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+        let buffer = &display_map.buffer_snapshot;
+        let range = range.start.to_offset(&display_map, Bias::Left)
+            ..range.end.to_offset(&display_map, Bias::Left);
+
+        let anchor_range = buffer.anchor_before(range.start)..buffer.anchor_after(range.end);
+        let start_ix = match self
+            .selections
+            .binary_search_by(|probe| probe.end.cmp(&anchor_range.start, &buffer).unwrap())
+        {
+            Ok(ix) | Err(ix) => ix,
+        };
+        let end_ix = match self
+            .selections
+            .binary_search_by(|probe| probe.start.cmp(&anchor_range.end, &buffer).unwrap())
+        {
+            Ok(ix) | Err(ix) => ix,
+        };
+
+        let selections = &self.selections[start_ix..end_ix];
+        let mut summaries = buffer
+            .summaries_for_anchors::<D, _>(selections.iter().flat_map(|s| [&s.start, &s.end]))
+            .into_iter();
+
+        result.insert(
+            self.replica_id(cx),
+            selections
+                .iter()
+                .map(|s| Selection {
+                    id: s.id,
+                    start: summaries.next().unwrap(),
+                    end: summaries.next().unwrap(),
+                    reversed: s.reversed,
+                    goal: s.goal,
+                })
+                .collect(),
+        );
+
+        for (replica_id, selections) in display_map
+            .buffer_snapshot
+            .remote_selections_in_range(range)
+        {
+            result.insert(replica_id, selections.collect());
+        }
+
+        result
+    }
+
+    pub fn local_selections<'a, D>(&self, cx: &'a AppContext) -> Vec<Selection<D>>
     where
         D: 'a + TextDimension + Ord + Sub<D, Output = D>,
     {
@@ -3067,7 +3086,7 @@ impl Editor {
             })
             .peekable();
 
-        let mut pending_selection = self.pending_selection::<D>(&buffer, cx);
+        let mut pending_selection = self.pending_selection::<D>(&buffer);
 
         iter::from_fn(move || {
             if let Some(pending) = pending_selection.as_mut() {
@@ -3098,18 +3117,16 @@ impl Editor {
     fn pending_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
         &self,
         snapshot: &MultiBufferSnapshot,
-        cx: &AppContext,
     ) -> Option<Selection<D>> {
         self.pending_selection
             .as_ref()
-            .map(|pending| self.resolve_selection(&pending.selection, &snapshot, cx))
+            .map(|pending| self.resolve_selection(&pending.selection, &snapshot))
     }
 
     fn resolve_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
         &self,
         selection: &Selection<Anchor>,
         buffer: &MultiBufferSnapshot,
-        cx: &AppContext,
     ) -> Selection<D> {
         Selection {
             id: selection.id,
@@ -3120,7 +3137,7 @@ impl Editor {
         }
     }
 
-    fn selection_count<'a>(&self, cx: &'a AppContext) -> usize {
+    fn selection_count<'a>(&self) -> usize {
         let mut count = self.selections.len();
         if self.pending_selection.is_some() {
             count += 1;
@@ -3131,27 +3148,25 @@ impl Editor {
     pub fn oldest_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
         &self,
         snapshot: &MultiBufferSnapshot,
-        cx: &AppContext,
     ) -> Selection<D> {
         self.selections
             .iter()
             .min_by_key(|s| s.id)
-            .map(|selection| self.resolve_selection(selection, snapshot, cx))
-            .or_else(|| self.pending_selection(snapshot, cx))
+            .map(|selection| self.resolve_selection(selection, snapshot))
+            .or_else(|| self.pending_selection(snapshot))
             .unwrap()
     }
 
     pub fn newest_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
         &self,
         snapshot: &MultiBufferSnapshot,
-        cx: &AppContext,
     ) -> Selection<D> {
-        self.pending_selection(snapshot, cx)
+        self.pending_selection(snapshot)
             .or_else(|| {
                 self.selections
                     .iter()
                     .min_by_key(|s| s.id)
-                    .map(|selection| self.resolve_selection(selection, snapshot, cx))
+                    .map(|selection| self.resolve_selection(selection, snapshot))
             })
             .unwrap()
     }
@@ -3249,7 +3264,7 @@ impl Editor {
     pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
         let mut fold_ranges = Vec::new();
 
-        let selections = self.selections::<Point>(cx);
+        let selections = self.local_selections::<Point>(cx);
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         for selection in selections {
             let range = selection.display_range(&display_map).sorted();
@@ -3272,7 +3287,7 @@ impl Editor {
     }
 
     pub fn unfold(&mut self, _: &Unfold, cx: &mut ViewContext<Self>) {
-        let selections = self.selections::<Point>(cx);
+        let selections = self.local_selections::<Point>(cx);
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let buffer = &display_map.buffer_snapshot;
         let ranges = selections
@@ -3332,7 +3347,7 @@ impl Editor {
     }
 
     pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
-        let selections = self.selections::<Point>(cx);
+        let selections = self.local_selections::<Point>(cx);
         let ranges = selections.into_iter().map(|s| s.start..s.end);
         self.fold_ranges(ranges, cx);
     }

crates/editor/src/items.rs 🔗

@@ -249,7 +249,7 @@ impl CursorPosition {
 
         self.selected_count = 0;
         let mut last_selection: Option<Selection<usize>> = None;
-        for selection in editor.selections::<usize>(cx) {
+        for selection in editor.local_selections::<usize>(cx) {
             self.selected_count += selection.end - selection.start;
             if last_selection
                 .as_ref()
@@ -323,9 +323,7 @@ impl DiagnosticMessage {
     fn update(&mut self, editor: ViewHandle<Editor>, cx: &mut ViewContext<Self>) {
         let editor = editor.read(cx);
         let buffer = editor.buffer().read(cx);
-        let cursor_position = editor
-            .newest_selection::<usize>(&buffer.read(cx), cx)
-            .head();
+        let cursor_position = editor.newest_selection::<usize>(&buffer.read(cx)).head();
         let new_diagnostic = buffer
             .read(cx)
             .diagnostics_in_range::<_, usize>(cursor_position..cursor_position)

crates/editor/src/multi_buffer.rs 🔗

@@ -7,10 +7,9 @@ use clock::ReplicaId;
 use collections::HashMap;
 use gpui::{AppContext, Entity, ModelContext, ModelHandle, MutableAppContext, Task};
 use language::{
-    Buffer, BufferChunks, BufferSnapshot, Chunk, DiagnosticEntry, Event, File, Language,
+    Buffer, BufferChunks, BufferSnapshot, Chunk, DiagnosticEntry, Event, File, Language, Selection,
     ToOffset as _, ToPoint as _, TransactionId,
 };
-pub use selection::SelectionSet;
 use std::{
     cell::{Ref, RefCell},
     cmp, io,
@@ -24,7 +23,7 @@ use text::{
     locator::Locator,
     rope::TextDimension,
     subscription::{Subscription, Topic},
-    AnchorRangeExt as _, Edit, Point, PointUtf16, SelectionSetId, TextSummary,
+    AnchorRangeExt as _, Edit, Point, PointUtf16, TextSummary,
 };
 use theme::SyntaxTheme;
 
@@ -36,7 +35,6 @@ pub struct MultiBuffer {
     snapshot: RefCell<MultiBufferSnapshot>,
     buffers: HashMap<usize, BufferState>,
     subscriptions: Topic,
-    selection_sets: HashMap<SelectionSetId, SelectionSet>,
     singleton: bool,
     replica_id: ReplicaId,
 }
@@ -104,7 +102,6 @@ impl MultiBuffer {
             snapshot: Default::default(),
             buffers: Default::default(),
             subscriptions: Default::default(),
-            selection_sets: Default::default(),
             singleton: false,
             replica_id,
         }
@@ -937,6 +934,19 @@ impl MultiBufferSnapshot {
         }
         None
     }
+
+    pub fn remote_selections_in_range<'a, I, O>(
+        &'a self,
+        range: Range<I>,
+    ) -> impl 'a + Iterator<Item = (ReplicaId, impl 'a + Iterator<Item = Selection<O>>)>
+    where
+        I: ToOffset,
+        O: TextDimension,
+    {
+        self.as_singleton()
+            .unwrap()
+            .remote_selections_in_range(range.start.to_offset(self)..range.end.to_offset(self))
+    }
 }
 
 impl Excerpt {

crates/editor/src/multi_buffer/selection.rs 🔗

@@ -1,85 +1,6 @@
-use super::{Anchor, MultiBufferSnapshot, ToOffset};
-use std::{
-    ops::{Range, Sub},
-    sync::Arc,
-};
-use sum_tree::Bias;
-use text::{rope::TextDimension, Selection, SelectionSetId};
-
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct SelectionSet {
-    pub id: SelectionSetId,
-    pub active: bool,
-    pub selections: Arc<[Selection<Anchor>]>,
-}
-
-impl SelectionSet {
-    pub fn len(&self) -> usize {
-        self.selections.len()
-    }
-
-    pub fn selections<'a, D>(
-        &'a self,
-        snapshot: &'a MultiBufferSnapshot,
-    ) -> impl 'a + Iterator<Item = Selection<D>>
-    where
-        D: TextDimension + Ord + Sub<D, Output = D>,
-    {
-        resolve_selections(&self.selections, snapshot)
-    }
-
-    pub fn intersecting_selections<'a, D, I>(
-        &'a self,
-        range: Range<(I, Bias)>,
-        snapshot: &'a MultiBufferSnapshot,
-    ) -> impl 'a + Iterator<Item = Selection<D>>
-    where
-        D: TextDimension + Ord + Sub<D, Output = D>,
-        I: 'a + ToOffset,
-    {
-        let start = snapshot.anchor_at(range.start.0, range.start.1);
-        let end = snapshot.anchor_at(range.end.0, range.end.1);
-        let start_ix = match self
-            .selections
-            .binary_search_by(|probe| probe.end.cmp(&start, snapshot).unwrap())
-        {
-            Ok(ix) | Err(ix) => ix,
-        };
-        let end_ix = match self
-            .selections
-            .binary_search_by(|probe| probe.start.cmp(&end, snapshot).unwrap())
-        {
-            Ok(ix) | Err(ix) => ix,
-        };
-        resolve_selections(&self.selections[start_ix..end_ix], snapshot)
-    }
-
-    pub fn oldest_selection<'a, D>(
-        &'a self,
-        snapshot: &'a MultiBufferSnapshot,
-    ) -> Option<Selection<D>>
-    where
-        D: TextDimension + Ord + Sub<D, Output = D>,
-    {
-        self.selections
-            .iter()
-            .min_by_key(|selection| selection.id)
-            .map(|selection| resolve_selection(selection, snapshot))
-    }
-
-    pub fn newest_selection<'a, D>(
-        &'a self,
-        snapshot: &'a MultiBufferSnapshot,
-    ) -> Option<Selection<D>>
-    where
-        D: TextDimension + Ord + Sub<D, Output = D>,
-    {
-        self.selections
-            .iter()
-            .max_by_key(|selection| selection.id)
-            .map(|selection| resolve_selection(selection, snapshot))
-    }
-}
+use super::{Anchor, MultiBufferSnapshot};
+use std::ops::Sub;
+use text::{rope::TextDimension, Selection};
 
 fn resolve_selection<'a, D>(
     selection: &'a Selection<Anchor>,

crates/go_to_line/src/go_to_line.rs 🔗

@@ -67,13 +67,14 @@ impl GoToLine {
         let (restore_state, cursor_point, max_point) = active_editor.update(cx, |editor, cx| {
             let restore_state = Some(RestoreState {
                 scroll_position: editor.scroll_position(cx),
-                selections: editor.selections::<usize>(cx),
+                selections: editor.local_selections::<usize>(cx),
             });
 
+            let buffer = editor.buffer().read(cx).read(cx);
             (
                 restore_state,
-                editor.newest_selection(cx).head(),
-                editor.buffer().read(cx).read(cx).max_point(),
+                editor.newest_selection(&buffer).head(),
+                buffer.max_point(),
             )
         });
 
@@ -143,7 +144,7 @@ impl GoToLine {
                         let display_point = point.to_display_point(&snapshot);
                         active_editor.select_ranges([point..point], Some(Autoscroll::Center), cx);
                         active_editor.set_highlighted_row(Some(display_point.row()));
-                        Some(active_editor.newest_selection(cx))
+                        Some(active_editor.newest_selection(&snapshot.buffer_snapshot))
                     });
                     cx.notify();
                 }
@@ -162,7 +163,9 @@ impl Entity for GoToLine {
         self.active_editor.update(cx, |editor, cx| {
             editor.set_highlighted_row(None);
             if let Some((line_selection, restore_state)) = line_selection.zip(restore_state) {
-                if line_selection.id == editor.newest_selection::<usize>(cx).id {
+                let newest_selection =
+                    editor.newest_selection::<usize>(&editor.buffer().read(cx).read(cx));
+                if line_selection.id == newest_selection.id {
                     editor.set_scroll_position(restore_state.scroll_position, cx);
                     editor.update_selections(restore_state.selections, None, cx);
                 }

crates/language/src/buffer.rs 🔗

@@ -30,7 +30,8 @@ use std::{
     time::{Duration, Instant, SystemTime, UNIX_EPOCH},
     vec,
 };
-use text::operation_queue::OperationQueue;
+use sum_tree::TreeMap;
+use text::{operation_queue::OperationQueue, rope::TextDimension};
 pub use text::{Buffer as TextBuffer, Operation as _, *};
 use theme::SyntaxTheme;
 use tree_sitter::{InputEdit, Parser, QueryCursor, Tree};
@@ -64,6 +65,7 @@ pub struct Buffer {
     syntax_tree: Mutex<Option<SyntaxTree>>,
     parsing_in_background: bool,
     parse_count: usize,
+    remote_selections: TreeMap<ReplicaId, Arc<[Selection<Anchor>]>>,
     diagnostics: DiagnosticSet,
     diagnostics_update_count: usize,
     language_server: Option<LanguageServerState>,
@@ -76,6 +78,7 @@ pub struct BufferSnapshot {
     text: text::BufferSnapshot,
     tree: Option<Tree>,
     diagnostics: DiagnosticSet,
+    remote_selections: TreeMap<ReplicaId, Arc<[Selection<Anchor>]>>,
     diagnostics_update_count: usize,
     is_parsing: bool,
     language: Option<Arc<Language>>,
@@ -112,6 +115,15 @@ pub enum Operation {
         diagnostics: Arc<[DiagnosticEntry<Anchor>]>,
         lamport_timestamp: clock::Lamport,
     },
+    UpdateSelections {
+        replica_id: ReplicaId,
+        selections: Arc<[Selection<Anchor>]>,
+        lamport_timestamp: clock::Lamport,
+    },
+    RemoveSelections {
+        replica_id: ReplicaId,
+        lamport_timestamp: clock::Lamport,
+    },
 }
 
 #[derive(Clone, Debug, Eq, PartialEq)]
@@ -329,6 +341,7 @@ impl Buffer {
             autoindent_requests: Default::default(),
             pending_autoindent: Default::default(),
             language: None,
+            remote_selections: Default::default(),
             diagnostics: Default::default(),
             diagnostics_update_count: 0,
             language_server: None,
@@ -342,6 +355,7 @@ impl Buffer {
         BufferSnapshot {
             text: self.text.snapshot(),
             tree: self.syntax_tree(),
+            remote_selections: self.remote_selections.clone(),
             diagnostics: self.diagnostics.clone(),
             diagnostics_update_count: self.diagnostics_update_count,
             is_parsing: self.parsing_in_background,
@@ -1286,6 +1300,10 @@ impl Buffer {
                         && self.text.can_resolve(&diagnostic.range.end)
                 })
             }
+            Operation::UpdateSelections { selections, .. } => selections
+                .iter()
+                .all(|s| self.can_resolve(&s.start) && self.can_resolve(&s.end)),
+            Operation::RemoveSelections { .. } => true,
         }
     }
 
@@ -1297,6 +1315,21 @@ impl Buffer {
             Operation::UpdateDiagnostics { diagnostics, .. } => {
                 self.apply_diagnostic_update(diagnostics, cx);
             }
+            Operation::UpdateSelections {
+                replica_id,
+                selections,
+                lamport_timestamp,
+            } => {
+                self.remote_selections.insert(replica_id, selections);
+                self.text.observe_lamport_timestamp(lamport_timestamp);
+            }
+            Operation::RemoveSelections {
+                replica_id: set_id,
+                lamport_timestamp,
+            } => {
+                self.remote_selections.remove(&set_id);
+                self.text.observe_lamport_timestamp(lamport_timestamp);
+            }
         }
     }
 
@@ -1323,7 +1356,7 @@ impl Buffer {
     }
 
     pub fn remove_peer(&mut self, replica_id: ReplicaId, cx: &mut ModelContext<Self>) {
-        self.text.remove_peer(replica_id);
+        self.remote_selections.remove(&replica_id);
         cx.notify();
     }
 
@@ -1615,6 +1648,43 @@ impl BufferSnapshot {
             .min_by_key(|(open_range, close_range)| close_range.end - open_range.start)
     }
 
+    pub fn remote_selections_in_range<'a, I, O>(
+        &'a self,
+        range: Range<I>,
+    ) -> impl 'a + Iterator<Item = (ReplicaId, impl 'a + Iterator<Item = Selection<O>>)>
+    where
+        I: ToOffset,
+        O: TextDimension,
+    {
+        let range = self.anchor_before(range.start)..self.anchor_after(range.end);
+        self.remote_selections
+            .iter()
+            .map(move |(replica_id, selections)| {
+                let start_ix = match selections
+                    .binary_search_by(|probe| probe.end.cmp(&range.start, self).unwrap())
+                {
+                    Ok(ix) | Err(ix) => ix,
+                };
+                let end_ix = match selections
+                    .binary_search_by(|probe| probe.start.cmp(&range.end, self).unwrap())
+                {
+                    Ok(ix) | Err(ix) => ix,
+                };
+
+                let selections = &selections[start_ix..end_ix];
+                let mut summaries =
+                    self.summaries_for_anchors(selections.iter().flat_map(|s| [&s.start, &s.end]));
+                let resolved = selections.iter().map(move |s| Selection {
+                    id: s.id,
+                    start: summaries.next().unwrap(),
+                    end: summaries.next().unwrap(),
+                    reversed: s.reversed,
+                    goal: s.goal,
+                });
+                (*replica_id, resolved)
+            })
+    }
+
     pub fn diagnostics_in_range<'a, T, O>(
         &'a self,
         search_range: Range<T>,
@@ -1650,6 +1720,7 @@ impl Clone for BufferSnapshot {
         Self {
             text: self.text.clone(),
             tree: self.tree.clone(),
+            remote_selections: self.remote_selections.clone(),
             diagnostics: self.diagnostics.clone(),
             diagnostics_update_count: self.diagnostics_update_count,
             is_parsing: self.is_parsing,
@@ -1889,6 +1960,12 @@ impl operation_queue::Operation for Operation {
             }
             Operation::UpdateDiagnostics {
                 lamport_timestamp, ..
+            }
+            | Operation::UpdateSelections {
+                lamport_timestamp, ..
+            }
+            | Operation::RemoveSelections {
+                lamport_timestamp, ..
             } => *lamport_timestamp,
         }
     }

crates/language/src/proto.rs 🔗

@@ -41,13 +41,12 @@ pub fn serialize_operation(operation: &Operation) -> proto::Operation {
                     .collect(),
                 version: From::from(&undo.version),
             }),
-            Operation::Buffer(text::Operation::UpdateSelections {
-                set_id,
+            Operation::UpdateSelections {
+                replica_id,
                 selections,
                 lamport_timestamp,
-            }) => proto::operation::Variant::UpdateSelections(proto::operation::UpdateSelections {
-                replica_id: set_id.replica_id as u32,
-                local_timestamp: set_id.value,
+            } => proto::operation::Variant::UpdateSelections(proto::operation::UpdateSelections {
+                replica_id: *replica_id as u32,
                 lamport_timestamp: lamport_timestamp.value,
                 selections: selections
                     .iter()
@@ -59,24 +58,13 @@ pub fn serialize_operation(operation: &Operation) -> proto::Operation {
                     })
                     .collect(),
             }),
-            Operation::Buffer(text::Operation::RemoveSelections {
-                set_id,
+            Operation::RemoveSelections {
+                replica_id,
                 lamport_timestamp,
-            }) => proto::operation::Variant::RemoveSelections(proto::operation::RemoveSelections {
-                replica_id: set_id.replica_id as u32,
-                local_timestamp: set_id.value,
+            } => proto::operation::Variant::RemoveSelections(proto::operation::RemoveSelections {
+                replica_id: *replica_id as u32,
                 lamport_timestamp: lamport_timestamp.value,
             }),
-            Operation::Buffer(text::Operation::SetActiveSelections {
-                set_id,
-                lamport_timestamp,
-            }) => proto::operation::Variant::SetActiveSelections(
-                proto::operation::SetActiveSelections {
-                    replica_id: lamport_timestamp.replica_id as u32,
-                    local_timestamp: set_id.map(|set_id| set_id.value),
-                    lamport_timestamp: lamport_timestamp.value,
-                },
-            ),
             Operation::UpdateDiagnostics {
                 diagnostics,
                 lamport_timestamp,
@@ -108,22 +96,16 @@ pub fn serialize_edit_operation(operation: &EditOperation) -> proto::operation::
     }
 }
 
-pub fn serialize_selection_set(set: &SelectionSet) -> proto::SelectionSet {
-    proto::SelectionSet {
-        replica_id: set.id.replica_id as u32,
-        lamport_timestamp: set.id.value as u32,
-        is_active: set.active,
-        selections: set
-            .selections
-            .iter()
-            .map(|selection| proto::Selection {
-                id: selection.id as u64,
-                start: Some(serialize_anchor(&selection.start)),
-                end: Some(serialize_anchor(&selection.end)),
-                reversed: selection.reversed,
-            })
-            .collect(),
-    }
+pub fn serialize_selections(selections: &Arc<[Selection<Anchor>]>) -> Vec<proto::Selection> {
+    selections
+        .iter()
+        .map(|selection| proto::Selection {
+            id: selection.id as u64,
+            start: Some(serialize_anchor(&selection.start)),
+            end: Some(serialize_anchor(&selection.end)),
+            reversed: selection.reversed,
+        })
+        .collect()
 }
 
 pub fn serialize_diagnostics<'a>(
@@ -215,42 +197,22 @@ pub fn deserialize_operation(message: proto::Operation) -> Result<Operation> {
                     })
                     .collect::<Vec<_>>();
 
-                Operation::Buffer(text::Operation::UpdateSelections {
-                    set_id: clock::Lamport {
-                        replica_id: message.replica_id as ReplicaId,
-                        value: message.local_timestamp,
-                    },
+                Operation::UpdateSelections {
+                    replica_id: message.replica_id as ReplicaId,
                     lamport_timestamp: clock::Lamport {
                         replica_id: message.replica_id as ReplicaId,
                         value: message.lamport_timestamp,
                     },
                     selections: Arc::from(selections),
-                })
-            }
-            proto::operation::Variant::RemoveSelections(message) => {
-                Operation::Buffer(text::Operation::RemoveSelections {
-                    set_id: clock::Lamport {
-                        replica_id: message.replica_id as ReplicaId,
-                        value: message.local_timestamp,
-                    },
-                    lamport_timestamp: clock::Lamport {
-                        replica_id: message.replica_id as ReplicaId,
-                        value: message.lamport_timestamp,
-                    },
-                })
-            }
-            proto::operation::Variant::SetActiveSelections(message) => {
-                Operation::Buffer(text::Operation::SetActiveSelections {
-                    set_id: message.local_timestamp.map(|value| clock::Lamport {
-                        replica_id: message.replica_id as ReplicaId,
-                        value,
-                    }),
-                    lamport_timestamp: clock::Lamport {
-                        replica_id: message.replica_id as ReplicaId,
-                        value: message.lamport_timestamp,
-                    },
-                })
+                }
             }
+            proto::operation::Variant::RemoveSelections(message) => Operation::RemoveSelections {
+                replica_id: message.replica_id as ReplicaId,
+                lamport_timestamp: clock::Lamport {
+                    replica_id: message.replica_id as ReplicaId,
+                    value: message.lamport_timestamp,
+                },
+            },
             proto::operation::Variant::UpdateDiagnostics(message) => Operation::UpdateDiagnostics {
                 diagnostics: Arc::from(deserialize_diagnostics(message.diagnostics)),
                 lamport_timestamp: clock::Lamport {
@@ -280,28 +242,21 @@ pub fn deserialize_edit_operation(edit: proto::operation::Edit) -> EditOperation
     }
 }
 
-pub fn deserialize_selection_set(set: proto::SelectionSet) -> SelectionSet {
-    SelectionSet {
-        id: clock::Lamport {
-            replica_id: set.replica_id as u16,
-            value: set.lamport_timestamp,
-        },
-        active: set.is_active,
-        selections: Arc::from(
-            set.selections
-                .into_iter()
-                .filter_map(|selection| {
-                    Some(Selection {
-                        id: selection.id as usize,
-                        start: deserialize_anchor(selection.start?)?,
-                        end: deserialize_anchor(selection.end?)?,
-                        reversed: selection.reversed,
-                        goal: SelectionGoal::None,
-                    })
+pub fn deserialize_selections(selections: Vec<proto::Selection>) -> Arc<[Selection<Anchor>]> {
+    Arc::from(
+        selections
+            .into_iter()
+            .filter_map(|selection| {
+                Some(Selection {
+                    id: selection.id as usize,
+                    start: deserialize_anchor(selection.start?)?,
+                    end: deserialize_anchor(selection.end?)?,
+                    reversed: selection.reversed,
+                    goal: SelectionGoal::None,
                 })
-                .collect::<Vec<_>>(),
-        ),
-    }
+            })
+            .collect::<Vec<_>>(),
+    )
 }
 
 pub fn deserialize_diagnostics(

crates/rpc/proto/zed.proto 🔗

@@ -286,8 +286,7 @@ message Operation {
         Undo undo = 2;
         UpdateSelections update_selections = 3;
         RemoveSelections remove_selections = 4;
-        SetActiveSelections set_active_selections = 5;
-        UpdateDiagnostics update_diagnostics = 6;
+        UpdateDiagnostics update_diagnostics = 5;
     }
 
     message Edit {
@@ -316,20 +315,12 @@ message Operation {
 
     message UpdateSelections {
         uint32 replica_id = 1;
-        uint32 local_timestamp = 2;
         uint32 lamport_timestamp = 3;
         repeated Selection selections = 4;
     }
 
     message RemoveSelections {
         uint32 replica_id = 1;
-        uint32 local_timestamp = 2;
-        uint32 lamport_timestamp = 3;
-    }
-
-    message SetActiveSelections {
-        uint32 replica_id = 1;
-        optional uint32 local_timestamp = 2;
         uint32 lamport_timestamp = 3;
     }
 }

crates/sum_tree/src/tree_map.rs 🔗

@@ -2,6 +2,7 @@ use std::{cmp::Ordering, fmt::Debug};
 
 use crate::{Bias, Dimension, Item, KeyedItem, SeekTarget, SumTree, Summary};
 
+#[derive(Clone)]
 pub struct TreeMap<K, V>(SumTree<MapEntry<K, V>>)
 where
     K: Clone + Debug + Default,
@@ -19,7 +20,7 @@ pub struct MapKey<K>(K);
 #[derive(Clone, Debug, Default)]
 pub struct MapKeyRef<'a, K>(Option<&'a K>);
 
-impl<K: Clone + Debug + Default + Ord, V: Clone + Debug + Default> TreeMap<K, V> {
+impl<K: Clone + Debug + Default + Ord, V: Clone + Debug> TreeMap<K, V> {
     pub fn get<'a>(&self, key: &'a K) -> Option<&V> {
         let mut cursor = self.0.cursor::<MapKeyRef<'_, K>>();
         let key = MapKeyRef(Some(key));
@@ -49,6 +50,20 @@ impl<K: Clone + Debug + Default + Ord, V: Clone + Debug + Default> TreeMap<K, V>
         self.0 = new_tree;
         removed
     }
+
+    pub fn iter<'a>(&'a self) -> impl 'a + Iterator<Item = (&'a K, &'a V)> {
+        self.0.iter().map(|entry| (&entry.key, &entry.value))
+    }
+}
+
+impl<K, V> Default for TreeMap<K, V>
+where
+    K: Clone + Debug + Default,
+    V: Clone + Debug,
+{
+    fn default() -> Self {
+        Self(Default::default())
+    }
 }
 
 impl<K, V> Item for MapEntry<K, V>

crates/text/src/selection.rs 🔗

@@ -1,10 +1,6 @@
 use crate::Anchor;
 use crate::{rope::TextDimension, BufferSnapshot, ToOffset, ToPoint};
-use std::{cmp::Ordering, ops::Range, sync::Arc};
-use sum_tree::Bias;
-
-pub type SelectionSetId = clock::Lamport;
-pub type SelectionsVersion = usize;
+use std::cmp::Ordering;
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub enum SelectionGoal {
@@ -22,20 +18,6 @@ pub struct Selection<T> {
     pub goal: SelectionGoal,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct SelectionSet {
-    pub id: SelectionSetId,
-    pub active: bool,
-    pub selections: Arc<[Selection<Anchor>]>,
-}
-
-#[derive(Debug, Eq, PartialEq)]
-pub struct SelectionState {
-    pub id: usize,
-    pub reversed: bool,
-    pub goal: SelectionGoal,
-}
-
 impl<T: Clone> Selection<T> {
     pub fn head(&self) -> T {
         if self.reversed {
@@ -90,78 +72,3 @@ impl Selection<Anchor> {
         }
     }
 }
-
-impl SelectionSet {
-    pub fn len(&self) -> usize {
-        self.selections.len()
-    }
-
-    pub fn selections<'a, D>(
-        &'a self,
-        snapshot: &'a BufferSnapshot,
-    ) -> impl 'a + Iterator<Item = Selection<D>>
-    where
-        D: TextDimension,
-    {
-        let anchors = self
-            .selections
-            .iter()
-            .flat_map(|selection| [&selection.start, &selection.end].into_iter());
-        let mut positions = snapshot.summaries_for_anchors::<D, _>(anchors);
-        self.selections.iter().map(move |selection| Selection {
-            start: positions.next().unwrap(),
-            end: positions.next().unwrap(),
-            goal: selection.goal,
-            reversed: selection.reversed,
-            id: selection.id,
-        })
-    }
-
-    pub fn intersecting_selections<'a, D, I>(
-        &'a self,
-        range: Range<(I, Bias)>,
-        snapshot: &'a BufferSnapshot,
-    ) -> impl 'a + Iterator<Item = Selection<D>>
-    where
-        D: TextDimension,
-        I: 'a + ToOffset,
-    {
-        let start = snapshot.anchor_at(range.start.0, range.start.1);
-        let end = snapshot.anchor_at(range.end.0, range.end.1);
-        let start_ix = match self
-            .selections
-            .binary_search_by(|probe| probe.end.cmp(&start, snapshot).unwrap())
-        {
-            Ok(ix) | Err(ix) => ix,
-        };
-        let end_ix = match self
-            .selections
-            .binary_search_by(|probe| probe.start.cmp(&end, snapshot).unwrap())
-        {
-            Ok(ix) | Err(ix) => ix,
-        };
-        self.selections[start_ix..end_ix]
-            .iter()
-            .map(|s| s.resolve(snapshot))
-    }
-
-    pub fn oldest_selection<'a, D>(&'a self, snapshot: &'a BufferSnapshot) -> Option<Selection<D>>
-    where
-        D: TextDimension,
-    {
-        self.selections
-            .iter()
-            .min_by_key(|s| s.id)
-            .map(|s| s.resolve(snapshot))
-    }
-
-    pub fn newest_selection<'a, D>(&'a self, snapshot: &'a BufferSnapshot) -> Option<Selection<D>>
-    where
-        D: TextDimension,
-    {
-        self.selections
-            .iter()
-            .max_by_key(|s| s.id)
-            .map(|s| s.resolve(snapshot))
-    }
-}

crates/text/src/text.rs 🔗

@@ -44,7 +44,6 @@ pub struct Buffer {
     snapshot: BufferSnapshot,
     last_edit: clock::Local,
     history: History,
-    selection_sets: HashMap<SelectionSetId, SelectionSet>,
     deferred_ops: OperationQueue<Operation>,
     deferred_replicas: HashSet<ReplicaId>,
     replica_id: ReplicaId,
@@ -413,19 +412,6 @@ pub enum Operation {
         undo: UndoOperation,
         lamport_timestamp: clock::Lamport,
     },
-    UpdateSelections {
-        set_id: SelectionSetId,
-        selections: Arc<[Selection<Anchor>]>,
-        lamport_timestamp: clock::Lamport,
-    },
-    RemoveSelections {
-        set_id: SelectionSetId,
-        lamport_timestamp: clock::Lamport,
-    },
-    SetActiveSelections {
-        set_id: Option<SelectionSetId>,
-        lamport_timestamp: clock::Lamport,
-    },
 }
 
 #[derive(Clone, Debug, Eq, PartialEq)]
@@ -487,7 +473,6 @@ impl Buffer {
             },
             last_edit: clock::Local::default(),
             history,
-            selection_sets: Default::default(),
             deferred_ops: OperationQueue::new(),
             deferred_replicas: HashSet::default(),
             replica_id,
@@ -514,6 +499,10 @@ impl Buffer {
         self.lamport_clock
     }
 
+    pub fn observe_lamport_timestamp(&mut self, timestamp: clock::Lamport) {
+        self.lamport_clock.observe(timestamp);
+    }
+
     pub fn remote_id(&self) -> u64 {
         self.remote_id
     }
@@ -754,47 +743,6 @@ impl Buffer {
                     self.lamport_clock.observe(lamport_timestamp);
                 }
             }
-            Operation::UpdateSelections {
-                set_id,
-                selections,
-                lamport_timestamp,
-            } => {
-                if let Some(set) = self.selection_sets.get_mut(&set_id) {
-                    set.selections = selections;
-                } else {
-                    self.selection_sets.insert(
-                        set_id,
-                        SelectionSet {
-                            id: set_id,
-                            selections,
-                            active: false,
-                        },
-                    );
-                }
-                self.lamport_clock.observe(lamport_timestamp);
-            }
-            Operation::RemoveSelections {
-                set_id,
-                lamport_timestamp,
-            } => {
-                self.selection_sets.remove(&set_id);
-                self.lamport_clock.observe(lamport_timestamp);
-            }
-            Operation::SetActiveSelections {
-                set_id,
-                lamport_timestamp,
-            } => {
-                for (id, set) in &mut self.selection_sets {
-                    if id.replica_id == lamport_timestamp.replica_id {
-                        if Some(*id) == set_id {
-                            set.active = true;
-                        } else {
-                            set.active = false;
-                        }
-                    }
-                }
-                self.lamport_clock.observe(lamport_timestamp);
-            }
         }
         Ok(())
     }
@@ -1107,13 +1055,6 @@ impl Buffer {
             match op {
                 Operation::Edit(edit) => self.version.ge(&edit.version),
                 Operation::Undo { undo, .. } => self.version.ge(&undo.version),
-                Operation::UpdateSelections { selections, .. } => selections
-                    .iter()
-                    .all(|s| self.can_resolve(&s.start) && self.can_resolve(&s.end)),
-                Operation::RemoveSelections { .. } => true,
-                Operation::SetActiveSelections { set_id, .. } => {
-                    set_id.map_or(true, |set_id| self.selection_sets.contains_key(&set_id))
-                }
             }
         }
     }
@@ -1151,11 +1092,6 @@ impl Buffer {
         }
     }
 
-    pub fn remove_peer(&mut self, replica_id: ReplicaId) {
-        self.selection_sets
-            .retain(|set_id, _| set_id.replica_id != replica_id)
-    }
-
     pub fn base_text(&self) -> &Arc<str> {
         &self.history.base_text
     }
@@ -2007,15 +1943,6 @@ impl operation_queue::Operation for Operation {
             Operation::Undo {
                 lamport_timestamp, ..
             } => *lamport_timestamp,
-            Operation::UpdateSelections {
-                lamport_timestamp, ..
-            } => *lamport_timestamp,
-            Operation::RemoveSelections {
-                lamport_timestamp, ..
-            } => *lamport_timestamp,
-            Operation::SetActiveSelections {
-                lamport_timestamp, ..
-            } => *lamport_timestamp,
         }
     }
 }