Speed up undoing multi-cursor changes
This commit is contained in:
+32
-14
@@ -1340,33 +1340,42 @@ impl Buffer {
|
||||
|
||||
fn apply_undo(&mut self, undo: UndoOperation) -> Result<()> {
|
||||
self.undo_map.insert(undo);
|
||||
|
||||
let edit = &self.history.ops[&undo.edit_id];
|
||||
let version = Some(edit.version.clone());
|
||||
let mut cx = edit.version.clone();
|
||||
cx.observe(undo.edit_id);
|
||||
let cx = Some(cx);
|
||||
|
||||
let mut old_fragments = self.fragments.cursor::<VersionedOffset, VersionedOffset>();
|
||||
old_fragments.seek(&VersionedOffset::Offset(0), Bias::Left, &version);
|
||||
|
||||
let mut new_fragments = SumTree::new();
|
||||
let mut new_fragments = old_fragments.slice(
|
||||
&VersionedOffset::Offset(edit.ranges[0].start),
|
||||
Bias::Right,
|
||||
&cx,
|
||||
);
|
||||
let mut new_ropes =
|
||||
RopeBuilder::new(self.visible_text.cursor(0), self.deleted_text.cursor(0));
|
||||
new_ropes.push_tree(new_fragments.summary().text);
|
||||
|
||||
for range in &edit.ranges {
|
||||
let mut end_offset = old_fragments.end(&version).offset();
|
||||
let insertion_len = edit.new_text.as_ref().map_or(0, |i| i.len());
|
||||
for (ix, range) in edit.ranges.iter().enumerate() {
|
||||
let delta = ix * insertion_len;
|
||||
let mut end_offset = old_fragments.end(&cx).offset();
|
||||
|
||||
if end_offset < range.start {
|
||||
if end_offset < range.start + delta {
|
||||
let preceding_fragments = old_fragments.slice(
|
||||
&VersionedOffset::Offset(range.start),
|
||||
Bias::Left,
|
||||
&version,
|
||||
&VersionedOffset::Offset(range.start + delta),
|
||||
Bias::Right,
|
||||
&cx,
|
||||
);
|
||||
new_ropes.push_tree(preceding_fragments.summary().text);
|
||||
new_fragments.push_tree(preceding_fragments, &None);
|
||||
}
|
||||
|
||||
while end_offset <= range.end {
|
||||
while end_offset <= delta + range.end + insertion_len {
|
||||
if let Some(fragment) = old_fragments.item() {
|
||||
let mut fragment = fragment.clone();
|
||||
let fragment_was_visible = fragment.visible;
|
||||
|
||||
if fragment.was_visible(&edit.version, &self.undo_map)
|
||||
|| fragment.timestamp.local() == edit.timestamp.local()
|
||||
{
|
||||
@@ -1376,15 +1385,24 @@ impl Buffer {
|
||||
new_ropes.push_fragment(&fragment, fragment_was_visible);
|
||||
new_fragments.push(fragment, &None);
|
||||
|
||||
old_fragments.next(&version);
|
||||
end_offset = old_fragments.end(&version).offset();
|
||||
old_fragments.next(&cx);
|
||||
if end_offset == old_fragments.end(&cx).offset() {
|
||||
let unseen_fragments = old_fragments.slice(
|
||||
&VersionedOffset::Offset(end_offset),
|
||||
Bias::Right,
|
||||
&cx,
|
||||
);
|
||||
new_ropes.push_tree(unseen_fragments.summary().text);
|
||||
new_fragments.push_tree(unseen_fragments, &None);
|
||||
}
|
||||
end_offset = old_fragments.end(&cx).offset();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let suffix = old_fragments.suffix(&version);
|
||||
let suffix = old_fragments.suffix(&cx);
|
||||
new_ropes.push_tree(suffix.summary().text);
|
||||
new_fragments.push_tree(suffix, &None);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user