diff --git a/zed/src/editor/buffer.rs b/zed/src/editor/buffer.rs index 68ddb22b5acb8b4c7a177a1375a4fb28f19847d4..7971327c33e44633c9b96d3da76909486d460278 100644 --- a/zed/src/editor/buffer.rs +++ b/zed/src/editor/buffer.rs @@ -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::(); - 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);