diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index 0cc8575e99..ad90f90b9d 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -65,34 +65,26 @@ impl FollowableItem for Editor { }) }); editor.update(&mut cx, |editor, cx| { - let excerpt_id; - let buffer_id; - { - let buffer = editor.buffer.read(cx).read(cx); - let singleton = buffer.as_singleton().unwrap(); - excerpt_id = singleton.0.clone(); - buffer_id = singleton.1; - } + let buffer = editor.buffer.read(cx).read(cx); let selections = state .selections .into_iter() .map(|selection| { - deserialize_selection(&excerpt_id, buffer_id, selection) + deserialize_selection(&buffer, selection) .ok_or_else(|| anyhow!("invalid selection")) }) .collect::>>()?; + let scroll_top_anchor = state + .scroll_top_anchor + .and_then(|anchor| deserialize_anchor(&buffer, anchor)); + drop(buffer); + if !selections.is_empty() { editor.set_selections_from_remote(selections, cx); } - - if let Some(anchor) = state.scroll_top_anchor { + if let Some(scroll_top_anchor) = scroll_top_anchor { editor.set_scroll_top_anchor( - Anchor { - buffer_id: Some(state.buffer_id as usize), - excerpt_id, - text_anchor: language::proto::deserialize_anchor(anchor) - .ok_or_else(|| anyhow!("invalid scroll top"))?, - }, + scroll_top_anchor, vec2f(state.scroll_x, state.scroll_y), cx, ); @@ -133,9 +125,7 @@ impl FollowableItem for Editor { let buffer_id = self.buffer.read(cx).as_singleton()?.read(cx).remote_id(); Some(proto::view::Variant::Editor(proto::view::Editor { buffer_id, - scroll_top_anchor: Some(language::proto::serialize_anchor( - &self.scroll_top_anchor.text_anchor, - )), + scroll_top_anchor: Some(serialize_anchor(&self.scroll_top_anchor)), scroll_x: self.scroll_position.x(), scroll_y: self.scroll_position.y(), selections: self @@ -159,9 +149,7 @@ impl FollowableItem for Editor { match update { proto::update_view::Variant::Editor(update) => match event { Event::ScrollPositionChanged { .. } => { - update.scroll_top_anchor = Some(language::proto::serialize_anchor( - &self.scroll_top_anchor.text_anchor, - )); + update.scroll_top_anchor = Some(serialize_anchor(&self.scroll_top_anchor)); update.scroll_x = self.scroll_position.x(); update.scroll_y = self.scroll_position.y(); true @@ -190,29 +178,22 @@ impl FollowableItem for Editor { update_view::Variant::Editor(message) => { let buffer = self.buffer.read(cx); let buffer = buffer.read(cx); - let (excerpt_id, buffer_id, _) = buffer.as_singleton().unwrap(); - let excerpt_id = excerpt_id.clone(); - drop(buffer); - let selections = message .selections .into_iter() - .filter_map(|selection| { - deserialize_selection(&excerpt_id, buffer_id, selection) - }) + .filter_map(|selection| deserialize_selection(&buffer, selection)) .collect::>(); + let scroll_top_anchor = message + .scroll_top_anchor + .and_then(|anchor| deserialize_anchor(&buffer, anchor)); + drop(buffer); if !selections.is_empty() { self.set_selections_from_remote(selections, cx); self.request_autoscroll_remotely(Autoscroll::newest(), cx); - } else if let Some(anchor) = message.scroll_top_anchor { + } else if let Some(anchor) = scroll_top_anchor { self.set_scroll_top_anchor( - Anchor { - buffer_id: Some(buffer_id), - excerpt_id, - text_anchor: language::proto::deserialize_anchor(anchor) - .ok_or_else(|| anyhow!("invalid scroll top"))?, - }, + anchor, vec2f(message.scroll_x, message.scroll_y), cx, ); @@ -235,38 +216,41 @@ impl FollowableItem for Editor { fn serialize_selection(selection: &Selection) -> proto::Selection { proto::Selection { id: selection.id as u64, - start: Some(language::proto::serialize_anchor( - &selection.start.text_anchor, - )), - end: Some(language::proto::serialize_anchor( - &selection.end.text_anchor, - )), + start: Some(serialize_anchor(&selection.start)), + end: Some(serialize_anchor(&selection.end)), reversed: selection.reversed, } } +fn serialize_anchor(anchor: &Anchor) -> proto::EditorAnchor { + proto::EditorAnchor { + excerpt_id: anchor.excerpt_id.to_proto(), + anchor: Some(language::proto::serialize_anchor(&anchor.text_anchor)), + } +} + fn deserialize_selection( - excerpt_id: &ExcerptId, - buffer_id: usize, + buffer: &MultiBufferSnapshot, selection: proto::Selection, ) -> Option> { Some(Selection { id: selection.id as usize, - start: Anchor { - buffer_id: Some(buffer_id), - excerpt_id: excerpt_id.clone(), - text_anchor: language::proto::deserialize_anchor(selection.start?)?, - }, - end: Anchor { - buffer_id: Some(buffer_id), - excerpt_id: excerpt_id.clone(), - text_anchor: language::proto::deserialize_anchor(selection.end?)?, - }, + start: deserialize_anchor(buffer, selection.start?)?, + end: deserialize_anchor(buffer, selection.end?)?, reversed: selection.reversed, goal: SelectionGoal::None, }) } +fn deserialize_anchor(buffer: &MultiBufferSnapshot, anchor: proto::EditorAnchor) -> Option { + let excerpt_id = ExcerptId::from_proto(anchor.excerpt_id); + Some(Anchor { + excerpt_id, + text_anchor: language::proto::deserialize_anchor(anchor.anchor?)?, + buffer_id: Some(buffer.buffer_id_for_excerpt(excerpt_id)?), + }) +} + impl Item for Editor { fn navigate(&mut self, data: Box, cx: &mut ViewContext) -> bool { if let Ok(data) = data.downcast::() { diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index ace07a347f..35e26534d7 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -2813,6 +2813,10 @@ impl MultiBufferSnapshot { } } + pub fn buffer_id_for_excerpt(&self, excerpt_id: ExcerptId) -> Option { + Some(self.excerpt(excerpt_id)?.buffer_id) + } + fn excerpt<'a>(&'a self, excerpt_id: ExcerptId) -> Option<&'a Excerpt> { let mut cursor = self.excerpts.cursor::>(); let locator = self.excerpt_locator_for_id(excerpt_id); @@ -3147,6 +3151,14 @@ impl ExcerptId { Self(usize::MAX) } + pub fn to_proto(&self) -> u64 { + self.0 as _ + } + + pub fn from_proto(proto: u64) -> Self { + Self(proto as _) + } + pub fn cmp(&self, other: &Self, snapshot: &MultiBufferSnapshot) -> cmp::Ordering { let a = snapshot.excerpt_locator_for_id(*self); let b = snapshot.excerpt_locator_for_id(*other); diff --git a/crates/language/src/proto.rs b/crates/language/src/proto.rs index 674ce4f50e..9612deb5bd 100644 --- a/crates/language/src/proto.rs +++ b/crates/language/src/proto.rs @@ -9,7 +9,7 @@ use rpc::proto; use std::{ops::Range, sync::Arc}; use text::*; -pub use proto::{BufferState, Operation, SelectionSet}; +pub use proto::{BufferState, Operation}; pub fn deserialize_line_ending(message: proto::LineEnding) -> fs::LineEnding { match message { @@ -122,8 +122,14 @@ pub fn serialize_selections(selections: &Arc<[Selection]>) -> Vec) -> proto::Selection { proto::Selection { id: selection.id as u64, - start: Some(serialize_anchor(&selection.start)), - end: Some(serialize_anchor(&selection.end)), + start: Some(proto::EditorAnchor { + anchor: Some(serialize_anchor(&selection.start)), + excerpt_id: 0, + }), + end: Some(proto::EditorAnchor { + anchor: Some(serialize_anchor(&selection.end)), + excerpt_id: 0, + }), reversed: selection.reversed, } } @@ -229,8 +235,8 @@ pub fn deserialize_operation(message: proto::Operation) -> Result) -> Arc<[Selecti pub fn deserialize_selection(selection: proto::Selection) -> Option> { Some(Selection { id: selection.id as usize, - start: deserialize_anchor(selection.start?)?, - end: deserialize_anchor(selection.end?)?, + start: deserialize_anchor(selection.start?.anchor?)?, + end: deserialize_anchor(selection.end?.anchor?)?, reversed: selection.reversed, goal: SelectionGoal::None, }) diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index 6bfe7124c9..3bc612bdc4 100644 --- a/crates/rpc/proto/zed.proto +++ b/crates/rpc/proto/zed.proto @@ -848,7 +848,7 @@ message UpdateView { message Editor { repeated Selection selections = 1; - Anchor scroll_top_anchor = 2; + EditorAnchor scroll_top_anchor = 2; float scroll_x = 3; float scroll_y = 4; } @@ -865,7 +865,7 @@ message View { message Editor { uint64 buffer_id = 1; repeated Selection selections = 2; - Anchor scroll_top_anchor = 3; + EditorAnchor scroll_top_anchor = 3; float scroll_x = 4; float scroll_y = 5; } @@ -920,21 +920,18 @@ enum LineEnding { Windows = 1; } -message SelectionSet { - uint32 replica_id = 1; - repeated Selection selections = 2; - uint32 lamport_timestamp = 3; - bool line_mode = 4; - CursorShape cursor_shape = 5; -} - message Selection { uint64 id = 1; - Anchor start = 2; - Anchor end = 3; + EditorAnchor start = 2; + EditorAnchor end = 3; bool reversed = 4; } +message EditorAnchor { + uint64 excerpt_id = 1; + Anchor anchor = 2; +} + enum CursorShape { CursorBar = 0; CursorBlock = 1;