Return optional transaction ids from undo/redo

Nathan Sobo created

This will allow the editor to restore selections that it associated with the start or end of a transaction.

Change summary

crates/editor/src/multi_buffer.rs |  4 ++--
crates/language/src/buffer.rs     | 28 ++++++++++++++++++----------
crates/text/src/text.rs           | 18 ++++++++++++------
3 files changed, 32 insertions(+), 18 deletions(-)

Detailed changes

crates/editor/src/multi_buffer.rs 🔗

@@ -224,14 +224,14 @@ impl MultiBuffer {
         })
     }
 
-    pub fn undo(&mut self, cx: &mut ModelContext<Self>) {
+    pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
         // TODO
         self.as_singleton()
             .unwrap()
             .update(cx, |buffer, cx| buffer.undo(cx))
     }
 
-    pub fn redo(&mut self, cx: &mut ModelContext<Self>) {
+    pub fn redo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
         // TODO
         self.as_singleton()
             .unwrap()

crates/language/src/buffer.rs 🔗

@@ -1443,26 +1443,34 @@ impl Buffer {
         cx.notify();
     }
 
-    pub fn undo(&mut self, cx: &mut ModelContext<Self>) {
+    pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
         let was_dirty = self.is_dirty();
         let old_version = self.version.clone();
 
-        for operation in self.text.undo() {
-            self.send_operation(Operation::Buffer(operation), cx);
+        if let Some((transaction_id, operations)) = self.text.undo() {
+            for operation in operations {
+                self.send_operation(Operation::Buffer(operation), cx);
+            }
+            self.did_edit(&old_version, was_dirty, cx);
+            Some(transaction_id)
+        } else {
+            None
         }
-
-        self.did_edit(&old_version, was_dirty, cx);
     }
 
-    pub fn redo(&mut self, cx: &mut ModelContext<Self>) {
+    pub fn redo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
         let was_dirty = self.is_dirty();
         let old_version = self.version.clone();
 
-        for operation in self.text.redo() {
-            self.send_operation(Operation::Buffer(operation), cx);
+        if let Some((transaction_id, operations)) = self.text.redo() {
+            for operation in operations {
+                self.send_operation(Operation::Buffer(operation), cx);
+            }
+            self.did_edit(&old_version, was_dirty, cx);
+            Some(transaction_id)
+        } else {
+            None
         }
-
-        self.did_edit(&old_version, was_dirty, cx);
     }
 }
 

crates/text/src/text.rs 🔗

@@ -1221,28 +1221,34 @@ impl Buffer {
         self.history.ops.values()
     }
 
-    pub fn undo(&mut self) -> Vec<Operation> {
-        let mut ops = Vec::new();
+    pub fn undo(&mut self) -> Option<(TransactionId, Vec<Operation>)> {
         if let Some(transaction) = self.history.pop_undo().cloned() {
+            let transaction_id = transaction.id;
             let selections = transaction.selections_before.clone();
+            let mut ops = Vec::new();
             ops.push(self.undo_or_redo(transaction).unwrap());
             for (set_id, selections) in selections {
                 ops.extend(self.restore_selection_set(set_id, selections));
             }
+            Some((transaction_id, ops))
+        } else {
+            None
         }
-        ops
     }
 
-    pub fn redo(&mut self) -> Vec<Operation> {
-        let mut ops = Vec::new();
+    pub fn redo(&mut self) -> Option<(TransactionId, Vec<Operation>)> {
         if let Some(transaction) = self.history.pop_redo().cloned() {
+            let transaction_id = transaction.id;
             let selections = transaction.selections_after.clone();
+            let mut ops = Vec::new();
             ops.push(self.undo_or_redo(transaction).unwrap());
             for (set_id, selections) in selections {
                 ops.extend(self.restore_selection_set(set_id, selections));
             }
+            Some((transaction_id, ops))
+        } else {
+            None
         }
-        ops
     }
 
     fn undo_or_redo(&mut self, transaction: Transaction) -> Result<Operation> {