Restore `History::group`

Antonio Scandurra created

Change summary

zed/src/editor/buffer.rs | 42 +++++++++++++++++++++++++++++++++++++-----
1 file changed, 37 insertions(+), 5 deletions(-)

Detailed changes

zed/src/editor/buffer.rs 🔗

@@ -228,11 +228,7 @@ impl History {
         now: Instant,
     ) {
         self.transaction_depth += 1;
-        if self.transaction_depth == 1
-            && self.undo_stack.last().map_or(true, |transaction| {
-                transaction.end != start || (now - transaction.last_edit_at) > self.group_interval
-            })
-        {
+        if self.transaction_depth == 1 {
             self.undo_stack.push(Transaction {
                 start: start.clone(),
                 end: start,
@@ -264,6 +260,41 @@ impl History {
         }
     }
 
+    fn group(&mut self) {
+        let mut new_len = self.undo_stack.len();
+        let mut transactions = self.undo_stack.iter_mut();
+
+        if let Some(mut transaction) = transactions.next_back() {
+            while let Some(prev_transaction) = transactions.next_back() {
+                if transaction.first_edit_at - prev_transaction.last_edit_at <= self.group_interval
+                    && transaction.start == prev_transaction.end
+                {
+                    transaction = prev_transaction;
+                    new_len -= 1;
+                } else {
+                    break;
+                }
+            }
+        }
+
+        let (transactions_to_keep, transactions_to_merge) = self.undo_stack.split_at_mut(new_len);
+        if let Some(last_transaction) = transactions_to_keep.last_mut() {
+            for transaction in &*transactions_to_merge {
+                for edit_id in &transaction.edits {
+                    last_transaction.push_edit(&self.ops[edit_id]);
+                }
+            }
+
+            if let Some(transaction) = transactions_to_merge.last_mut() {
+                last_transaction.last_edit_at = transaction.last_edit_at;
+                last_transaction.selections_after = transaction.selections_after.take();
+                last_transaction.end = transaction.end.clone();
+            }
+        }
+
+        self.undo_stack.truncate(new_len);
+    }
+
     fn push_undo(&mut self, edit_id: time::Local) {
         assert_ne!(self.transaction_depth, 0);
         let last_transaction = self.undo_stack.last_mut().unwrap();
@@ -931,6 +962,7 @@ impl Buffer {
         if let Some(transaction) = self.history.end_transaction(selections, now) {
             let since = transaction.start.clone();
             let was_dirty = transaction.buffer_was_dirty;
+            self.history.group();
 
             if let Some(cx) = cx {
                 cx.notify();