diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index 9b274519d3..2c7c252e3b 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -3,7 +3,7 @@ mod fold_map; mod tab_map; mod wrap_map; -use crate::{Anchor, MultiBuffer, MultiBufferSnapshot, ToOffset, ToPoint}; +use crate::{Anchor, AnchorRangeExt, MultiBuffer, MultiBufferSnapshot, ToOffset, ToPoint}; use block_map::{BlockMap, BlockPoint}; use collections::{HashMap, HashSet}; use fold_map::FoldMap; @@ -97,6 +97,15 @@ impl DisplayMap { } } + pub fn set_state(&mut self, other: &DisplaySnapshot, cx: &mut ModelContext) { + self.fold( + other + .folds_in_range(0..other.buffer_snapshot.len()) + .map(|fold| fold.to_offset(&other.buffer_snapshot)), + cx, + ); + } + pub fn fold( &mut self, ranges: impl IntoIterator>, diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index def74d2250..428958e769 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -892,14 +892,7 @@ impl Editor { ) -> Self { let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx)); let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); - Self::new( - EditorMode::SingleLine, - buffer, - None, - field_editor_style, - None, - cx, - ) + Self::new(EditorMode::SingleLine, buffer, None, field_editor_style, cx) } pub fn auto_height( @@ -914,7 +907,6 @@ impl Editor { buffer, None, field_editor_style, - None, cx, ) } @@ -925,7 +917,7 @@ impl Editor { cx: &mut ViewContext, ) -> Self { let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); - Self::new(EditorMode::Full, buffer, project, None, None, cx) + Self::new(EditorMode::Full, buffer, project, None, cx) } pub fn for_multibuffer( @@ -933,7 +925,7 @@ impl Editor { project: Option>, cx: &mut ViewContext, ) -> Self { - Self::new(EditorMode::Full, buffer, project, None, None, cx) + Self::new(EditorMode::Full, buffer, project, None, cx) } pub fn clone(&self, cx: &mut ViewContext) -> Self { @@ -942,9 +934,15 @@ impl Editor { self.buffer.clone(), self.project.clone(), self.get_field_editor_theme, - Some(self.selections.clone()), cx, ); + self.display_map.update(cx, |display_map, cx| { + let snapshot = display_map.snapshot(cx); + clone.display_map.update(cx, |display_map, cx| { + display_map.set_state(&snapshot, cx); + }); + }); + clone.selections.set_state(&self.selections); clone.scroll_position = self.scroll_position; clone.scroll_top_anchor = self.scroll_top_anchor.clone(); clone.searchable = self.searchable; @@ -956,7 +954,6 @@ impl Editor { buffer: ModelHandle, project: Option>, get_field_editor_theme: Option, - selections: Option, cx: &mut ViewContext, ) -> Self { let display_map = cx.add_model(|cx| { @@ -977,8 +974,7 @@ impl Editor { cx.observe(&display_map, Self::on_display_map_changed) .detach(); - let selections = selections - .unwrap_or_else(|| SelectionsCollection::new(display_map.clone(), buffer.clone())); + let selections = SelectionsCollection::new(display_map.clone(), buffer.clone()); let mut this = Self { handle: cx.weak_handle(), @@ -6468,23 +6464,55 @@ mod tests { } #[gpui::test] - fn test_clone_with_selections(cx: &mut gpui::MutableAppContext) { + fn test_clone(cx: &mut gpui::MutableAppContext) { let (text, selection_ranges) = marked_text_ranges(indoc! {" - The qu[ick brown - fox jum]ps over - the lazy dog + one + two + three[] + four + five[] "}); cx.set_global(Settings::test(cx)); let buffer = MultiBuffer::build_simple(&text, cx); - let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx)); + let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx)); - let cloned_editor = view.update(cx, |view, cx| { - view.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone())); - view.clone(cx) + editor.update(cx, |editor, cx| { + editor.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone())); + editor.fold_ranges( + [ + Point::new(1, 0)..Point::new(2, 0), + Point::new(3, 0)..Point::new(4, 0), + ], + cx, + ); }); - assert_set_eq!(cloned_editor.selections.ranges(cx), selection_ranges); + let (_, cloned_editor) = editor.update(cx, |editor, cx| { + cx.add_window(Default::default(), |cx| editor.clone(cx)) + }); + + let snapshot = editor.update(cx, |e, cx| e.snapshot(cx)); + let cloned_snapshot = cloned_editor.update(cx, |e, cx| e.snapshot(cx)); + + assert_eq!( + cloned_editor.update(cx, |e, cx| e.display_text(cx)), + editor.update(cx, |e, cx| e.display_text(cx)) + ); + assert_eq!( + cloned_snapshot + .folds_in_range(0..text.len()) + .collect::>(), + snapshot.folds_in_range(0..text.len()).collect::>(), + ); + assert_set_eq!( + cloned_editor.read(cx).selections.ranges::(cx), + editor.read(cx).selections.ranges(cx) + ); + assert_set_eq!( + cloned_editor.update(cx, |e, cx| dbg!(e.selections.display_ranges(cx))), + editor.update(cx, |e, cx| dbg!(e.selections.display_ranges(cx))) + ); } #[gpui::test] diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 601ad98d86..b4762b5774 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1444,7 +1444,7 @@ impl Element for EditorElement { { return false; } - + let point = if paint.text_bounds.contains_point(*position) { let (point, overshoot) = paint.point_for_position(&self.snapshot(cx), layout, *position); @@ -1791,7 +1791,7 @@ mod tests { cx.set_global(Settings::test(cx)); let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx); let (window_id, editor) = cx.add_window(Default::default(), |cx| { - Editor::new(EditorMode::Full, buffer, None, None, None, cx) + Editor::new(EditorMode::Full, buffer, None, None, cx) }); let element = EditorElement::new( editor.downgrade(), @@ -1813,7 +1813,7 @@ mod tests { cx.set_global(Settings::test(cx)); let buffer = MultiBuffer::build_simple("", cx); let (window_id, editor) = cx.add_window(Default::default(), |cx| { - Editor::new(EditorMode::Full, buffer, None, None, None, cx) + Editor::new(EditorMode::Full, buffer, None, None, cx) }); editor.update(cx, |editor, cx| { diff --git a/crates/editor/src/selections_collection.rs b/crates/editor/src/selections_collection.rs index f99384bd79..1d02b26e4b 100644 --- a/crates/editor/src/selections_collection.rs +++ b/crates/editor/src/selections_collection.rs @@ -61,6 +61,13 @@ impl SelectionsCollection { self.buffer.read(cx).read(cx) } + pub fn set_state(&mut self, other: &SelectionsCollection) { + self.next_selection_id = other.next_selection_id; + self.line_mode = other.line_mode; + self.disjoint = other.disjoint.clone(); + self.pending = other.pending.clone(); + } + pub fn count<'a>(&self) -> usize { let mut count = self.disjoint.len(); if self.pending.is_some() { diff --git a/crates/editor/src/test.rs b/crates/editor/src/test.rs index 41eadd6130..33bb07e94c 100644 --- a/crates/editor/src/test.rs +++ b/crates/editor/src/test.rs @@ -77,7 +77,7 @@ pub(crate) fn build_editor( buffer: ModelHandle, cx: &mut ViewContext, ) -> Editor { - Editor::new(EditorMode::Full, buffer, None, None, None, cx) + Editor::new(EditorMode::Full, buffer, None, None, cx) } pub struct EditorTestContext<'a> { @@ -428,7 +428,7 @@ impl<'a> EditorLspTestContext<'a> { let (window_id, editor) = cx.add_window(Default::default(), |cx| { let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); - Editor::new(EditorMode::Full, buffer, Some(project), None, None, cx) + Editor::new(EditorMode::Full, buffer, Some(project), None, cx) }); editor.update(cx, |_, cx| cx.focus_self());