From 3d6a09ec758e37b0ba684bc9b6062013b29601da Mon Sep 17 00:00:00 2001 From: prxnvt <53838599+prxnvt@users.noreply.github.com> Date: Thu, 22 Oct 2026 02:04:01 -0400 Subject: [PATCH] UI: a reference box stops picking when a macro action starts, and debugging never fills one A reference box that had focus kept picking from the grid while Check, Run or a debugger action ran. The selections those make landed in the box and dirtied the draft, and a later Check could save that draft. The pick now ends when an action starts, and while a debug run is active a selection on the grid is never taken as a pick. Also: the parity assessment said an .xlsm's VBA project is dropped on open; it is kept unchanged on save and never run. --- crates/ui-egui/src/macro_editor.rs | 9 +++++-- crates/ui-egui/tests/it/macro_editor.rs | 34 +++++++++++++++++++++++++ docs/target-app-parity.md | 2 +- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/crates/ui-egui/src/macro_editor.rs b/crates/ui-egui/src/macro_editor.rs index 8c3cf76db..955cb45f6 100644 --- a/crates/ui-egui/src/macro_editor.rs +++ b/crates/ui-egui/src/macro_editor.rs @@ -563,6 +563,8 @@ fn error_step(msg: &str) -> Option<(String, String)> { /// Check: validates the inputs and dry-runs the macro; the grid shows what it would touch. pub fn check(app: &mut SheetApp, ed: &mut Editor) { + // A reference box picking from the grid would take the selections the action makes. + ed.refs.pick = None; if !ensure_saved(app, ed) { return; } @@ -613,6 +615,7 @@ fn check_text(v: &Json) -> String { /// Run: runs the saved macro as one undo step. pub fn run(app: &mut SheetApp, ed: &mut Editor) { + ed.refs.pick = None; if !ensure_saved(app, ed) { return; } @@ -649,6 +652,7 @@ fn with(mut base: Json, extra: Json) -> Json { /// Step, Continue or Run to Here: starts debugging if needed (paused before step 1), then acts. pub fn debug_action(app: &mut SheetApp, ed: &mut Editor, action: &str) { + ed.refs.pick = None; let debugging = app.session.macro_debug.is_some(); // Starting selects the first step: take Run to Here's target before that. let target = ed.selected.clone().filter(|s| split_path(s).is_some()); @@ -840,8 +844,9 @@ fn ref_edit(app: &SheetApp, ui: &mut Ui, d: &mut Dialog, refs: &mut RefPick, key let r = ui.add(egui::TextEdit::singleline(&mut s).desired_width(width - 30.0).id_salt(("refedit", key))); if r.gained_focus() || (r.clicked() && !picking) { begin_pick(app, refs, key); - } else if picking && !r.has_focus() && sel != refs.seen { - // A selection made on the grid becomes the reference. + } else if picking && !r.has_focus() && sel != refs.seen && app.session.macro_debug.is_none() { + // A selection made on the grid becomes the reference; while debugging, the selection + // follows the steps and is not a pick. s = sel.clone(); refs.seen = sel; } diff --git a/crates/ui-egui/tests/it/macro_editor.rs b/crates/ui-egui/tests/it/macro_editor.rs index c302f9bb4..52e116f89 100644 --- a/crates/ui-egui/tests/it/macro_editor.rs +++ b/crates/ui-egui/tests/it/macro_editor.rs @@ -162,6 +162,40 @@ fn run_to_here_then_stop_asks_whether_to_keep_the_changes() { } } +#[test] +fn debugging_never_writes_the_selection_into_a_reference_box() { + // A reference box that was picking from the grid stays out of it once an action starts, and + // the selections the debugger makes while it runs never land in a box or dirty the draft. + let mut h = harness(); + three(&mut h); + click(&mut h, "Step 3: Set A3 to A3"); + // The step's Cell box is picking, with the selection it last saw (A1). + let pick = |h: &mut Harness| { + let refs = &mut h.state_mut().macros.editor.as_mut().unwrap().refs; + refs.pick = Some("ref:3:cell".into()); + refs.seen = "$A$1".into(); + }; + pick(&mut h); + h.run_steps(2); + assert_eq!(draft_cells(&h), ["A1", "A2", "A3"]); + click(&mut h, "Run to Here"); + assert!(h.state().session.macro_debug.is_some()); + let ed = h.state().macros.editor.as_ref().unwrap(); + assert!(ed.refs.pick.is_none(), "the action ends the pick"); + assert!(!ed.dirty); + // A box focused while debugging does not take the selection either. + pick(&mut h); + h.state_mut().run("selection.set", json!({"range": "F9"})).unwrap(); + h.run_steps(3); + let ed = h.state().macros.editor.as_ref().unwrap(); + assert!(!ed.dirty, "the draft stays clean"); + assert_eq!(draft_cells(&h), ["A1", "A2", "A3"]); + h.state_mut().macros.editor.as_mut().unwrap().refs.pick = None; + click(&mut h, "Stop"); + click(&mut h, "Undo Changes"); + assert!(h.state().session.macro_debug.is_none()); +} + #[test] fn step_into_from_the_macros_dialog_pauses_before_the_first_step() { let mut h = harness(); diff --git a/docs/target-app-parity.md b/docs/target-app-parity.md index 015bf69f0..18286ce52 100644 --- a/docs/target-app-parity.md +++ b/docs/target-app-parity.md @@ -93,7 +93,7 @@ performance 8, stability 8, localization 4, hardware 2, platforms 2, ecosystem 2 | Get & Transform, external data, data model | 5 | ~15% | ~10% | 60–100 | Import of CSV/TSV, JSON, HTML. No Power Query editor, no From Web, database or folder sources, no connections or refresh, no relationships or data model, no external workbook links (dropped with a warning) | | Insert objects | 3 | ~55% | ~45% | 25–40 | Pictures, 8 shape kinds (Excel has ~170), text boxes, own icon set, ink with Ink to Shape, hyperlinks, checkboxes. Missing: SmartArt, WordArt, equations, signature line, objects, 3-D models, screenshot, pictures in cells (PR #105) | | Review, comments, protection, collaboration | 4 | ~55% | ~40% | 35–55 | Threaded comments, notes, spelling (system dictionary), thesaurus, sheet and workbook protection, Allow Edit Ranges with Excel-compatible password hashes (#307). Missing: comment navigation, Show Changes, notes-to-comments conversion, accessibility checker, co-authoring, opening password-encrypted files (refused with a message since #17) | -| Automation | 4 | ~30% | ~20% | 12–20 | Recorded, editable GridCraft scripts (Automate tab). Typed macros in the engine (`macro.*`: recorder, runner with input checks and a footprint dry run, debugger; [macros.md](macros.md)), recorded from Automate › Macros, edited and debugged in a step editor, and run from the Macros dialog or a Ctrl+Shift shortcut. VBA is out of scope by owner decision and is **dropped** when an `.xlsm` is opened (warning shown). No Office Scripts compatibility | +| Automation | 4 | ~30% | ~20% | 12–20 | Recorded, editable GridCraft scripts (Automate tab). Typed macros in the engine (`macro.*`: recorder, runner with input checks and a footprint dry run, debugger; [macros.md](macros.md)), recorded from Automate › Macros, edited and debugged in a step editor, and run from the Macros dialog or a Ctrl+Shift shortcut. VBA is out of scope by owner decision: an `.xlsm` keeps its VBA project unchanged on save and never runs it. No Office Scripts compatibility | | **Weighted** | 100 | **~75%** | **~59%** | **300–485** | | ## Dimensions