From eb7b2b93f48f5e2f28a403917818f288ea0a4f32 Mon Sep 17 00:00:00 2001 From: prxnvt <53838599+prxnvt@users.noreply.github.com> Date: Wed, 21 Oct 2026 15:20:48 -0400 Subject: [PATCH] UI: the macro editor remembers a rename even when the save after it fails Save renames the stored macro first and then saves the draft. When the save failed (a draft too large to keep in the workbook, say), saved_as still held the old name, so every later Save, Check, Run and debug start tried to rename a macro that no longer existed. saved_as now takes the new name as soon as the rename succeeds. --- crates/ui-egui/src/macro_editor.rs | 9 ++++++--- crates/ui-egui/tests/it/macro_editor.rs | 27 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/crates/ui-egui/src/macro_editor.rs b/crates/ui-egui/src/macro_editor.rs index c5c30e85b..40d6118a4 100644 --- a/crates/ui-egui/src/macro_editor.rs +++ b/crates/ui-egui/src/macro_editor.rs @@ -517,10 +517,13 @@ pub fn save(app: &mut SheetApp, ed: &mut Editor) -> bool { } if let Some(old) = ed.saved_as.clone() && !old.eq_ignore_ascii_case(&ed.draft.name) - && let Err(e) = app.run("macro.rename", json!({"name": old, "to": ed.draft.name})) { - app.message = Some(("Save Macro".into(), crate::clean_error(&e))); - return false; + if let Err(e) = app.run("macro.rename", json!({"name": old, "to": ed.draft.name})) { + app.message = Some(("Save Macro".into(), crate::clean_error(&e))); + return false; + } + // The workbook has it under the new name now, even if the save below fails. + ed.saved_as = Some(ed.draft.name.clone()); } // A new draft never replaces a macro that has its name. let replace = ed.saved_as.is_some(); diff --git a/crates/ui-egui/tests/it/macro_editor.rs b/crates/ui-egui/tests/it/macro_editor.rs index 8effcfd09..8e7db5206 100644 --- a/crates/ui-egui/tests/it/macro_editor.rs +++ b/crates/ui-egui/tests/it/macro_editor.rs @@ -242,3 +242,30 @@ fn a_new_macro_never_replaces_one_with_its_name() { h.run_steps(2); } } + +#[test] +fn a_rename_that_lands_before_a_failed_save_is_remembered() { + let mut h = harness(); + three(&mut h); + let big = "x".repeat(5 * 1024 * 1024); + { + let ed = h.state_mut().macros.editor.as_mut().unwrap(); + ed.draft.name = "Renamed".into(); + // Too large to keep in the workbook: the rename lands, the save after it fails. + ed.draft.steps.push(gridcraft_engine::model::Step::command("cell.set", json!({"cell": "A4", "input": big}))); + ed.dirty = true; + } + h.run_steps(2); + click(&mut h, "Save"); + let msg = h.state_mut().message.take().map(|(_, m)| m).unwrap_or_default(); + assert!(msg.contains("too large"), "{msg}"); + assert_eq!(h.state().macros.editor.as_ref().unwrap().saved_as.as_deref(), Some("Renamed")); + // Trimmed back, the next Save works. + h.state_mut().macros.editor.as_mut().unwrap().draft.steps.pop(); + h.run_steps(2); + click(&mut h, "Save"); + assert!(h.state_mut().message.take().is_none()); + let wb = &h.state().session.active().unwrap().wb; + assert_eq!(wb.macros.len(), 1); + assert_eq!((wb.macros[0].name.as_str(), wb.macros[0].steps.len()), ("Renamed", 3)); +}