diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index c663e442a7..07a01f7363 100644 --- a/crates/editor/src/editor.rs +++ b/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::(&display_map.buffer_snapshot, cx); + let newest_selection = self.newest_selection::(&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::(cx); + let selections = self.local_selections::(cx); first_cursor_top = selections .first() .unwrap() @@ -702,7 +702,7 @@ impl Editor { cx: &mut ViewContext, ) -> bool { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let selections = self.selections::(cx); + let selections = self.local_selections::(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::(&display_map.buffer_snapshot, cx) + .newest_selection::(&display_map.buffer_snapshot) .tail(); self.begin_selection(position, false, click_count, cx); @@ -855,8 +855,8 @@ impl Editor { self.update_selections::(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::(buffer, cx); - let mut selections = self.selections(cx); + let newest_selection = self.newest_selection::(buffer); + let mut selections = self.local_selections(cx); selections.retain(|selection| selection.id != newest_selection.id); self.update_selections::(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::(&display_map.buffer_snapshot, cx) + .newest_selection::(&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.columnar_selection_tail.take(); if self.pending_selection.is_some() { - let selections = self.selections::(cx); + let selections = self.local_selections::(cx); self.update_selections(selections, None, cx); } } @@ -1047,13 +1047,13 @@ impl Editor { reversed: selection.reversed, goal: selection.goal, }; - if self.selections::(cx).is_empty() { + if self.local_selections::(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::(&buffer, cx); - if self.selection_count(cx) == 1 { + let mut oldest_selection = self.oldest_selection::(&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::(cx); + let selections = self.local_selections::(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.start_transaction(cx); - let old_selections = self.selections::(cx); + let old_selections = self.local_selections::(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) { - let selections = self.selections::(cx); + let selections = self.local_selections::(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) -> bool { - let old_selections = self.selections::(cx); + let old_selections = self.local_selections::(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.start_transaction(cx); - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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.start_transaction(cx); let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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.start_transaction(cx); let tab_size = self.build_settings.borrow()(cx).tab_size; - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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.start_transaction(cx); let tab_size = self.build_settings.borrow()(cx).tab_size; - let selections = self.selections::(cx); + let selections = self.local_selections::(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::(cx), Some(Autoscroll::Fit), cx); + self.update_selections( + self.local_selections::(cx), + Some(Autoscroll::Fit), + cx, + ); self.end_transaction(cx); } pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext) { self.start_transaction(cx); - let selections = self.selections::(cx); + let selections = self.local_selections::(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.start_transaction(cx); - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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.start_transaction(cx); - let selections = self.selections::(cx); + let selections = self.local_selections::(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.start_transaction(cx); - let selections = self.selections::(cx); + let selections = self.local_selections::(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.start_transaction(cx); let mut text = String::new(); - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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) { - let selections = self.selections::(cx); + let selections = self.local_selections::(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::>() { - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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) { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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) { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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) { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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) { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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::(cx); + let mut selections = self.local_selections::(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) { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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::(cx); + let mut selections = self.local_selections::(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) { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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, ) { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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, ) { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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::(cx); + let mut selections = self.local_selections::(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, ) { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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, ) { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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::(cx); + let mut selections = self.local_selections::(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, ) { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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, ) { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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) { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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) { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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) { - let mut selection = self.selections::(cx).last().unwrap().clone(); + let mut selection = self.local_selections::(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) { - let mut selection = self.selections::(cx).first().unwrap().clone(); + let mut selection = self.local_selections::(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) { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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::(cx); + let selections = self.local_selections::(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) { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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::(cx); + let mut selections = self.local_selections::(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::(cx); + let mut selections = self.local_selections::(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::(cx), Some(Autoscroll::Fit), cx); + self.update_selections( + self.local_selections::(cx), + Some(Autoscroll::Fit), + cx, + ); self.end_transaction(cx); } @@ -2736,7 +2744,7 @@ impl Editor { _: &SelectLargerSyntaxNode, cx: &mut ViewContext, ) { - let old_selections = self.selections::(cx).into_boxed_slice(); + let old_selections = self.local_selections::(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, ) { - let mut selections = self.selections::(cx); + let mut selections = self.local_selections::(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) { let buffer = self.buffer.read(cx).snapshot(cx); - let selection = self.newest_selection::(&buffer, cx); + let selection = self.newest_selection::(&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, cx: &'a mut MutableAppContext, - ) -> Vec> { - todo!() - // let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - // let buffer = self.buffer.read(cx); + ) -> HashMap>> + where + D: TextDimension + Ord + Sub, + { + let mut result = HashMap::new(); - // 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 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 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::(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() + 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::(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 selections<'a, D>(&self, cx: &'a AppContext) -> Vec> + pub fn local_selections<'a, D>(&self, cx: &'a AppContext) -> Vec> where D: 'a + TextDimension + Ord + Sub, { @@ -3067,7 +3086,7 @@ impl Editor { }) .peekable(); - let mut pending_selection = self.pending_selection::(&buffer, cx); + let mut pending_selection = self.pending_selection::(&buffer); iter::from_fn(move || { if let Some(pending) = pending_selection.as_mut() { @@ -3098,18 +3117,16 @@ impl Editor { fn pending_selection>( &self, snapshot: &MultiBufferSnapshot, - cx: &AppContext, ) -> Option> { 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>( &self, selection: &Selection, buffer: &MultiBufferSnapshot, - cx: &AppContext, ) -> Selection { 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>( &self, snapshot: &MultiBufferSnapshot, - cx: &AppContext, ) -> Selection { 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>( &self, snapshot: &MultiBufferSnapshot, - cx: &AppContext, ) -> Selection { - 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) { let mut fold_ranges = Vec::new(); - let selections = self.selections::(cx); + let selections = self.local_selections::(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) { - let selections = self.selections::(cx); + let selections = self.local_selections::(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) { - let selections = self.selections::(cx); + let selections = self.local_selections::(cx); let ranges = selections.into_iter().map(|s| s.start..s.end); self.fold_ranges(ranges, cx); } diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index cbc9ff223d..6989cc0fcc 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -249,7 +249,7 @@ impl CursorPosition { self.selected_count = 0; let mut last_selection: Option> = None; - for selection in editor.selections::(cx) { + for selection in editor.local_selections::(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, cx: &mut ViewContext) { let editor = editor.read(cx); let buffer = editor.buffer().read(cx); - let cursor_position = editor - .newest_selection::(&buffer.read(cx), cx) - .head(); + let cursor_position = editor.newest_selection::(&buffer.read(cx)).head(); let new_diagnostic = buffer .read(cx) .diagnostics_in_range::<_, usize>(cursor_position..cursor_position) diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index 1e93c16f77..51879bcf63 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/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, buffers: HashMap, subscriptions: Topic, - selection_sets: HashMap, 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, + ) -> impl 'a + Iterator>)> + 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 { diff --git a/crates/editor/src/multi_buffer/selection.rs b/crates/editor/src/multi_buffer/selection.rs index 3a4369b3da..86d36ae16b 100644 --- a/crates/editor/src/multi_buffer/selection.rs +++ b/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]>, -} - -impl SelectionSet { - pub fn len(&self) -> usize { - self.selections.len() - } - - pub fn selections<'a, D>( - &'a self, - snapshot: &'a MultiBufferSnapshot, - ) -> impl 'a + Iterator> - where - D: TextDimension + Ord + Sub, - { - resolve_selections(&self.selections, snapshot) - } - - pub fn intersecting_selections<'a, D, I>( - &'a self, - range: Range<(I, Bias)>, - snapshot: &'a MultiBufferSnapshot, - ) -> impl 'a + Iterator> - where - D: TextDimension + Ord + Sub, - 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> - where - D: TextDimension + Ord + Sub, - { - 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> - where - D: TextDimension + Ord + Sub, - { - 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, diff --git a/crates/go_to_line/src/go_to_line.rs b/crates/go_to_line/src/go_to_line.rs index 4c021ac1a4..85c5a6439b 100644 --- a/crates/go_to_line/src/go_to_line.rs +++ b/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::(cx), + selections: editor.local_selections::(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::(cx).id { + let newest_selection = + editor.newest_selection::(&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); } diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index b408bf589b..c0f968cb27 100644 --- a/crates/language/src/buffer.rs +++ b/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>, parsing_in_background: bool, parse_count: usize, + remote_selections: TreeMap]>>, diagnostics: DiagnosticSet, diagnostics_update_count: usize, language_server: Option, @@ -76,6 +78,7 @@ pub struct BufferSnapshot { text: text::BufferSnapshot, tree: Option, diagnostics: DiagnosticSet, + remote_selections: TreeMap]>>, diagnostics_update_count: usize, is_parsing: bool, language: Option>, @@ -112,6 +115,15 @@ pub enum Operation { diagnostics: Arc<[DiagnosticEntry]>, lamport_timestamp: clock::Lamport, }, + UpdateSelections { + replica_id: ReplicaId, + selections: Arc<[Selection]>, + 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.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, + ) -> impl 'a + Iterator>)> + 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, @@ -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, } } diff --git a/crates/language/src/proto.rs b/crates/language/src/proto.rs index 6f36c7dc0b..8921ffa421 100644 --- a/crates/language/src/proto.rs +++ b/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]>) -> Vec { + 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 { }) .collect::>(); - 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) -> Arc<[Selection]> { + 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::>(), - ), - } + }) + .collect::>(), + ) } pub fn deserialize_diagnostics( diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index 7e7a180cd2..7a06abb122 100644 --- a/crates/rpc/proto/zed.proto +++ b/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; } } diff --git a/crates/sum_tree/src/tree_map.rs b/crates/sum_tree/src/tree_map.rs index 75405cbef4..3619d7870e 100644 --- a/crates/sum_tree/src/tree_map.rs +++ b/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(SumTree>) where K: Clone + Debug + Default, @@ -19,7 +20,7 @@ pub struct MapKey(K); #[derive(Clone, Debug, Default)] pub struct MapKeyRef<'a, K>(Option<&'a K>); -impl TreeMap { +impl TreeMap { pub fn get<'a>(&self, key: &'a K) -> Option<&V> { let mut cursor = self.0.cursor::>(); let key = MapKeyRef(Some(key)); @@ -49,6 +50,20 @@ impl TreeMap self.0 = new_tree; removed } + + pub fn iter<'a>(&'a self) -> impl 'a + Iterator { + self.0.iter().map(|entry| (&entry.key, &entry.value)) + } +} + +impl Default for TreeMap +where + K: Clone + Debug + Default, + V: Clone + Debug, +{ + fn default() -> Self { + Self(Default::default()) + } } impl Item for MapEntry diff --git a/crates/text/src/selection.rs b/crates/text/src/selection.rs index 0afbf8cf74..4e7d6f5236 100644 --- a/crates/text/src/selection.rs +++ b/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 { pub goal: SelectionGoal, } -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct SelectionSet { - pub id: SelectionSetId, - pub active: bool, - pub selections: Arc<[Selection]>, -} - -#[derive(Debug, Eq, PartialEq)] -pub struct SelectionState { - pub id: usize, - pub reversed: bool, - pub goal: SelectionGoal, -} - impl Selection { pub fn head(&self) -> T { if self.reversed { @@ -90,78 +72,3 @@ impl Selection { } } } - -impl SelectionSet { - pub fn len(&self) -> usize { - self.selections.len() - } - - pub fn selections<'a, D>( - &'a self, - snapshot: &'a BufferSnapshot, - ) -> impl 'a + Iterator> - where - D: TextDimension, - { - let anchors = self - .selections - .iter() - .flat_map(|selection| [&selection.start, &selection.end].into_iter()); - let mut positions = snapshot.summaries_for_anchors::(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> - 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> - 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> - where - D: TextDimension, - { - self.selections - .iter() - .max_by_key(|s| s.id) - .map(|s| s.resolve(snapshot)) - } -} diff --git a/crates/text/src/text.rs b/crates/text/src/text.rs index 5da3c7043e..d715a3fbad 100644 --- a/crates/text/src/text.rs +++ b/crates/text/src/text.rs @@ -44,7 +44,6 @@ pub struct Buffer { snapshot: BufferSnapshot, last_edit: clock::Local, history: History, - selection_sets: HashMap, deferred_ops: OperationQueue, deferred_replicas: HashSet, replica_id: ReplicaId, @@ -413,19 +412,6 @@ pub enum Operation { undo: UndoOperation, lamport_timestamp: clock::Lamport, }, - UpdateSelections { - set_id: SelectionSetId, - selections: Arc<[Selection]>, - lamport_timestamp: clock::Lamport, - }, - RemoveSelections { - set_id: SelectionSetId, - lamport_timestamp: clock::Lamport, - }, - SetActiveSelections { - set_id: Option, - 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 { &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, } } }