mirror of
https://github.com/storytold/gridcraft.git
synced 2026-10-30 05:37:00 -06:00
Engine: the panic guard restores entries a nested Undo removed
Truncating the undo history to its length at the command's start cannot bring back an entry that a nested edit.undo popped. The guard now keeps the undo and redo history as they were and puts both back. The regression test gains the undo-then-panic case.
This commit is contained in:
@@ -533,8 +533,9 @@ impl Session {
|
|||||||
// Whether a group was open on the document before the command, and how long its history was.
|
// Whether a group was open on the document before the command, and how long its history was.
|
||||||
let start = before.as_ref().and_then(|(uid, ..)| self.docs.iter().find(|d| d.uid == *uid).map(|d| (self.in_group(*uid), d.undo.len())));
|
let start = before.as_ref().and_then(|(uid, ..)| self.docs.iter().find(|d| d.uid == *uid).map(|d| (self.in_group(*uid), d.undo.len())));
|
||||||
// A command that panics leaves the history as it found it: the steps commands nested in it
|
// A command that panics leaves the history as it found it: the steps commands nested in it
|
||||||
// made go with the workbook, and the redo history they cleared comes back.
|
// made or undid, and the redo history they cleared, come back. A length is not enough,
|
||||||
let redo_before = before.as_ref().and_then(|(uid, ..)| self.docs.iter().find(|d| d.uid == *uid).map(|d| d.redo.clone()));
|
// because a nested `edit.undo` removes entries.
|
||||||
|
let history_before = before.as_ref().and_then(|(uid, ..)| self.docs.iter().find(|d| d.uid == *uid).map(|d| (d.undo.clone(), d.redo.clone())));
|
||||||
// The recorder keeps top-level calls with the place they ran in.
|
// The recorder keeps top-level calls with the place they ran in.
|
||||||
let place = (self.depth == 0 && self.recorder.is_some()).then(|| match self.active() {
|
let place = (self.depth == 0 && self.recorder.is_some()).then(|| match self.active() {
|
||||||
Some(d) => (d.uid, d.wb.active_sheet, d.wb.active().map(|sh| sh.name.clone()).unwrap_or_default(), d.selection.clone()),
|
Some(d) => (d.uid, d.wb.active_sheet, d.wb.active().map(|sh| sh.name.clone()).unwrap_or_default(), d.selection.clone()),
|
||||||
@@ -562,10 +563,8 @@ impl Session {
|
|||||||
{
|
{
|
||||||
d.wb = wb.clone();
|
d.wb = wb.clone();
|
||||||
d.selection = sel.clone();
|
d.selection = sel.clone();
|
||||||
if let Some((_, len)) = start {
|
if let Some((undo, redo)) = history_before {
|
||||||
d.undo.truncate(len);
|
d.undo = undo;
|
||||||
}
|
|
||||||
if let Some(redo) = redo_before {
|
|
||||||
d.redo = redo;
|
d.redo = redo;
|
||||||
}
|
}
|
||||||
d.calc.rebuild(&d.wb);
|
d.calc.rebuild(&d.wb);
|
||||||
|
|||||||
@@ -563,6 +563,20 @@ fn a_command_that_panics_leaves_the_history_as_it_found_it() {
|
|||||||
assert_eq!(s.doc().unwrap().redo.len(), 1, "the redo history is back");
|
assert_eq!(s.doc().unwrap().redo.len(), 1, "the redo history is back");
|
||||||
s.execute("edit.redo", json!({})).unwrap();
|
s.execute("edit.redo", json!({})).unwrap();
|
||||||
assert_eq!(v(&s, "A1").display(), "2");
|
assert_eq!(v(&s, "A1").display(), "2");
|
||||||
|
|
||||||
|
// A command that undoes through a nested command and then panics: the entry Undo removed
|
||||||
|
// comes back, and the redo entry it made goes.
|
||||||
|
crate::cmd::register_undoable_test_command("test.undoThenPanic", |s, _| {
|
||||||
|
s.execute("edit.undo", json!({}))?;
|
||||||
|
panic!("after an undo");
|
||||||
|
});
|
||||||
|
assert_eq!((undo_labels(&s).len(), s.doc().unwrap().redo.len()), (2, 0));
|
||||||
|
assert!(s.execute("test.undoThenPanic", json!({})).is_err());
|
||||||
|
assert_eq!(v(&s, "A1").display(), "2", "the workbook is restored");
|
||||||
|
assert_eq!(undo_labels(&s), ["Enter Cell", "Enter Cell"], "the undone step is back");
|
||||||
|
assert_eq!(s.doc().unwrap().redo.len(), 0);
|
||||||
|
s.execute("edit.undo", json!({})).unwrap();
|
||||||
|
assert_eq!(v(&s, "A1").display(), "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------- recording buffer
|
// ---------------------------------------------------------------- recording buffer
|
||||||
|
|||||||
Reference in New Issue
Block a user