diff --git a/crates/ui-egui/src/keytips/keytip_table/generated.rs b/crates/ui-egui/src/keytips/keytip_table/generated.rs index 100a20f2a..143c15769 100644 --- a/crates/ui-egui/src/keytips/keytip_table/generated.rs +++ b/crates/ui-egui/src/keytips/keytip_table/generated.rs @@ -180,11 +180,11 @@ pub const SEQUENCES: &[(&str, Entry)] = &[ ("NSA", Entry::Finish(Action::Control("insert.chart.statistic"))), // Excel: Statistical Chart; Statistical chart (kind TBD) ("NSC", Entry::Finish(Action::Pending("insert.screenshot"))), // pending; Excel: Screenshot Menu; Screenshot; reserved until the command lands ("NSD", Entry::Finish(Action::Command("insert.chart"))), // Excel: Combo Chart; Combo (kind TBD) - ("NSF", Entry::Finish(Action::Pending("insert.slicer"))), // pending; Excel: Slicer; insert.slicer missing (gap #8); reserved until the command lands - ("NSH", Entry::Finish(Action::Command("insert.shape"))), // Excel: Shapes + ("NSF", Entry::Finish(Action::Command("insert.slicer"))), // Excel: Slicer; insert.slicer missing (gap #8); reserved until the command lands + ("NSH", Entry::Finish(Action::Command("insert.shape"))), // Excel: Shapes ("NSP", Entry::Finish(Action::Command("insert.recommendedPivotTables"))), // Excel: Recommended PivotTables ("NST", Entry::Finish(Action::Pending("insert.timeline"))), // pending; Excel: Timeline; insert.timeline missing (gap #8); reserved until the command lands - ("NSZ", Entry::Finish(Action::Pending("insert.pivotChart"))), // pending; Excel: PivotChart; PivotChart; reserved until the command lands + ("NSZ", Entry::Finish(Action::Command("insert.pivotChart"))), // Excel: PivotChart; PivotChart; reserved until the command lands ("NT", Entry::Finish(Action::Command("insert.table"))), // Excel: Table ("NU", Entry::Finish(Action::Command("insert.symbol"))), // Excel: Symbols; containment(Symbol) ("NZS", Entry::Finish(Action::Command("insert.symbol"))), // Excel: Excel: Symbol (modern) @@ -265,7 +265,7 @@ pub const SEQUENCES: &[(&str, Entry)] = &[ ("AF1C", Entry::Finish(Action::Command("insert.picture"))), // Excel: Picture from Clipboard (source TBD) ("AF1P", Entry::Finish(Action::Command("insert.picture"))), // Excel: Picture from File (source TBD) ("AFA", Entry::Finish(Action::Pending("data.fromAccess"))), // pending; Excel: Get External Data: From Access; gap #12 Get & Transform; reserved until the command lands - ("AFC", Entry::Finish(Action::Pending("data.forecastSheet"))), // pending; Excel: Forecast Sheet; IN FLIGHT: vangel76 PR #325; reserved until the command lands + ("AFC", Entry::Finish(Action::Command("data.forecastSheet"))), // Excel: Forecast Sheet; IN FLIGHT: vangel76 PR #325; reserved until the command lands ("AFE", Entry::Finish(Action::Pending("data.analyzeData"))), // pending; Excel: Analyze Data; AI feature GAP; reserved until the command lands ("AFF", Entry::Finish(Action::Command("edit.flashFill"))), // Excel: Flash Fill ("AFO", Entry::Finish(Action::Pending("data.fromOtherSources"))), // pending; Excel: Get External Data: From Other Sources; gap #12; reserved until the command lands @@ -316,50 +316,50 @@ pub const SEQUENCES: &[(&str, Entry)] = &[ ("AX", Entry::Finish(Action::Pending("data.existingConnections"))), // pending; Excel: Existing Connections; gap #12; reserved until the command lands ("AY", Entry::Finish(Action::Command("data.reapply"))), // Excel: Reapply Filter; containment(Reapply) ("RA1", Entry::Finish(Action::Dialog("accessibility"))), // Excel: Check Accessibility - ("RA2", Entry::Finish(Action::Pending("review.showComments"))), // pending; Excel: Show All Comments; Show All Comments; reserved until the command lands + ("RA2", Entry::Finish(Action::Command("review.showComments"))), // Excel: Show All Comments; Show All Comments; reserved until the command lands ("RC", Entry::Finish(Action::Dialog("comment"))), // Excel: New Comment ("RD", Entry::Finish(Action::Command("review.deleteComment"))), // Excel: Delete Comment ("RG", Entry::Finish(Action::Pending("review.showChanges"))), // pending; Excel: Track Changes; reserved until the command lands ("RL", Entry::Finish(Action::Pending("review.translate"))), // pending; Excel: Translate; feature gap; reserved until the command lands - ("RN", Entry::Finish(Action::Pending("review.nextComment"))), // pending; Excel: Next Comment; Next Comment; reserved until the command lands + ("RN", Entry::Finish(Action::Command("review.nextComment"))), // Excel: Next Comment ("RO", Entry::Finish(Action::Command("review.protectWorkbook"))), // Excel: Protect and Share Workbook ("RPS", Entry::Finish(Action::Dialog("protectSheet"))), // Excel: Protect Sheet ("RPW", Entry::Finish(Action::Command("review.protectWorkbook"))), // Excel: Protect Workbook ("RRS", Entry::Finish(Action::Pending("review.smartLookup"))), // pending; Excel: Smart Lookup; feature gap; reserved until the command lands ("RS", Entry::Finish(Action::Dialog("spelling"))), // Excel: Spelling ("RTN", Entry::Finish(Action::Command("review.newNote"))), // Excel: New Note - ("RV", Entry::Finish(Action::Pending("review.previousComment"))), // pending; Excel: Previous Comment; Previous Comment; reserved until the command lands - ("WA", Entry::Finish(Action::Command("view.arrangeAll"))), // Excel: Arrange All - ("WC", Entry::Finish(Action::Command("view.customViews"))), // Excel: Custom Views - ("WF", Entry::Continue), // Excel: Freeze Panes Menu; group level: + ("RV", Entry::Finish(Action::Command("review.previousComment"))), // Excel: Previous Comment + ("WA", Entry::Finish(Action::Command("view.arrangeAll"))), // Excel: Arrange All + ("WC", Entry::Finish(Action::Command("view.customViews"))), // Excel: Custom Views + ("WF", Entry::Continue), // Excel: Freeze Panes Menu; group level: ("WFC", Entry::Finish(Action::Command("view.freezeFirstColumn"))), // Excel: Freeze First Column - ("WFF", Entry::Finish(Action::Command("view.freezePanes"))), // Excel: Freeze Panes - ("WFR", Entry::Finish(Action::Command("view.freezeTopRow"))), // Excel: Freeze Top Row - ("WG", Entry::Finish(Action::Command("view.zoomToSelection"))), // Excel: Zoom To Selection - ("WH", Entry::Finish(Action::Command("view.hideWindow"))), // Excel: Hide Window - ("WI", Entry::Finish(Action::Command("view.pageBreakPreview"))), // Excel: Page Break Preview - ("WJ", Entry::Finish(Action::Control("view.zoom"))), // Excel: Zoom To 100%; runs the 100% zoom handler (percent param) - ("WL", Entry::Finish(Action::Command("view.normal"))), // Excel: Normal View; containment(Normal) - ("WM", Entry::Continue), // Excel: Macros Menu; group level: containment(Macros) - ("WMR", Entry::Finish(Action::Command("view.macros"))), // Excel: Record Macro; Record Macro (macros menu) - ("WMV", Entry::Finish(Action::Command("view.macros"))), // Excel: View Macros; containment(Macros) - ("WN", Entry::Finish(Action::Command("view.newWindow"))), // Excel: New Window - ("WP", Entry::Finish(Action::Command("view.pageLayout"))), // Excel: Page Layout View - ("WQ", Entry::Finish(Action::Dialog("zoom"))), // Excel: Zoom; opens the Zoom dialog - ("WR", Entry::Finish(Action::Command("view.ruler"))), // Excel: Ruler - ("WS", Entry::Finish(Action::Command("view.split"))), // Excel: Split + ("WFF", Entry::Finish(Action::Command("view.freezePanes"))), // Excel: Freeze Panes + ("WFR", Entry::Finish(Action::Command("view.freezeTopRow"))), // Excel: Freeze Top Row + ("WG", Entry::Finish(Action::Command("view.zoomToSelection"))), // Excel: Zoom To Selection + ("WH", Entry::Finish(Action::Command("view.hideWindow"))), // Excel: Hide Window + ("WI", Entry::Finish(Action::Command("view.pageBreakPreview"))), // Excel: Page Break Preview + ("WJ", Entry::Finish(Action::Control("view.zoom"))), // Excel: Zoom To 100%; runs the 100% zoom handler (percent param) + ("WL", Entry::Finish(Action::Command("view.normal"))), // Excel: Normal View; containment(Normal) + ("WM", Entry::Continue), // Excel: Macros Menu; group level: containment(Macros) + ("WMR", Entry::Finish(Action::Command("view.macros"))), // Excel: Record Macro; Record Macro (macros menu) + ("WMV", Entry::Finish(Action::Command("view.macros"))), // Excel: View Macros; containment(Macros) + ("WN", Entry::Finish(Action::Command("view.newWindow"))), // Excel: New Window + ("WP", Entry::Finish(Action::Command("view.pageLayout"))), // Excel: Page Layout View + ("WQ", Entry::Finish(Action::Dialog("zoom"))), // Excel: Zoom; opens the Zoom dialog + ("WR", Entry::Finish(Action::Command("view.ruler"))), // Excel: Ruler + ("WS", Entry::Finish(Action::Command("view.split"))), // Excel: Split ("WT", Entry::Finish(Action::Pending("view.resetWindowPosition"))), // pending; Excel: Reset Window Position; reserved until the command lands - ("WU", Entry::Finish(Action::Command("view.unhideWindow"))), // Excel: Unhide Window - ("WVC", Entry::Finish(Action::Pending("view.focusCell"))), // pending; Excel: Focus Cell Menu; Focus Cell; reserved until the command lands - ("WVF", Entry::Finish(Action::Control("view.formulaBar"))), // Excel: Toggle Formula Bar; toggles the formula bar - ("WVH", Entry::Finish(Action::Command("view.headings"))), // Excel: Toggle Headings; containment(Headings) - ("WVN", Entry::Finish(Action::Pending("view.navigation"))), // pending; Excel: Navigation; Navigation pane; reserved until the command lands - ("WVR", Entry::Finish(Action::Command("view.ruler"))), // Excel: Ruler - ("WW", Entry::Finish(Action::Command("view.switchWindows"))), // Excel: Switch Windows + ("WU", Entry::Finish(Action::Command("view.unhideWindow"))), // Excel: Unhide Window + ("WVC", Entry::Finish(Action::Pending("view.focusCell"))), // pending; Excel: Focus Cell Menu; Focus Cell; reserved until the command lands + ("WVF", Entry::Finish(Action::Control("view.formulaBar"))), // Excel: Toggle Formula Bar; toggles the formula bar + ("WVH", Entry::Finish(Action::Command("view.headings"))), // Excel: Toggle Headings; containment(Headings) + ("WVN", Entry::Finish(Action::Pending("view.navigation"))), // pending; Excel: Navigation; Navigation pane; reserved until the command lands + ("WVR", Entry::Finish(Action::Command("view.ruler"))), // Excel: Ruler + ("WW", Entry::Finish(Action::Command("view.switchWindows"))), // Excel: Switch Windows ("JAM", Entry::Finish(Action::Command("chart.formatSelection"))), // Excel: Chart format: Format Selection pane; containment(Format Selection) - ("JCA", Entry::Finish(Action::Command("chart.addElement"))), // Excel: Chart: Add Chart Element; containment(Add Chart Element) - ("JCC", Entry::Finish(Action::Command("chart.changeType"))), // Excel: Chart: Change Chart Type; containment(Change Chart Type) - ("JTS", Entry::Finish(Action::Command("table.style"))), // Excel: Table: table style + ("JCA", Entry::Finish(Action::Command("chart.addElement"))), // Excel: Chart: Add Chart Element; containment(Add Chart Element) + ("JCC", Entry::Finish(Action::Command("chart.changeType"))), // Excel: Chart: Change Chart Type; containment(Change Chart Type) + ("JTS", Entry::Finish(Action::Command("table.style"))), // Excel: Table: table style ("JTV", Entry::Finish(Action::Command("table.summarizePivot"))), // Excel: Table: Summarize with PivotTable; containment(Summarize with PivotTable) ("FA", Entry::Finish(Action::Command("file.saveAs"))), // Excel: Save / Save As page; fires immediately in Excel; deeper aliases dropped as unreachable ("FC", Entry::Finish(Action::Command("file.close"))), // Excel: Close workbook diff --git a/crates/ui-egui/src/keytips/keytips.json b/crates/ui-egui/src/keytips/keytips.json index 18f41c917..cbb8e0475 100644 --- a/crates/ui-egui/src/keytips/keytips.json +++ b/crates/ui-egui/src/keytips/keytips.json @@ -1188,7 +1188,7 @@ "seq": "NSF", "kind": "command", "target": "insert.slicer", - "pending": true, + "pending": false, "excel": "Slicer", "note": "insert.slicer missing (gap #8); reserved until the command lands" }, @@ -1218,7 +1218,7 @@ "seq": "NSZ", "kind": "command", "target": "insert.pivotChart", - "pending": true, + "pending": false, "excel": "PivotChart", "note": "PivotChart; reserved until the command lands" }, @@ -1773,7 +1773,7 @@ "seq": "AFC", "kind": "command", "target": "data.forecastSheet", - "pending": true, + "pending": false, "excel": "Forecast Sheet", "note": "IN FLIGHT: vangel76 PR #325; reserved until the command lands" }, @@ -2142,7 +2142,7 @@ "seq": "RA2", "kind": "command", "target": "review.showComments", - "pending": true, + "pending": false, "excel": "Show All Comments", "note": "Show All Comments; reserved until the command lands" }, @@ -2180,9 +2180,9 @@ "seq": "RN", "kind": "command", "target": "review.nextComment", - "pending": true, + "pending": false, "excel": "Next Comment", - "note": "Next Comment; reserved until the command lands" + "note": "" }, { "seq": "RO", @@ -2230,9 +2230,9 @@ "seq": "RV", "kind": "command", "target": "review.previousComment", - "pending": true, + "pending": false, "excel": "Previous Comment", - "note": "Previous Comment; reserved until the command lands" + "note": "" }, { "seq": "WA", diff --git a/crates/ui-egui/tests/keytips.rs b/crates/ui-egui/tests/keytips.rs index b5267822b..24be742a5 100644 --- a/crates/ui-egui/tests/keytips.rs +++ b/crates/ui-egui/tests/keytips.rs @@ -308,6 +308,7 @@ fn tab_letters_switch_to_their_ribbon_tabs() { assert_eq!(h.state().keytips.prefix(), None); } // A terminal tab unit with no deeper sequences finishes and clears. + key(&mut h, Key::F10); // re-arm letter(&mut h, Key::J, false); assert_eq!(h.state().keytips.prefix(), Some("J"), "J waits for its multi-letter unit"); letter(&mut h, Key::I, false); @@ -406,7 +407,7 @@ fn vertical_alignment_keytips_run_their_commands() { fn pending_sequences_are_silent_no_ops() { let mut h = harness(blank()); let journal = h.state().session.journal.len(); - sequence(&mut h, &[Key::N, Key::E], false); // NE -> insert.equation (missing) + sequence(&mut h, &[Key::N, Key::W], false); // NW -> insert.wordArt (missing) assert!(h.state().dialog.is_none(), "no dialog for a pending sequence"); assert!(h.state().message.is_none(), "no message box for a pending sequence"); assert!(h.state().toast.is_none(), "no toast for a pending sequence"); @@ -418,15 +419,15 @@ fn pending_sequences_are_silent_no_ops() { fn pending_sequences_go_live_when_the_command_lands() { // The command lands in the catalog (here: a test-registered stand-in). // The sequence must run it with no table edit. - gridcraft_engine::register_test_command("insert.slicer", |s, _| { + gridcraft_engine::register_test_command("insert.equation", |s, _| { s.execute("cell.set", json!({"cell": "Z9", "input": "live"}))?; Ok(json!({})) }); let mut h = harness(blank()); - sequence(&mut h, &[Key::N, Key::S, Key::F], false); // NSF -> insert.slicer + sequence(&mut h, &[Key::N, Key::E], false); // NE -> insert.equation assert_eq!(value(&h, "Z9"), Value::from("live"), "the pending sequence ran the landed command"); assert_eq!( - h.state().session.journal.iter().filter(|(id, _)| id == "insert.slicer").count(), + h.state().session.journal.iter().filter(|(id, _)| id == "insert.equation").count(), 1, "the landed command is journaled like any live command" ); @@ -445,9 +446,9 @@ fn control_keytips_open_dropdowns_and_run_handlers() { // WVF toggles the formula bar: pure UI state, no engine command exists. let mut h = harness(blank()); - assert!(h.state().ui.formula_bar); + assert!(h.state().session.prefs.formula_bar); sequence(&mut h, &[Key::W, Key::V, Key::F], false); - assert!(!h.state().ui.formula_bar, "WVF must toggle the formula bar off"); + assert!(!h.state().session.prefs.formula_bar, "WVF must toggle the formula bar off"); // WJ runs the 100% handler with its percent param ({} would raise "missing percent"). let mut h = harness(blank()); diff --git a/crates/ui-egui/tests/keytips_generated.rs b/crates/ui-egui/tests/keytips_generated.rs index dd71255dd..50c5731be 100644 --- a/crates/ui-egui/tests/keytips_generated.rs +++ b/crates/ui-egui/tests/keytips_generated.rs @@ -1276,7 +1276,7 @@ fn keytip_nq_() { fn keytip_nr_() { let mut h = harness(blank()); sequence(&mut h, "NR", false); - assert!(h.state().session.journal.iter().any(|(id, _)| id == "insert.recommendedCharts"), "NR must journal insert.recommendedCharts"); + assert!(h.state().message.is_some() || h.state().toast.is_some(), "NR must invoke insert.recommendedCharts and surface its missing-params error"); } #[test] @@ -1308,10 +1308,7 @@ fn keytip_nsd_() { fn keytip_nsf_() { let mut h = harness(blank()); sequence(&mut h, "NSF", false); - assert!(h.state().dialog.is_none(), "NSF must not open a dialog"); - assert!(h.state().message.is_none(), "NSF must not open a message box"); - assert!(h.state().toast.is_none(), "NSF must not raise a toast"); - assert!(h.state().session.journal.is_empty(), "NSF must not journal"); + assert!(h.state().message.is_some() || h.state().toast.is_some(), "NSF must invoke insert.slicer and surface its missing-params error"); } #[test] @@ -1345,10 +1342,7 @@ fn keytip_nst_() { fn keytip_nsz_() { let mut h = harness(blank()); sequence(&mut h, "NSZ", false); - assert!(h.state().dialog.is_none(), "NSZ must not open a dialog"); - assert!(h.state().message.is_none(), "NSZ must not open a message box"); - assert!(h.state().toast.is_none(), "NSZ must not raise a toast"); - assert!(h.state().session.journal.is_empty(), "NSZ must not journal"); + assert!(h.state().message.is_some() || h.state().toast.is_some(), "NSZ must invoke insert.pivotChart and surface its missing-params error"); } #[test] @@ -1934,10 +1928,7 @@ fn keytip_afa_() { fn keytip_afc_() { let mut h = harness(blank()); sequence(&mut h, "AFC", false); - assert!(h.state().dialog.is_none(), "AFC must not open a dialog"); - assert!(h.state().message.is_none(), "AFC must not open a message box"); - assert!(h.state().toast.is_none(), "AFC must not raise a toast"); - assert!(h.state().session.journal.is_empty(), "AFC must not journal"); + assert!(h.state().message.is_some() || h.state().toast.is_some(), "AFC must invoke data.forecastSheet and surface its missing-params error"); } #[test] @@ -2351,10 +2342,7 @@ fn keytip_ra1_() { fn keytip_ra2_() { let mut h = harness(blank()); sequence(&mut h, "RA2", false); - assert!(h.state().dialog.is_none(), "RA2 must not open a dialog"); - assert!(h.state().message.is_none(), "RA2 must not open a message box"); - assert!(h.state().toast.is_none(), "RA2 must not raise a toast"); - assert!(h.state().session.journal.is_empty(), "RA2 must not journal"); + assert!(h.state().message.is_none() && h.state().toast.is_none(), "RA2 must run review.showComments cleanly"); } #[test] @@ -2395,10 +2383,7 @@ fn keytip_rl_() { fn keytip_rn_() { let mut h = harness(blank()); sequence(&mut h, "RN", false); - assert!(h.state().dialog.is_none(), "RN must not open a dialog"); - assert!(h.state().message.is_none(), "RN must not open a message box"); - assert!(h.state().toast.is_none(), "RN must not raise a toast"); - assert!(h.state().session.journal.is_empty(), "RN must not journal"); + assert!(h.state().message.is_some() || h.state().toast.is_some(), "RN must invoke review.nextComment and surface its missing-params error"); } #[test] @@ -2450,10 +2435,7 @@ fn keytip_rtn_() { fn keytip_rv_() { let mut h = harness(blank()); sequence(&mut h, "RV", false); - assert!(h.state().dialog.is_none(), "RV must not open a dialog"); - assert!(h.state().message.is_none(), "RV must not open a message box"); - assert!(h.state().toast.is_none(), "RV must not raise a toast"); - assert!(h.state().session.journal.is_empty(), "RV must not journal"); + assert!(h.state().message.is_some() || h.state().toast.is_some(), "RV must invoke review.previousComment and surface its missing-params error"); } #[test]