Clone fold and selection state correctly when splitting an editor
This commit is contained in:
parent
1720933597
commit
fb2a7787a1
5 changed files with 74 additions and 30 deletions
|
@ -3,7 +3,7 @@ mod fold_map;
|
||||||
mod tab_map;
|
mod tab_map;
|
||||||
mod wrap_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 block_map::{BlockMap, BlockPoint};
|
||||||
use collections::{HashMap, HashSet};
|
use collections::{HashMap, HashSet};
|
||||||
use fold_map::FoldMap;
|
use fold_map::FoldMap;
|
||||||
|
@ -97,6 +97,15 @@ impl DisplayMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_state(&mut self, other: &DisplaySnapshot, cx: &mut ModelContext<Self>) {
|
||||||
|
self.fold(
|
||||||
|
other
|
||||||
|
.folds_in_range(0..other.buffer_snapshot.len())
|
||||||
|
.map(|fold| fold.to_offset(&other.buffer_snapshot)),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn fold<T: ToOffset>(
|
pub fn fold<T: ToOffset>(
|
||||||
&mut self,
|
&mut self,
|
||||||
ranges: impl IntoIterator<Item = Range<T>>,
|
ranges: impl IntoIterator<Item = Range<T>>,
|
||||||
|
|
|
@ -891,14 +891,7 @@ impl Editor {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
|
let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
|
||||||
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
|
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||||
Self::new(
|
Self::new(EditorMode::SingleLine, buffer, None, field_editor_style, cx)
|
||||||
EditorMode::SingleLine,
|
|
||||||
buffer,
|
|
||||||
None,
|
|
||||||
field_editor_style,
|
|
||||||
None,
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn auto_height(
|
pub fn auto_height(
|
||||||
|
@ -913,7 +906,6 @@ impl Editor {
|
||||||
buffer,
|
buffer,
|
||||||
None,
|
None,
|
||||||
field_editor_style,
|
field_editor_style,
|
||||||
None,
|
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -924,7 +916,7 @@ impl Editor {
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
|
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(
|
pub fn for_multibuffer(
|
||||||
|
@ -932,7 +924,7 @@ impl Editor {
|
||||||
project: Option<ModelHandle<Project>>,
|
project: Option<ModelHandle<Project>>,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Self {
|
) -> 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>) -> Self {
|
pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
|
||||||
|
@ -941,9 +933,15 @@ impl Editor {
|
||||||
self.buffer.clone(),
|
self.buffer.clone(),
|
||||||
self.project.clone(),
|
self.project.clone(),
|
||||||
self.get_field_editor_theme,
|
self.get_field_editor_theme,
|
||||||
Some(self.selections.clone()),
|
|
||||||
cx,
|
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_position = self.scroll_position;
|
||||||
clone.scroll_top_anchor = self.scroll_top_anchor.clone();
|
clone.scroll_top_anchor = self.scroll_top_anchor.clone();
|
||||||
clone.searchable = self.searchable;
|
clone.searchable = self.searchable;
|
||||||
|
@ -955,7 +953,6 @@ impl Editor {
|
||||||
buffer: ModelHandle<MultiBuffer>,
|
buffer: ModelHandle<MultiBuffer>,
|
||||||
project: Option<ModelHandle<Project>>,
|
project: Option<ModelHandle<Project>>,
|
||||||
get_field_editor_theme: Option<GetFieldEditorTheme>,
|
get_field_editor_theme: Option<GetFieldEditorTheme>,
|
||||||
selections: Option<SelectionsCollection>,
|
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let display_map = cx.add_model(|cx| {
|
let display_map = cx.add_model(|cx| {
|
||||||
|
@ -976,8 +973,7 @@ impl Editor {
|
||||||
cx.observe(&display_map, Self::on_display_map_changed)
|
cx.observe(&display_map, Self::on_display_map_changed)
|
||||||
.detach();
|
.detach();
|
||||||
|
|
||||||
let selections = selections
|
let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
|
||||||
.unwrap_or_else(|| SelectionsCollection::new(display_map.clone(), buffer.clone()));
|
|
||||||
|
|
||||||
let mut this = Self {
|
let mut this = Self {
|
||||||
handle: cx.weak_handle(),
|
handle: cx.weak_handle(),
|
||||||
|
@ -6463,23 +6459,55 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[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! {"
|
let (text, selection_ranges) = marked_text_ranges(indoc! {"
|
||||||
The qu[ick brown
|
one
|
||||||
fox jum]ps over
|
two
|
||||||
the lazy dog
|
three[]
|
||||||
|
four
|
||||||
|
five[]
|
||||||
"});
|
"});
|
||||||
cx.set_global(Settings::test(cx));
|
cx.set_global(Settings::test(cx));
|
||||||
let buffer = MultiBuffer::build_simple(&text, 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| {
|
editor.update(cx, |editor, cx| {
|
||||||
view.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone()));
|
editor.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone()));
|
||||||
view.clone(cx)
|
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::<Vec<_>>(),
|
||||||
|
snapshot.folds_in_range(0..text.len()).collect::<Vec<_>>(),
|
||||||
|
);
|
||||||
|
assert_set_eq!(
|
||||||
|
cloned_editor.read(cx).selections.ranges::<Point>(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]
|
#[gpui::test]
|
||||||
|
|
|
@ -1791,7 +1791,7 @@ mod tests {
|
||||||
cx.set_global(Settings::test(cx));
|
cx.set_global(Settings::test(cx));
|
||||||
let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
|
let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
|
||||||
let (window_id, editor) = cx.add_window(Default::default(), |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(
|
let element = EditorElement::new(
|
||||||
editor.downgrade(),
|
editor.downgrade(),
|
||||||
|
@ -1813,7 +1813,7 @@ mod tests {
|
||||||
cx.set_global(Settings::test(cx));
|
cx.set_global(Settings::test(cx));
|
||||||
let buffer = MultiBuffer::build_simple("", cx);
|
let buffer = MultiBuffer::build_simple("", cx);
|
||||||
let (window_id, editor) = cx.add_window(Default::default(), |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| {
|
editor.update(cx, |editor, cx| {
|
||||||
|
|
|
@ -61,6 +61,13 @@ impl SelectionsCollection {
|
||||||
self.buffer.read(cx).read(cx)
|
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 {
|
pub fn count<'a>(&self) -> usize {
|
||||||
let mut count = self.disjoint.len();
|
let mut count = self.disjoint.len();
|
||||||
if self.pending.is_some() {
|
if self.pending.is_some() {
|
||||||
|
|
|
@ -77,7 +77,7 @@ pub(crate) fn build_editor(
|
||||||
buffer: ModelHandle<MultiBuffer>,
|
buffer: ModelHandle<MultiBuffer>,
|
||||||
cx: &mut ViewContext<Editor>,
|
cx: &mut ViewContext<Editor>,
|
||||||
) -> Editor {
|
) -> Editor {
|
||||||
Editor::new(EditorMode::Full, buffer, None, None, None, cx)
|
Editor::new(EditorMode::Full, buffer, None, None, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EditorTestContext<'a> {
|
pub struct EditorTestContext<'a> {
|
||||||
|
@ -428,7 +428,7 @@ impl<'a> EditorLspTestContext<'a> {
|
||||||
let (window_id, editor) = cx.add_window(Default::default(), |cx| {
|
let (window_id, editor) = cx.add_window(Default::default(), |cx| {
|
||||||
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, 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());
|
editor.update(cx, |_, cx| cx.focus_self());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue