From f11d74ee7ca14de58e75ea236a0623194d1794f0 Mon Sep 17 00:00:00 2001 From: James Date: Sun, 11 Oct 2026 19:53:05 +0300 Subject: [PATCH] Populate the full Excel keytip table (408 sequences, issues #33 and #49) Population of keytips.json from the collected Excel Alt-sequence set: - 408 curated entries: 10 tabs, 354 command binds (64 reserved pending, 290 live catalog commands), 2 dialog openers, 42 group levels. - Bind-all policy: sequences whose command does not exist yet bind to the canonical future id as Action::Pending -- badge shows, invocation is a silent no-op until the command lands (ids from docs/parity-checklist). - Group levels: 46 command entries that are strict prefixes of deeper sequences were demoted to menu openers so the trie never fires early (HV must not paste; it waits for the variant letter). - Fire-immediately restores: HC Copy, HAN Accounting, FA Save As, FO Open, FI Info. Unreachable legacy aliases (HCC, HANM, FA1, FAY3, FOC, FOO, FIP) dropped: the parent fires first. - ES stays a terminal dialog opener as in Excel: the A/F/T/V variants are dialog mnemonics, not trie sequences. - Escape pops one trie level and returns to the armed root at a single letter; keytips.json is the single modifiable source; xtask keytips now emits through rustfmt so --check is byte-stable. - Tests: 99 pass (27 lib + 14 keytips + suite), all 8 CI gates green. --- crates/ui-egui/src/keytips.rs | 12 +- crates/ui-egui/src/keytips/keytip_table.rs | 2 +- .../src/keytips/keytip_table/generated.rs | 392 ++- crates/ui-egui/src/keytips/keytips.json | 2863 ++++++++++++++++- crates/ui-egui/tests/keytips.rs | 7 + xtask/src/keytips.rs | 30 +- 6 files changed, 3276 insertions(+), 30 deletions(-) diff --git a/crates/ui-egui/src/keytips.rs b/crates/ui-egui/src/keytips.rs index 85bb214..51a8793 100644 --- a/crates/ui-egui/src/keytips.rs +++ b/crates/ui-egui/src/keytips.rs @@ -92,10 +92,14 @@ impl KeyTips { } else if self.prefix.is_some() && !matches!(key, Key::ShiftLeft | Key::ShiftRight) { handled = true; if *key == Key::Escape { - if let Some(prefix) = self.prefix.as_mut() - && prefix.pop().is_none() - { - self.prefix = None; + // Escape pops one level; at a single-letter level it + // returns to the armed root (empty prefix). + if let Some(prefix) = self.prefix.as_mut() { + if prefix.is_empty() { + self.prefix = None; + } else { + prefix.pop(); + } } } else if key.name().len() == 1 { let next = format!("{}{key_name}", self.prefix.as_deref().unwrap_or_default(), key_name = key.name()); diff --git a/crates/ui-egui/src/keytips/keytip_table.rs b/crates/ui-egui/src/keytips/keytip_table.rs index 638b6dd..8caa4d6 100644 --- a/crates/ui-egui/src/keytips/keytip_table.rs +++ b/crates/ui-egui/src/keytips/keytip_table.rs @@ -149,7 +149,7 @@ mod tests { #[test] fn item_letter_is_one_level_deep() { assert_eq!(item_letter("HV", "dialog:pasteSpecial"), Some("HVS")); - assert_eq!(item_letter("E", "dialog:pasteSpecial"), Some("ES")); + assert_eq!(item_letter("HV", "edit.pasteSpecial"), Some("HVA")); assert_eq!(item_letter("H", "dialog:pasteSpecial"), None, "the item badge waits for its group letter"); assert_eq!(item_letter("HO", "home.autofitColumnWidth"), Some("HOI")); } diff --git a/crates/ui-egui/src/keytips/keytip_table/generated.rs b/crates/ui-egui/src/keytips/keytip_table/generated.rs index 446cbb2..c078e77 100644 --- a/crates/ui-egui/src/keytips/keytip_table/generated.rs +++ b/crates/ui-egui/src/keytips/keytip_table/generated.rs @@ -20,8 +20,398 @@ pub const SEQUENCES: &[(&str, Entry)] = &[ ("HAL", Entry::Finish(Action::Command("home.alignLeft"))), ("HAC", Entry::Finish(Action::Command("home.alignCenter"))), ("HVS", Entry::Finish(Action::Dialog("pasteSpecial"))), - ("ES", Entry::Finish(Action::Dialog("pasteSpecial"))), // Legacy Edit menu. + ("ES", Entry::Finish(Action::Dialog("pasteSpecial"))), // Excel: Classic Paste Special dialog (legacy Edit route); A/F/T/V are dialog mnemonics ("HOI", Entry::Finish(Action::Command("home.autofitColumnWidth"))), ("OCA", Entry::Finish(Action::Command("home.autofitColumnWidth"))), // Legacy Format menu. ("WVG", Entry::Finish(Action::Command("view.gridlines"))), + ("0", Entry::Finish(Action::Pending("qat.10"))), // pending; Excel: Quick Access Toolbar position 10; QAT navigation does not exist yet + ("1", Entry::Finish(Action::Pending("qat.1"))), // pending; Excel: Quick Access Toolbar position 1; QAT navigation does not exist yet + ("2", Entry::Finish(Action::Pending("qat.2"))), // pending; Excel: Quick Access Toolbar position 2; QAT navigation does not exist yet + ("3", Entry::Finish(Action::Pending("qat.3"))), // pending; Excel: Quick Access Toolbar position 3; QAT navigation does not exist yet + ("4", Entry::Finish(Action::Pending("qat.4"))), // pending; Excel: Quick Access Toolbar position 4; QAT navigation does not exist yet + ("5", Entry::Finish(Action::Pending("qat.5"))), // pending; Excel: Quick Access Toolbar position 5; QAT navigation does not exist yet + ("H0", Entry::Finish(Action::Command("home.increaseDecimal"))), // Excel: Increase Decimals; containment(Increase Decimal) + ("H1", Entry::Finish(Action::Command("home.bold"))), // Excel: Bold + ("H2", Entry::Finish(Action::Command("home.italic"))), // Excel: Italic + ("H3", Entry::Continue), // Excel: Underline Menu; group level: + ("H3D", Entry::Finish(Action::Command("home.doubleUnderline"))), // Excel: Double Underline + ("H3U", Entry::Finish(Action::Command("home.underline"))), // Excel: Underline + ("H5", Entry::Finish(Action::Command("home.decreaseIndent"))), // Excel: Decrease Indent + ("H6", Entry::Finish(Action::Command("home.increaseIndent"))), // Excel: Increase Indent + ("H9", Entry::Finish(Action::Command("home.decreaseDecimal"))), // Excel: Decrease Decimals; containment(Decrease Decimal) + ("HAN", Entry::Finish(Action::Command("home.accounting"))), // Excel: Accounting Format; fires immediately in Excel; deeper aliases dropped as unreachable + ("HAS", Entry::Finish(Action::Command("home.addIns"))), // Excel: Add-ins; containment(Add-ins) + ("HB", Entry::Continue), // Excel: Borders Menu; group level: + ("HBA", Entry::Finish(Action::Command("home.borders"))), // Excel: All Borders; containment(Borders) + ("HBB", Entry::Finish(Action::Command("home.borders"))), // Excel: Bottom Double Border; border-side TBD + ("HBC", Entry::Finish(Action::Command("home.borders"))), // Excel: Top and Thick Bottom Border; border-side TBD + ("HBD", Entry::Finish(Action::Command("home.borders"))), // Excel: Top and Bottom Border; border-side TBD + ("HBE", Entry::Finish(Action::Command("home.borders"))), // Excel: Erase Border; border-side TBD + ("HBG", Entry::Finish(Action::Command("home.drawBorder"))), // Excel: Draw Border Grid; containment(Draw Border) + ("HBH", Entry::Finish(Action::Command("home.borders"))), // Excel: Thick Bottom Border; border-side TBD + ("HBI", Entry::Finish(Action::Command("home.borders"))), // Excel: Line Color; Line Color (submenu TBD) + ("HBL", Entry::Finish(Action::Command("home.borders"))), // Excel: Left Border; border-side TBD + ("HBM", Entry::Finish(Action::Command("home.borders"))), // Excel: More Borders; containment(Borders) + ("HBN", Entry::Finish(Action::Command("home.borders"))), // Excel: No Border; border-side TBD + ("HBO", Entry::Finish(Action::Command("home.borders"))), // Excel: Bottom Border; border-side TBD + ("HBP", Entry::Finish(Action::Command("home.borders"))), // Excel: Top Border; border-side TBD + ("HBR", Entry::Finish(Action::Command("home.borders"))), // Excel: Right Border; border-side TBD + ("HBS", Entry::Finish(Action::Command("home.borders"))), // Excel: Outside Borders; containment(Borders) + ("HBT", Entry::Finish(Action::Command("home.borders"))), // Excel: Thick Outside Borders; border-side TBD + ("HBU", Entry::Finish(Action::Command("home.borders"))), // Excel: Top and Double Bottom Border; border-side TBD + ("HBW", Entry::Finish(Action::Command("home.drawBorder"))), // Excel: Draw Border + ("HBY", Entry::Finish(Action::Command("home.borders"))), // Excel: Line Style; Line Style (submenu TBD) + ("HC", Entry::Finish(Action::Command("edit.copy"))), // Excel: Copy; fires immediately in Excel; deeper aliases dropped as unreachable + ("HCP", Entry::Finish(Action::Pending("home.copyAsPicture"))), // pending; Excel: Copy as Picture; reserved until the command lands + ("HDC", Entry::Finish(Action::Command("home.deleteColumns"))), // Excel: Delete Columns; Delete Columns + ("HDD", Entry::Finish(Action::Command("home.deleteCells"))), // Excel: Delete Cells + ("HDR", Entry::Finish(Action::Command("home.deleteRows"))), // Excel: Delete Rows; Delete Rows + ("HDS", Entry::Finish(Action::Command("home.deleteSheet"))), // Excel: Delete Sheet + ("HEA", Entry::Finish(Action::Command("edit.clearAll"))), // Excel: Clear All + ("HEC", Entry::Finish(Action::Command("edit.clearContents"))), // Excel: Clear Contents + ("HEF", Entry::Finish(Action::Command("edit.clearFormats"))), // Excel: Clear Formats + ("HEL", Entry::Finish(Action::Command("edit.clearHyperlinks"))), // Excel: Clear Hyperlinks + ("HEM", Entry::Finish(Action::Command("edit.clearComments"))), // Excel: Clear Comments and Notes; containment(Clear Comments and Notes) + ("HFC", Entry::Finish(Action::Command("home.fontColor"))), // Excel: Font Color + ("HFDC", Entry::Finish(Action::Command("home.conditionalFormat"))), // Excel: Find Conditional Formatting; containment(Conditional Formatting) + ("HFDF", Entry::Finish(Action::Command("edit.find"))), // Excel: Find + ("HFDG", Entry::Finish(Action::Command("edit.goTo"))), // Excel: Go To + ("HFDM", Entry::Finish(Action::Command("edit.find"))), // Excel: Find Notes; containment(Find) + ("HFDO", Entry::Finish(Action::Pending("home.selectObjects"))), // pending; Excel: Select Objects; Select Objects; reserved until the command lands + ("HFDP", Entry::Finish(Action::Command("arrange.selectionPane"))), // Excel: Selection Pane + ("HFDR", Entry::Finish(Action::Command("edit.replace"))), // Excel: Replace + ("HFDS", Entry::Finish(Action::Command("edit.goToSpecial"))), // Excel: Go To Special + ("HFF", Entry::Finish(Action::Command("home.fontName"))), // Excel: Font Selection + ("HFG", Entry::Finish(Action::Command("home.increaseFontSize"))), // Excel: Increase Font Size + ("HFI", Entry::Continue), // Excel: Fill; group level: containment(Fill Up) + ("HFIA", Entry::Finish(Action::Pending("home.fillAcrossWorksheets"))), // pending; Excel: Fill Across Worksheets; Fill Across Worksheets; reserved until the command lands + ("HFID", Entry::Finish(Action::Command("edit.fillDown"))), // Excel: Fill Down + ("HFIF", Entry::Finish(Action::Command("edit.flashFill"))), // Excel: Flash Fill + ("HFIJ", Entry::Finish(Action::Command("home.justify"))), // Excel: Fill Justify; containment(Justify) + ("HFIL", Entry::Finish(Action::Command("edit.fillLeft"))), // Excel: Fill Left + ("HFIR", Entry::Finish(Action::Command("edit.fillRight"))), // Excel: Fill Right + ("HFIS", Entry::Finish(Action::Command("edit.fillSeries"))), // Excel: Fill Series; containment(Series) + ("HFIU", Entry::Finish(Action::Command("edit.fillUp"))), // Excel: Fill Up + ("HFK", Entry::Finish(Action::Command("home.decreaseFontSize"))), // Excel: Decrease Font Size + ("HFM", Entry::Finish(Action::Command("home.numberFormat"))), // Excel: More Number Formats; containment(Number Format) + ("HFP", Entry::Finish(Action::Command("edit.formatPainter"))), // Excel: Format Painter + ("HFQ", Entry::Continue), // Excel: Orientation Menu; group level: containment(Orientation) + ("HFQL", Entry::Finish(Action::Pending("home.angleClockwise"))), // pending; Excel: Angle Clockwise; Angle Clockwise; reserved until the command lands + ("HFQO", Entry::Finish(Action::Pending("home.angleCounterclockwise"))), // pending; Excel: Angle Counterclockwise; Angle Counterclockwise; reserved until the command lands + ("HFS", Entry::Finish(Action::Command("home.fontSize"))), // Excel: Font Size + ("HH", Entry::Finish(Action::Command("home.fillColor"))), // Excel: Fill Color + ("HIC", Entry::Finish(Action::Command("home.insertColumns"))), // Excel: Insert Columns; Insert Columns + ("HIE", Entry::Finish(Action::Command("home.insertCells"))), // Excel: Insert Copied Cells; Insert Cells (copied cells TBD) + ("HII", Entry::Finish(Action::Command("home.insertCells"))), // Excel: Insert Cells + ("HIR", Entry::Finish(Action::Command("home.insertRows"))), // Excel: Insert Rows; Insert Rows + ("HIS", Entry::Finish(Action::Command("home.insertSheet"))), // Excel: Insert Sheet + ("HJ", Entry::Continue), // Excel: Cell Styles; group level: + ("HJN", Entry::Finish(Action::Command("home.newCellStyle"))), // Excel: New Cell Style + ("HK", Entry::Finish(Action::Command("home.comma"))), // Excel: Comma Style + ("HL", Entry::Continue), // Excel: Conditional Formatting; group level: containment(Conditional Formatting) + ("HLC", Entry::Continue), // Excel: Clear Rules Menu; group level: containment(Clear Rules) + ("HLCE", Entry::Finish(Action::Command("home.clearRules"))), // Excel: Clear Rules From Sheet; containment(Clear Rules) + ("HLCS", Entry::Finish(Action::Command("home.clearRules"))), // Excel: Clear Rules From Cells; containment(Clear Rules) + ("HLCT", Entry::Finish(Action::Command("home.clearRules"))), // Excel: Clear Rules From Table; containment(Clear Rules) + ("HLD", Entry::Finish(Action::Command("home.conditionalFormat"))), // Excel: Data Bars; Data Bars (submenu TBD) + ("HLH", Entry::Finish(Action::Command("home.conditionalFormat"))), // Excel: Highlight Cells; Highlight Cells (submenu TBD) + ("HLN", Entry::Finish(Action::Command("home.conditionalFormat"))), // Excel: New Rule; New Rule (submenu TBD) + ("HLR", Entry::Finish(Action::Command("home.manageRules"))), // Excel: Manage Rules; containment(Manage Rules) + ("HLT", Entry::Finish(Action::Command("home.conditionalFormat"))), // Excel: Top/Bottom Rules; Top/Bottom (submenu TBD) + ("HM", Entry::Continue), // Excel: Merge & Center Menu; group level: containment(Merge & Center) + ("HMA", Entry::Finish(Action::Command("home.mergeAcross"))), // Excel: Merge Across + ("HMC", Entry::Finish(Action::Command("home.mergeCenter"))), // Excel: Merge & Center + ("HMM", Entry::Finish(Action::Command("home.mergeCells"))), // Excel: Merge Cells + ("HMU", Entry::Finish(Action::Command("home.unmergeCells"))), // Excel: Unmerge Cells + ("HN", Entry::Finish(Action::Command("home.numberFormat"))), // Excel: Number Format + ("HOA", Entry::Finish(Action::Command("home.autofitRowHeight"))), // Excel: AutoFit Row Height + ("HOD", Entry::Finish(Action::Command("home.columnWidth"))), // Excel: Default Column Width; containment(Column Width) + ("HOE", Entry::Finish(Action::Command("home.formatCells"))), // Excel: Format Cells + ("HOH", Entry::Finish(Action::Command("home.rowHeight"))), // Excel: Row Height + ("HOL", Entry::Finish(Action::Command("home.lockCell"))), // Excel: Lock Cell; containment(Lock Cell) + ("HOM", Entry::Finish(Action::Command("sheet.move"))), // Excel: Move or Copy Sheet + ("HOP", Entry::Finish(Action::Command("review.protectSheet"))), // Excel: Protect Sheet + ("HOR", Entry::Finish(Action::Command("sheet.rename"))), // Excel: Rename Sheet + ("HOT", Entry::Finish(Action::Command("sheet.tabColor"))), // Excel: Tab Color + ("HOUC", Entry::Finish(Action::Command("home.hideColumns"))), // Excel: Hide Columns + ("HOUH", Entry::Finish(Action::Command("sheet.unhide"))), // Excel: Unhide Sheet + ("HOUL", Entry::Finish(Action::Command("home.unhideColumns"))), // Excel: Unhide Columns + ("HOUO", Entry::Finish(Action::Command("home.unhideRows"))), // Excel: Unhide Rows + ("HOUR", Entry::Finish(Action::Command("home.hideRows"))), // Excel: Hide Rows + ("HOUS", Entry::Finish(Action::Command("sheet.hide"))), // Excel: Hide Sheet + ("HOW", Entry::Finish(Action::Command("home.columnWidth"))), // Excel: Column Width + ("HP", Entry::Finish(Action::Command("home.numberFormat"))), // Excel: Percentage Style; format TBD + ("HSC", Entry::Finish(Action::Command("data.clearFilter"))), // Excel: Clear Filter + ("HSF", Entry::Finish(Action::Command("data.filter"))), // Excel: Filter + ("HSO", Entry::Finish(Action::Command("data.sortDescending"))), // Excel: Sort Z to A + ("HSS", Entry::Finish(Action::Command("data.sortAscending"))), // Excel: Sort A to Z + ("HSU", Entry::Finish(Action::Command("data.sort"))), // Excel: Custom Sort + ("HT", Entry::Continue), // Excel: Format as Table; group level: + ("HTN", Entry::Finish(Action::Command("table.style"))), // Excel: New Table Style + ("HTP", Entry::Finish(Action::Command("table.style"))), // Excel: New Pivot Table Style + ("HU", Entry::Continue), // Excel: AutoSum; group level: + ("HUA", Entry::Finish(Action::Command("formulas.autoSum"))), // Excel: Auto Average; AutoSum: Average (variant TBD) + ("HUC", Entry::Finish(Action::Command("formulas.autoSum"))), // Excel: Auto Count Numbers; AutoSum: Count (variant TBD) + ("HUI", Entry::Finish(Action::Command("formulas.autoSum"))), // Excel: Auto Min; AutoSum: Min (variant TBD) + ("HUM", Entry::Finish(Action::Command("formulas.autoSum"))), // Excel: Auto Max; AutoSum: Max (variant TBD) + ("HV", Entry::Continue), // Excel: Paste; group level: + ("HVA", Entry::Finish(Action::Command("edit.pasteSpecial"))), // Excel: Paste Values and Number Formatting; paste variant, params TBD: what=TBD(values+numfmt) + ("HVB", Entry::Finish(Action::Command("edit.pasteSpecial"))), // Excel: Paste No Borders; paste variant, params TBD: what=TBD(no-borders) + ("HVE", Entry::Finish(Action::Command("edit.pasteSpecial"))), // Excel: Paste Values and Source Formatting; paste variant, params TBD: what=TBD(values+src-fmt) + ("HVF", Entry::Finish(Action::Command("edit.pasteSpecial"))), // Excel: Paste Formula; paste-variant TBD + ("HVI", Entry::Finish(Action::Command("edit.pasteSpecial"))), // Excel: Paste Linked Picture; what=TBD(linked-picture) + ("HVK", Entry::Finish(Action::Command("edit.pasteSpecial"))), // Excel: Paste Keep Source Formatting; paste variant, params TBD: what=TBD(keep-source) + ("HVM", Entry::Finish(Action::Command("edit.pasteSpecial"))), // Excel: Paste Destination Formatting; paste variant, params TBD: what=TBD(dest) + ("HVN", Entry::Finish(Action::Command("edit.pasteSpecial"))), // Excel: Paste Link; paste variant, params TBD: what=TBD(link) + ("HVO", Entry::Finish(Action::Command("edit.pasteSpecial"))), // Excel: Paste Formula and Formatting; paste variant, params TBD: what=TBD(formula+formatting) + ("HVP", Entry::Finish(Action::Command("edit.paste"))), // Excel: Paste + ("HVR", Entry::Finish(Action::Command("edit.pasteSpecial"))), // Excel: Paste Formatting; paste variant, params TBD: what=formats + ("HVT", Entry::Finish(Action::Command("edit.pasteSpecial"))), // Excel: Paste Transpose; paste variant, params TBD: what=transpose + ("HVU", Entry::Finish(Action::Command("edit.pasteSpecial"))), // Excel: Paste Picture; what=TBD(picture) + ("HVV", Entry::Finish(Action::Command("edit.pasteSpecial"))), // Excel: Paste Values; paste variant, params TBD: what=values + ("HVW", Entry::Finish(Action::Command("edit.pasteSpecial"))), // Excel: Paste Keep Source Column Widths; paste variant, params TBD: what=TBD(col-widths) + ("HW", Entry::Continue), // Excel: Wrap Text Menu; group level: containment(Wrap Text) + ("HWS", Entry::Finish(Action::Pending("home.shrinkToFit"))), // pending; Excel: Shrink to Fit; Shrink to Fit; reserved until the command lands + ("HWW", Entry::Finish(Action::Command("home.wrapText"))), // Excel: Wrap Text + ("HX", Entry::Finish(Action::Command("edit.cut"))), // Excel: Cut + ("NC1", Entry::Finish(Action::Command("insert.chart"))), // Excel: Column Chart; Column chart (kind TBD) + ("NC2", Entry::Finish(Action::Command("review.newComment"))), // Excel: New Comment + ("NCB", Entry::Finish(Action::Command("insert.checkbox"))), // Excel: Checkbox + ("ND", Entry::Finish(Action::Command("insert.chart"))), // Excel: Scatter Chart; Scatter (kind TBD) + ("NE", Entry::Finish(Action::Pending("insert.equation"))), // pending; Excel: Equations; Equations; reserved until the command lands + ("NF", Entry::Continue), // Excel: Online Pictures; group level: containment(Picture) + ("NFP", Entry::Continue), // Excel: From Picture Menu; group level: containment(Picture) + ("NFPF", Entry::Finish(Action::Command("insert.picture"))), // Excel: Picture From File; containment(Picture) + ("NH1", Entry::Finish(Action::Command("pageLayout.headerFooter"))), // Excel: Header & Footer + ("NHF", Entry::Finish(Action::Command("pageLayout.headerFooter"))), // Excel: Header & Footer + ("NHI", Entry::Finish(Action::Command("insert.chart"))), // Excel: Hierarchy Chart; Hierarchy (kind TBD) + ("NI1", Entry::Finish(Action::Command("insert.chart"))), // Excel: Waterfall Chart; Waterfall (kind TBD) + ("NI2", Entry::Finish(Action::Command("insert.link"))), // Excel: Link + ("NJ", Entry::Finish(Action::Pending("`insert.object`"))), // pending; Excel: Object; insert.object missing; reserved until the command lands + ("NM1T", Entry::Finish(Action::Command("insert.picture"))), // Excel: SmartArt Picture; containment(Picture) + ("NM2", Entry::Finish(Action::Command("insert.chart"))), // Excel: Map Chart; Map (kind TBD) + ("NN1", Entry::Finish(Action::Command("insert.chart"))), // Excel: Line Chart; Line chart (kind TBD) + ("NNS", Entry::Finish(Action::Command("insert.icons"))), // Excel: Icons + ("NP", Entry::Continue), // Excel: Picture; group level: + ("NPB", Entry::Finish(Action::Command("insert.picture"))), // Excel: Picture from File; containment(Picture) + ("NPF", Entry::Finish(Action::Command("insert.picture"))), // Excel: Place in Cell; Picture in cell (source TBD) + ("NPI", Entry::Finish(Action::Command("insert.picture"))), // Excel: Place in Cell Menu; Picture in cell (source TBD) + ("NPO", Entry::Finish(Action::Command("insert.picture"))), // Excel: Place over Cells Menu; Picture over cells (source TBD) + ("NQ", Entry::Finish(Action::Command("insert.chart"))), // Excel: Pie Chart; Pie (kind TBD) + ("NR", Entry::Finish(Action::Command("insert.recommendedCharts"))), // Excel: Recommended Charts + ("NSA", Entry::Finish(Action::Command("insert.chart"))), // 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 + ("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 + ("NT", Entry::Finish(Action::Command("insert.table"))), // Excel: Table + ("NU", Entry::Finish(Action::Command("insert.symbol"))), // Excel: Symbols; containment(Symbol) + ("NV", Entry::Finish(Action::Command("insert.pivotTable"))), // Excel: PivotTable + ("NW", Entry::Finish(Action::Pending("insert.wordArt"))), // pending; Excel: WordArt; WordArt; reserved until the command lands + ("NX", Entry::Finish(Action::Command("insert.textBox"))), // Excel: Text Box + ("NZK", Entry::Continue), // Excel: Sparklines Menu; group level: + ("NZKSL", Entry::Finish(Action::Command("insert.sparkline"))), // Excel: Line Sparkline + ("NZKSO", Entry::Finish(Action::Command("insert.sparkline"))), // Excel: Column Sparkline + ("NZKSW", Entry::Finish(Action::Command("insert.sparkline"))), // Excel: Win/Loss Sparkline + ("NZTX", Entry::Finish(Action::Command("insert.textBox"))), // Excel: Text Box + ("PAE", Entry::Finish(Action::Command("arrange.sendBackward"))), // Excel: Send Backward + ("PAF", Entry::Finish(Action::Command("arrange.bringForward"))), // Excel: Bring Forward + ("PB", Entry::Continue), // Excel: Breaks; group level: + ("PBI", Entry::Finish(Action::Command("pageLayout.breaks"))), // Excel: Insert Page Break; Insert Page Break + ("PBR", Entry::Finish(Action::Command("pageLayout.breaks"))), // Excel: Remove Page Break; Remove Page Break + ("PG", Entry::Finish(Action::Command("pageLayout.background"))), // Excel: Background + ("PI", Entry::Finish(Action::Command("pageLayout.printTitles"))), // Excel: Print Titles + ("PM", Entry::Continue), // Excel: Margins; group level: + ("PMA", Entry::Finish(Action::Command("pageLayout.margins"))), // Excel: Custom Margins; containment(Margins) + ("PO", Entry::Finish(Action::Command("pageLayout.orientation"))), // Excel: Orientation + ("PPG", Entry::Finish(Action::Command("pageLayout.printGridlines"))), // Excel: Print Gridlines + ("PPH", Entry::Finish(Action::Command("pageLayout.printHeadings"))), // Excel: Print Headings + ("PR", Entry::Continue), // Excel: Print Area; group level: + ("PRS", Entry::Finish(Action::Command("pageLayout.printArea"))), // Excel: Set Print Area + ("PSP", Entry::Finish(Action::Command("pageLayout.pageSetup"))), // Excel: Page Setup + ("PSZ", Entry::Finish(Action::Command("pageLayout.size"))), // Excel: Size + ("PTC", Entry::Finish(Action::Command("pageLayout.themeColors"))), // Excel: Theme Colors; containment(Colors) + ("PTE", Entry::Finish(Action::Command("pageLayout.themeEffects"))), // Excel: Theme Effects; containment(Effects) + ("PTF", Entry::Finish(Action::Command("pageLayout.themeFonts"))), // Excel: Theme Fonts; containment(Fonts) + ("PTH", Entry::Continue), // Excel: Themes; group level: + ("PTHB", Entry::Finish(Action::Command("pageLayout.theme"))), // Excel: Browse Themes; containment(Themes) + ("PVG", Entry::Finish(Action::Command("view.gridlines"))), // Excel: View Gridlines + ("PVH", Entry::Finish(Action::Command("view.headings"))), // Excel: View Headings + ("MA", Entry::Continue), // Excel: Remove Arrows Menu; group level: containment(Remove Arrows) + ("MAA", Entry::Finish(Action::Pending("formulas.removeArrows"))), // pending; Excel: Remove All Arrows; Remove All Arrows; reserved until the command lands + ("MAP", Entry::Finish(Action::Pending("formulas.removePrecedentArrows"))), // pending; Excel: Remove Precedent Arrows; Remove Precedent Arrows; reserved until the command lands + ("MB", Entry::Finish(Action::Command("formulas.calculateNow"))), // Excel: Calculate Now + ("MC", Entry::Finish(Action::Command("formulas.createFromSelection"))), // Excel: Create From Selection + ("MD", Entry::Finish(Action::Command("formulas.traceDependents"))), // Excel: Trace Dependents + ("ME", Entry::Continue), // Excel: Date & Time Menu; group level: containment(Date & Time) + ("MEF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Date & Time - Insert Function; containment(Insert Function) + ("MF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Insert Function + ("MG", Entry::Continue), // Excel: Math & Trig Menu; group level: containment(Math & Trig) + ("MGF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Math & Trig - Insert Function; containment(Insert Function) + ("MH", Entry::Finish(Action::Command("formulas.showFormulas"))), // Excel: Show Formulas + ("MI", Entry::Continue), // Excel: Financial Menu; group level: containment(Financial) + ("MIF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Financial - Insert Function; containment(Insert Function) + ("MJ", Entry::Finish(Action::Command("formulas.calculateSheet"))), // Excel: Calculate Sheet + ("MK", Entry::Continue), // Excel: Error Checking Menu; group level: containment(Error Checking) + ("MKK", Entry::Finish(Action::Command("formulas.errorChecking"))), // Excel: Error Checking + ("ML", Entry::Continue), // Excel: Logical Menu; group level: containment(Logical) + ("MLF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Logical - Insert Function; containment(Insert Function) + ("MM", Entry::Finish(Action::Command("formulas.defineName"))), // Excel: Define Name + ("MN", Entry::Finish(Action::Command("formulas.nameManager"))), // Excel: Name Manager + ("MO", Entry::Continue), // Excel: Lookup & Reference Menu; group level: containment(Lookup & Reference) + ("MOF", Entry::Finish(Action::Command("formulas.lookupReference"))), // Excel: Lookup & Reference - Insert Function; containment(Lookup & Reference) + ("MP", Entry::Finish(Action::Command("formulas.tracePrecedents"))), // Excel: Trace Precedents + ("MQ", Entry::Continue), // Excel: More Functions Menu; group level: containment(More Functions) + ("MQCF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Cube - Insert Function; containment(Insert Function) + ("MQEF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Engineering - Insert Function; containment(Insert Function) + ("MQIF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Information - Insert Function; containment(Insert Function) + ("MQOF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Compatibility - Insert Function; containment(Insert Function) + ("MQSF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Statistical - Insert Function; containment(Insert Function) + ("MQWF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Web - Insert Function; containment(Insert Function) + ("MR", Entry::Continue), // Excel: Recently Used Menu; group level: containment(Recently Used) + ("MRF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Recently Used - Insert Function; containment(Insert Function) + ("MS", Entry::Continue), // Excel: Use in Formula Menu; group level: containment(Use in Formula) + ("MSP", Entry::Finish(Action::Command("edit.pasteSpecial"))), // Excel: Paste Names; paste-variant TBD + ("MT", Entry::Continue), // Excel: Text Menu; group level: containment(Text) + ("MTF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Text - Insert Function; containment(Insert Function) + ("MU", Entry::Continue), // Excel: AutoSum Menu; group level: + ("MUA", Entry::Finish(Action::Command("formulas.autoSum"))), // Excel: Average; AutoSum: Average (variant TBD) + ("MUC", Entry::Finish(Action::Command("formulas.autoSum"))), // Excel: Count Numbers; AutoSum: Count (variant TBD) + ("MUF", Entry::Finish(Action::Command("formulas.moreFunctions"))), // Excel: More Functions (AutoSum); containment(More Functions) + ("MUI", Entry::Finish(Action::Command("formulas.autoSum"))), // Excel: Min; AutoSum: Min (variant TBD) + ("MUM", Entry::Finish(Action::Command("formulas.autoSum"))), // Excel: Max; AutoSum: Max (variant TBD) + ("MUS", Entry::Finish(Action::Command("formulas.autoSum"))), // Excel: Sum + ("MV", Entry::Finish(Action::Command("formulas.evaluateFormula"))), // Excel: Evaluate Formula + ("MW", Entry::Finish(Action::Command("formulas.watchWindow"))), // Excel: Watch Window + ("MX", Entry::Continue), // Excel: Calculation Options Menu; group level: containment(Calculation Options) + ("MXA", Entry::Finish(Action::Command("formulas.calculationOptions"))), // Excel: Automatic Calculation; Calculation options: Automatic + ("MXM", Entry::Finish(Action::Command("formulas.calculationOptions"))), // Excel: Manual Calculation; Calculation options: Manual + ("MXP", Entry::Finish(Action::Command("formulas.calculationOptions"))), // Excel: Partial Calculation; Calculation options: Partial + ("AB", Entry::Finish(Action::Command("data.subtotal"))), // Excel: Subtotal + ("AC", Entry::Finish(Action::Command("data.clearFilter"))), // Excel: Clear Filter + ("AD", Entry::Finish(Action::Command("data.consolidate"))), // Excel: Consolidate + ("AE", Entry::Finish(Action::Command("data.textToColumns"))), // Excel: Text to Columns + ("AF1", Entry::Continue), // Excel: Data from Picture Menu; group level: feature gap; reserved until the command lands + ("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 + ("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 + ("AFT", Entry::Finish(Action::Pending("data.fromText"))), // pending; Excel: Get External Data: From Text; gap #12; reserved until the command lands + ("AFW", Entry::Finish(Action::Pending("data.fromWeb"))), // pending; Excel: Get External Data: From Web; reserved until the command lands + ("AG", Entry::Continue), // Excel: Group Menu; group level: containment(Group) + ("AGA", Entry::Finish(Action::Pending("data.autoOutline"))), // pending; Excel: Auto Outline; Auto Outline; reserved until the command lands + ("AGG", Entry::Finish(Action::Command("data.group"))), // Excel: Group + ("AH", Entry::Finish(Action::Command("data.hideDetail"))), // Excel: Hide Detail + ("AJ", Entry::Finish(Action::Command("data.showDetail"))), // Excel: Show Detail + ("AK", Entry::Finish(Action::Command("data.queriesConnections"))), // Excel: Edit Links; Edit Links (Queries & Connections); + ("AM", Entry::Finish(Action::Command("data.removeDuplicates"))), // Excel: Remove Duplicates + ("AO", Entry::Finish(Action::Command("data.queriesConnections"))), // Excel: Queries & Connections + ("AP1", Entry::Finish(Action::Command("file.properties"))), // Excel: Properties + ("APN", Entry::Continue), // Excel: Get Data (Power Query) Menu; group level: Power Query variants = GAP + ("APND", Entry::Finish(Action::Pending("data.fromDatabase"))), // pending; Excel: From Database (Microsoft Query); gap #12; reserved until the command lands + ("APNE", Entry::Finish(Action::Pending("data.powerQueryEditor"))), // pending; Excel: Launch Power Query Editor; gap #12; reserved until the command lands + ("APNG", Entry::Finish(Action::Command("data.getData"))), // Excel: Get Data (Power Query); containment(Get Data) + ("APNH", Entry::Finish(Action::Pending("data.fromHtml"))), // pending; Excel: From HTML; gap #12; reserved until the command lands + ("APNL", Entry::Finish(Action::Pending("data.fromSqlServer"))), // pending; Excel: From SQL Server ODBC; gap #12; reserved until the command lands + ("APNS", Entry::Finish(Action::Pending("data.dataSourceSettings"))), // pending; Excel: Data Source Settings; gap #12; reserved until the command lands + ("APNT", Entry::Finish(Action::Pending("data.fromTextLegacy"))), // pending; Excel: From Text (Legacy); gap #12; reserved until the command lands + ("APR", Entry::Finish(Action::Pending("data.recentSources"))), // pending; Excel: Recent Sources; gap #12; reserved until the command lands + ("APS", Entry::Finish(Action::Command("data.queriesConnections"))), // Excel: Show Queries + ("APT", Entry::Finish(Action::Pending("data.fromTable"))), // pending; Excel: From Table (query); gap #12; reserved until the command lands + ("AQ", Entry::Finish(Action::Command("data.advancedFilter"))), // Excel: Advanced Filter + ("AR", Entry::Continue), // group: group: Queries & Connections + ("ARA", Entry::Finish(Action::Command("data.refreshAll"))), // Excel: Refresh All + ("ARC", Entry::Finish(Action::Pending("data.cancelRefresh"))), // pending; Excel: Cancel Refresh; gap #12; reserved until the command lands + ("ARO", Entry::Finish(Action::Pending("data.connectionProperties"))), // pending; Excel: Connection Properties; gap #12; reserved until the command lands + ("ARR", Entry::Finish(Action::Command("pivot.refresh"))), // Excel: Refresh + ("ARS", Entry::Finish(Action::Pending("data.refreshStatus"))), // pending; Excel: Refresh Status; gap #12; reserved until the command lands + ("ASA", Entry::Finish(Action::Command("data.sortAscending"))), // Excel: Sort A to Z + ("ASD", Entry::Finish(Action::Command("data.sortDescending"))), // Excel: Sort Z to A + ("ASS", Entry::Finish(Action::Command("data.sort"))), // Excel: Sort + ("AT", Entry::Finish(Action::Command("data.filter"))), // Excel: Filter + ("AU", Entry::Continue), // Excel: Ungroup Menu; group level: containment(Ungroup) + ("AUC", Entry::Finish(Action::Pending("data.clearOutline"))), // pending; Excel: Clear Outline; feature gap; reserved until the command lands + ("AUU", Entry::Finish(Action::Command("data.ungroup"))), // Excel: Ungroup + ("AV", Entry::Continue), // Excel: Data Validation Menu; group level: containment(Data Validation) + ("AVI", Entry::Finish(Action::Command("data.circleInvalid"))), // Excel: Circle Invalid Data + ("AVR", Entry::Finish(Action::Pending("data.clearValidationCircles"))), // pending; Excel: Clear Validation Circles; reserved until the command lands + ("AVV", Entry::Finish(Action::Command("data.validation"))), // Excel: Data Validation + ("AW", Entry::Continue), // group: group: What-If (goalSeek/scenarioManager/dataTable) + ("AWG", Entry::Finish(Action::Command("data.goalSeek"))), // Excel: Goal Seek + ("AWS", Entry::Finish(Action::Command("data.scenarioManager"))), // Excel: Scenario Manager + ("AWT", Entry::Finish(Action::Command("data.dataTable"))), // Excel: Data Table + ("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::Command("review.checkAccessibility"))), // Excel: Check Accessibility + ("RA2", Entry::Finish(Action::Pending("review.showComments"))), // pending; Excel: Show All Comments; Show All Comments; reserved until the command lands + ("RC", Entry::Finish(Action::Command("review.newComment"))), // 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 + ("RO", Entry::Finish(Action::Command("review.protectWorkbook"))), // Excel: Protect and Share Workbook + ("RPS", Entry::Finish(Action::Command("review.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::Command("review.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 + ("RW", Entry::Finish(Action::Pending("review.shareWorkbook"))), // pending; Excel: Share Workbook; reserved until the command lands + ("WA", Entry::Finish(Action::Command("view.arrangeAll"))), // Excel: Arrange All + ("WB", Entry::Finish(Action::Pending("view.sideBySide"))), // pending; Excel: View Side by Side; reserved until the command lands + ("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::Command("view.zoom"))), // Excel: Zoom To 100% + ("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::Command("view.zoom"))), // Excel: Zoom + ("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::Pending("view.formulaBar"))), // pending; Excel: Toggle Formula Bar; Toggle Formula Bar; reserved until the command lands + ("WVH", Entry::Finish(Action::Command("view.headings"))), // Excel: Toggle Headings; containment(Headings) + ("WVL", Entry::Finish(Action::Pending("view.synchronousScrolling"))), // pending; Excel: Synchronous Scrolling; Synchronous Scrolling; reserved until the command lands + ("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 + ("WVV", Entry::Finish(Action::Pending("view.sideBySide"))), // pending; Excel: View Side by Side; reserved until the command lands + ("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 + ("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 + ("FD", Entry::Finish(Action::Pending("file.account"))), // pending; Excel: Account page; Account page; reserved until the command lands + ("FEA", Entry::Finish(Action::Command("file.exportPdf"))), // Excel: Export: create PDF/XPS; Export: create PDF/XPS + ("FEC", Entry::Finish(Action::Command("file.saveAs"))), // Excel: Export: change file type; Export: change file type + ("FH", Entry::Finish(Action::Pending("file.home"))), // pending; Excel: File Home page (recent/pinned/shared/new blank); File Home page; reserved until the command lands + ("FI", Entry::Finish(Action::Command("file.properties"))), // Excel: Info page; fires immediately in Excel; deeper aliases dropped as unreachable + ("FN", Entry::Finish(Action::Command("file.new"))), // Excel: New page; New page + ("FO", Entry::Finish(Action::Command("file.open"))), // Excel: Open page; fires immediately in Excel; deeper aliases dropped as unreachable + ("FP", Entry::Finish(Action::Command("file.print"))), // Excel: Print page; containment(Print) + ("FT", Entry::Finish(Action::Pending("file.options"))), // pending; Excel: Options dialog; Options dialog; reserved until the command lands + ("Q", Entry::Finish(Action::Pending("ui.search"))), // pending; Excel: Search / Tell Me; Alt+Q search box does not exist yet (issue #49) + ("6", Entry::Finish(Action::Pending("qat.6"))), // pending; Excel: Quick Access Toolbar position 6; QAT navigation does not exist yet + ("7", Entry::Finish(Action::Pending("qat.7"))), // pending; Excel: Quick Access Toolbar position 7; QAT navigation does not exist yet + ("8", Entry::Finish(Action::Pending("qat.8"))), // pending; Excel: Quick Access Toolbar position 8; QAT navigation does not exist yet + ("9", Entry::Finish(Action::Pending("qat.9"))), // pending; Excel: Quick Access Toolbar position 9; QAT navigation does not exist yet ]; diff --git a/crates/ui-egui/src/keytips/keytips.json b/crates/ui-egui/src/keytips/keytips.json index 13489f1..1056d31 100644 --- a/crates/ui-egui/src/keytips/keytips.json +++ b/crates/ui-egui/src/keytips/keytips.json @@ -11,25 +11,2846 @@ " - Keep entries grouped by tab and sorted by sequence within a group; the FIRST entry for a tab is its canonical badge (legacy aliases come after it)." ], "sequences": [ - { "seq": "H", "kind": "tab", "target": "Home" }, - { "seq": "N", "kind": "tab", "target": "Insert" }, - { "seq": "JI", "kind": "tab", "target": "Draw", "note": "Two-letter unit. Deeper Draw letters differ between Excel and GridCraft; left blank for future contributors." }, - { "seq": "P", "kind": "tab", "target": "Page Layout" }, - { "seq": "M", "kind": "tab", "target": "Formulas" }, - { "seq": "A", "kind": "tab", "target": "Data" }, - { "seq": "R", "kind": "tab", "target": "Review" }, - { "seq": "W", "kind": "tab", "target": "View" }, - { "seq": "E", "kind": "tab", "target": "Home", "note": "Legacy Edit-menu path (Excel 2003); leads to the same Home menus." }, - { "seq": "O", "kind": "tab", "target": "Home", "note": "Legacy Format-menu path (Excel 2003); leads to the same Home menus." }, - - { "seq": "HAR", "kind": "command", "target": "home.alignRight" }, - { "seq": "HAL", "kind": "command", "target": "home.alignLeft" }, - { "seq": "HAC", "kind": "command", "target": "home.alignCenter" }, - { "seq": "HVS", "kind": "dialog", "target": "pasteSpecial" }, - { "seq": "ES", "kind": "dialog", "target": "pasteSpecial", "note": "Legacy Edit menu." }, - { "seq": "HOI", "kind": "command", "target": "home.autofitColumnWidth" }, - { "seq": "OCA", "kind": "command", "target": "home.autofitColumnWidth", "note": "Legacy Format menu." }, - - { "seq": "WVG", "kind": "command", "target": "view.gridlines" } + { + "seq": "H", + "kind": "tab", + "target": "Home" + }, + { + "seq": "N", + "kind": "tab", + "target": "Insert" + }, + { + "seq": "JI", + "kind": "tab", + "target": "Draw", + "note": "Two-letter unit. Deeper Draw letters differ between Excel and GridCraft; left blank for future contributors." + }, + { + "seq": "P", + "kind": "tab", + "target": "Page Layout" + }, + { + "seq": "M", + "kind": "tab", + "target": "Formulas" + }, + { + "seq": "A", + "kind": "tab", + "target": "Data" + }, + { + "seq": "R", + "kind": "tab", + "target": "Review" + }, + { + "seq": "W", + "kind": "tab", + "target": "View" + }, + { + "seq": "E", + "kind": "tab", + "target": "Home", + "note": "Legacy Edit-menu path (Excel 2003); leads to the same Home menus." + }, + { + "seq": "O", + "kind": "tab", + "target": "Home", + "note": "Legacy Format-menu path (Excel 2003); leads to the same Home menus." + }, + { + "seq": "HAR", + "kind": "command", + "target": "home.alignRight" + }, + { + "seq": "HAL", + "kind": "command", + "target": "home.alignLeft" + }, + { + "seq": "HAC", + "kind": "command", + "target": "home.alignCenter" + }, + { + "seq": "HVS", + "kind": "dialog", + "target": "pasteSpecial" + }, + { + "seq": "ES", + "kind": "dialog", + "target": "pasteSpecial", + "excel": "Classic Paste Special dialog (legacy Edit route); A/F/T/V are dialog mnemonics" + }, + { + "seq": "HOI", + "kind": "command", + "target": "home.autofitColumnWidth" + }, + { + "seq": "OCA", + "kind": "command", + "target": "home.autofitColumnWidth", + "note": "Legacy Format menu." + }, + { + "seq": "WVG", + "kind": "command", + "target": "view.gridlines" + }, + { + "seq": "0", + "kind": "command", + "target": "qat.10", + "pending": true, + "excel": "Quick Access Toolbar position 10", + "note": "QAT navigation does not exist yet" + }, + { + "seq": "1", + "kind": "command", + "target": "qat.1", + "pending": true, + "excel": "Quick Access Toolbar position 1", + "note": "QAT navigation does not exist yet" + }, + { + "seq": "2", + "kind": "command", + "target": "qat.2", + "pending": true, + "excel": "Quick Access Toolbar position 2", + "note": "QAT navigation does not exist yet" + }, + { + "seq": "3", + "kind": "command", + "target": "qat.3", + "pending": true, + "excel": "Quick Access Toolbar position 3", + "note": "QAT navigation does not exist yet" + }, + { + "seq": "4", + "kind": "command", + "target": "qat.4", + "pending": true, + "excel": "Quick Access Toolbar position 4", + "note": "QAT navigation does not exist yet" + }, + { + "seq": "5", + "kind": "command", + "target": "qat.5", + "pending": true, + "excel": "Quick Access Toolbar position 5", + "note": "QAT navigation does not exist yet" + }, + { + "seq": "H0", + "kind": "command", + "target": "home.increaseDecimal", + "excel": "Increase Decimals", + "note": "containment(Increase Decimal)" + }, + { + "seq": "H1", + "kind": "command", + "target": "home.bold", + "excel": "Bold", + "note": "" + }, + { + "seq": "H2", + "kind": "command", + "target": "home.italic", + "excel": "Italic", + "note": "" + }, + { + "seq": "H3", + "kind": "continue", + "excel": "Underline Menu", + "note": "group level:" + }, + { + "seq": "H3D", + "kind": "command", + "target": "home.doubleUnderline", + "excel": "Double Underline", + "note": "" + }, + { + "seq": "H3U", + "kind": "command", + "target": "home.underline", + "excel": "Underline", + "note": "" + }, + { + "seq": "H5", + "kind": "command", + "target": "home.decreaseIndent", + "excel": "Decrease Indent", + "note": "" + }, + { + "seq": "H6", + "kind": "command", + "target": "home.increaseIndent", + "excel": "Increase Indent", + "note": "" + }, + { + "seq": "H9", + "kind": "command", + "target": "home.decreaseDecimal", + "excel": "Decrease Decimals", + "note": "containment(Decrease Decimal)" + }, + { + "seq": "HAN", + "kind": "command", + "excel": "Accounting Format", + "note": "fires immediately in Excel; deeper aliases dropped as unreachable", + "target": "home.accounting" + }, + { + "seq": "HAS", + "kind": "command", + "target": "home.addIns", + "excel": "Add-ins", + "note": "containment(Add-ins)" + }, + { + "seq": "HB", + "kind": "continue", + "excel": "Borders Menu", + "note": "group level:" + }, + { + "seq": "HBA", + "kind": "command", + "target": "home.borders", + "excel": "All Borders", + "note": "containment(Borders)" + }, + { + "seq": "HBB", + "kind": "command", + "target": "home.borders", + "excel": "Bottom Double Border", + "note": "border-side TBD" + }, + { + "seq": "HBC", + "kind": "command", + "target": "home.borders", + "excel": "Top and Thick Bottom Border", + "note": "border-side TBD" + }, + { + "seq": "HBD", + "kind": "command", + "target": "home.borders", + "excel": "Top and Bottom Border", + "note": "border-side TBD" + }, + { + "seq": "HBE", + "kind": "command", + "target": "home.borders", + "excel": "Erase Border", + "note": "border-side TBD" + }, + { + "seq": "HBG", + "kind": "command", + "target": "home.drawBorder", + "excel": "Draw Border Grid", + "note": "containment(Draw Border)" + }, + { + "seq": "HBH", + "kind": "command", + "target": "home.borders", + "excel": "Thick Bottom Border", + "note": "border-side TBD" + }, + { + "seq": "HBI", + "kind": "command", + "target": "home.borders", + "excel": "Line Color", + "note": "Line Color (submenu TBD)" + }, + { + "seq": "HBL", + "kind": "command", + "target": "home.borders", + "excel": "Left Border", + "note": "border-side TBD" + }, + { + "seq": "HBM", + "kind": "command", + "target": "home.borders", + "excel": "More Borders", + "note": "containment(Borders)" + }, + { + "seq": "HBN", + "kind": "command", + "target": "home.borders", + "excel": "No Border", + "note": "border-side TBD" + }, + { + "seq": "HBO", + "kind": "command", + "target": "home.borders", + "excel": "Bottom Border", + "note": "border-side TBD" + }, + { + "seq": "HBP", + "kind": "command", + "target": "home.borders", + "excel": "Top Border", + "note": "border-side TBD" + }, + { + "seq": "HBR", + "kind": "command", + "target": "home.borders", + "excel": "Right Border", + "note": "border-side TBD" + }, + { + "seq": "HBS", + "kind": "command", + "target": "home.borders", + "excel": "Outside Borders", + "note": "containment(Borders)" + }, + { + "seq": "HBT", + "kind": "command", + "target": "home.borders", + "excel": "Thick Outside Borders", + "note": "border-side TBD" + }, + { + "seq": "HBU", + "kind": "command", + "target": "home.borders", + "excel": "Top and Double Bottom Border", + "note": "border-side TBD" + }, + { + "seq": "HBW", + "kind": "command", + "target": "home.drawBorder", + "excel": "Draw Border", + "note": "" + }, + { + "seq": "HBY", + "kind": "command", + "target": "home.borders", + "excel": "Line Style", + "note": "Line Style (submenu TBD)" + }, + { + "seq": "HC", + "kind": "command", + "excel": "Copy", + "note": "fires immediately in Excel; deeper aliases dropped as unreachable", + "target": "edit.copy" + }, + { + "seq": "HCP", + "kind": "command", + "target": "home.copyAsPicture", + "pending": true, + "excel": "Copy as Picture", + "note": "reserved until the command lands" + }, + { + "seq": "HDC", + "kind": "command", + "target": "home.deleteColumns", + "excel": "Delete Columns", + "note": "Delete Columns" + }, + { + "seq": "HDD", + "kind": "command", + "target": "home.deleteCells", + "excel": "Delete Cells", + "note": "" + }, + { + "seq": "HDR", + "kind": "command", + "target": "home.deleteRows", + "excel": "Delete Rows", + "note": "Delete Rows" + }, + { + "seq": "HDS", + "kind": "command", + "target": "home.deleteSheet", + "excel": "Delete Sheet", + "note": "" + }, + { + "seq": "HEA", + "kind": "command", + "target": "edit.clearAll", + "excel": "Clear All", + "note": "" + }, + { + "seq": "HEC", + "kind": "command", + "target": "edit.clearContents", + "excel": "Clear Contents", + "note": "" + }, + { + "seq": "HEF", + "kind": "command", + "target": "edit.clearFormats", + "excel": "Clear Formats", + "note": "" + }, + { + "seq": "HEL", + "kind": "command", + "target": "edit.clearHyperlinks", + "excel": "Clear Hyperlinks", + "note": "" + }, + { + "seq": "HEM", + "kind": "command", + "target": "edit.clearComments", + "excel": "Clear Comments and Notes", + "note": "containment(Clear Comments and Notes)" + }, + { + "seq": "HFC", + "kind": "command", + "target": "home.fontColor", + "excel": "Font Color", + "note": "" + }, + { + "seq": "HFDC", + "kind": "command", + "target": "home.conditionalFormat", + "excel": "Find Conditional Formatting", + "note": "containment(Conditional Formatting)" + }, + { + "seq": "HFDF", + "kind": "command", + "target": "edit.find", + "excel": "Find", + "note": "" + }, + { + "seq": "HFDG", + "kind": "command", + "target": "edit.goTo", + "excel": "Go To", + "note": "" + }, + { + "seq": "HFDM", + "kind": "command", + "target": "edit.find", + "excel": "Find Notes", + "note": "containment(Find)" + }, + { + "seq": "HFDO", + "kind": "command", + "target": "home.selectObjects", + "pending": true, + "excel": "Select Objects", + "note": "Select Objects; reserved until the command lands" + }, + { + "seq": "HFDP", + "kind": "command", + "target": "arrange.selectionPane", + "excel": "Selection Pane", + "note": "" + }, + { + "seq": "HFDR", + "kind": "command", + "target": "edit.replace", + "excel": "Replace", + "note": "" + }, + { + "seq": "HFDS", + "kind": "command", + "target": "edit.goToSpecial", + "excel": "Go To Special", + "note": "" + }, + { + "seq": "HFF", + "kind": "command", + "target": "home.fontName", + "excel": "Font Selection", + "note": "" + }, + { + "seq": "HFG", + "kind": "command", + "target": "home.increaseFontSize", + "excel": "Increase Font Size", + "note": "" + }, + { + "seq": "HFI", + "kind": "continue", + "excel": "Fill", + "note": "group level: containment(Fill Up)" + }, + { + "seq": "HFIA", + "kind": "command", + "target": "home.fillAcrossWorksheets", + "pending": true, + "excel": "Fill Across Worksheets", + "note": "Fill Across Worksheets; reserved until the command lands" + }, + { + "seq": "HFID", + "kind": "command", + "target": "edit.fillDown", + "excel": "Fill Down", + "note": "" + }, + { + "seq": "HFIF", + "kind": "command", + "target": "edit.flashFill", + "excel": "Flash Fill", + "note": "" + }, + { + "seq": "HFIJ", + "kind": "command", + "target": "home.justify", + "excel": "Fill Justify", + "note": "containment(Justify)" + }, + { + "seq": "HFIL", + "kind": "command", + "target": "edit.fillLeft", + "excel": "Fill Left", + "note": "" + }, + { + "seq": "HFIR", + "kind": "command", + "target": "edit.fillRight", + "excel": "Fill Right", + "note": "" + }, + { + "seq": "HFIS", + "kind": "command", + "target": "edit.fillSeries", + "excel": "Fill Series", + "note": "containment(Series)" + }, + { + "seq": "HFIU", + "kind": "command", + "target": "edit.fillUp", + "excel": "Fill Up", + "note": "" + }, + { + "seq": "HFK", + "kind": "command", + "target": "home.decreaseFontSize", + "excel": "Decrease Font Size", + "note": "" + }, + { + "seq": "HFM", + "kind": "command", + "target": "home.numberFormat", + "excel": "More Number Formats", + "note": "containment(Number Format)" + }, + { + "seq": "HFP", + "kind": "command", + "target": "edit.formatPainter", + "excel": "Format Painter", + "note": "" + }, + { + "seq": "HFQ", + "kind": "continue", + "excel": "Orientation Menu", + "note": "group level: containment(Orientation)" + }, + { + "seq": "HFQL", + "kind": "command", + "target": "home.angleClockwise", + "pending": true, + "excel": "Angle Clockwise", + "note": "Angle Clockwise; reserved until the command lands" + }, + { + "seq": "HFQO", + "kind": "command", + "target": "home.angleCounterclockwise", + "pending": true, + "excel": "Angle Counterclockwise", + "note": "Angle Counterclockwise; reserved until the command lands" + }, + { + "seq": "HFS", + "kind": "command", + "target": "home.fontSize", + "excel": "Font Size", + "note": "" + }, + { + "seq": "HH", + "kind": "command", + "target": "home.fillColor", + "excel": "Fill Color", + "note": "" + }, + { + "seq": "HIC", + "kind": "command", + "target": "home.insertColumns", + "excel": "Insert Columns", + "note": "Insert Columns" + }, + { + "seq": "HIE", + "kind": "command", + "target": "home.insertCells", + "excel": "Insert Copied Cells", + "note": "Insert Cells (copied cells TBD)" + }, + { + "seq": "HII", + "kind": "command", + "target": "home.insertCells", + "excel": "Insert Cells", + "note": "" + }, + { + "seq": "HIR", + "kind": "command", + "target": "home.insertRows", + "excel": "Insert Rows", + "note": "Insert Rows" + }, + { + "seq": "HIS", + "kind": "command", + "target": "home.insertSheet", + "excel": "Insert Sheet", + "note": "" + }, + { + "seq": "HJ", + "kind": "continue", + "excel": "Cell Styles", + "note": "group level:" + }, + { + "seq": "HJN", + "kind": "command", + "target": "home.newCellStyle", + "excel": "New Cell Style", + "note": "" + }, + { + "seq": "HK", + "kind": "command", + "target": "home.comma", + "excel": "Comma Style", + "note": "" + }, + { + "seq": "HL", + "kind": "continue", + "excel": "Conditional Formatting", + "note": "group level: containment(Conditional Formatting)" + }, + { + "seq": "HLC", + "kind": "continue", + "excel": "Clear Rules Menu", + "note": "group level: containment(Clear Rules)" + }, + { + "seq": "HLCE", + "kind": "command", + "target": "home.clearRules", + "excel": "Clear Rules From Sheet", + "note": "containment(Clear Rules)" + }, + { + "seq": "HLCS", + "kind": "command", + "target": "home.clearRules", + "excel": "Clear Rules From Cells", + "note": "containment(Clear Rules)" + }, + { + "seq": "HLCT", + "kind": "command", + "target": "home.clearRules", + "excel": "Clear Rules From Table", + "note": "containment(Clear Rules)" + }, + { + "seq": "HLD", + "kind": "command", + "target": "home.conditionalFormat", + "excel": "Data Bars", + "note": "Data Bars (submenu TBD)" + }, + { + "seq": "HLH", + "kind": "command", + "target": "home.conditionalFormat", + "excel": "Highlight Cells", + "note": "Highlight Cells (submenu TBD)" + }, + { + "seq": "HLN", + "kind": "command", + "target": "home.conditionalFormat", + "excel": "New Rule", + "note": "New Rule (submenu TBD)" + }, + { + "seq": "HLR", + "kind": "command", + "target": "home.manageRules", + "excel": "Manage Rules", + "note": "containment(Manage Rules)" + }, + { + "seq": "HLT", + "kind": "command", + "target": "home.conditionalFormat", + "excel": "Top/Bottom Rules", + "note": "Top/Bottom (submenu TBD)" + }, + { + "seq": "HM", + "kind": "continue", + "excel": "Merge & Center Menu", + "note": "group level: containment(Merge & Center)" + }, + { + "seq": "HMA", + "kind": "command", + "target": "home.mergeAcross", + "excel": "Merge Across", + "note": "" + }, + { + "seq": "HMC", + "kind": "command", + "target": "home.mergeCenter", + "excel": "Merge & Center", + "note": "" + }, + { + "seq": "HMM", + "kind": "command", + "target": "home.mergeCells", + "excel": "Merge Cells", + "note": "" + }, + { + "seq": "HMU", + "kind": "command", + "target": "home.unmergeCells", + "excel": "Unmerge Cells", + "note": "" + }, + { + "seq": "HN", + "kind": "command", + "target": "home.numberFormat", + "excel": "Number Format", + "note": "" + }, + { + "seq": "HOA", + "kind": "command", + "target": "home.autofitRowHeight", + "excel": "AutoFit Row Height", + "note": "" + }, + { + "seq": "HOD", + "kind": "command", + "target": "home.columnWidth", + "excel": "Default Column Width", + "note": "containment(Column Width)" + }, + { + "seq": "HOE", + "kind": "command", + "target": "home.formatCells", + "excel": "Format Cells", + "note": "" + }, + { + "seq": "HOH", + "kind": "command", + "target": "home.rowHeight", + "excel": "Row Height", + "note": "" + }, + { + "seq": "HOL", + "kind": "command", + "target": "home.lockCell", + "excel": "Lock Cell", + "note": "containment(Lock Cell)" + }, + { + "seq": "HOM", + "kind": "command", + "target": "sheet.move", + "excel": "Move or Copy Sheet", + "note": "" + }, + { + "seq": "HOP", + "kind": "command", + "target": "review.protectSheet", + "excel": "Protect Sheet", + "note": "" + }, + { + "seq": "HOR", + "kind": "command", + "target": "sheet.rename", + "excel": "Rename Sheet", + "note": "" + }, + { + "seq": "HOT", + "kind": "command", + "target": "sheet.tabColor", + "excel": "Tab Color", + "note": "" + }, + { + "seq": "HOUC", + "kind": "command", + "target": "home.hideColumns", + "excel": "Hide Columns", + "note": "" + }, + { + "seq": "HOUH", + "kind": "command", + "target": "sheet.unhide", + "excel": "Unhide Sheet", + "note": "" + }, + { + "seq": "HOUL", + "kind": "command", + "target": "home.unhideColumns", + "excel": "Unhide Columns", + "note": "" + }, + { + "seq": "HOUO", + "kind": "command", + "target": "home.unhideRows", + "excel": "Unhide Rows", + "note": "" + }, + { + "seq": "HOUR", + "kind": "command", + "target": "home.hideRows", + "excel": "Hide Rows", + "note": "" + }, + { + "seq": "HOUS", + "kind": "command", + "target": "sheet.hide", + "excel": "Hide Sheet", + "note": "" + }, + { + "seq": "HOW", + "kind": "command", + "target": "home.columnWidth", + "excel": "Column Width", + "note": "" + }, + { + "seq": "HP", + "kind": "command", + "target": "home.numberFormat", + "excel": "Percentage Style", + "note": "format TBD" + }, + { + "seq": "HSC", + "kind": "command", + "target": "data.clearFilter", + "excel": "Clear Filter", + "note": "" + }, + { + "seq": "HSF", + "kind": "command", + "target": "data.filter", + "excel": "Filter", + "note": "" + }, + { + "seq": "HSO", + "kind": "command", + "target": "data.sortDescending", + "excel": "Sort Z to A", + "note": "" + }, + { + "seq": "HSS", + "kind": "command", + "target": "data.sortAscending", + "excel": "Sort A to Z", + "note": "" + }, + { + "seq": "HSU", + "kind": "command", + "target": "data.sort", + "excel": "Custom Sort", + "note": "" + }, + { + "seq": "HT", + "kind": "continue", + "excel": "Format as Table", + "note": "group level:" + }, + { + "seq": "HTN", + "kind": "command", + "target": "table.style", + "excel": "New Table Style", + "note": "" + }, + { + "seq": "HTP", + "kind": "command", + "target": "table.style", + "excel": "New Pivot Table Style", + "note": "" + }, + { + "seq": "HU", + "kind": "continue", + "excel": "AutoSum", + "note": "group level:" + }, + { + "seq": "HUA", + "kind": "command", + "target": "formulas.autoSum", + "excel": "Auto Average", + "note": "AutoSum: Average (variant TBD)" + }, + { + "seq": "HUC", + "kind": "command", + "target": "formulas.autoSum", + "excel": "Auto Count Numbers", + "note": "AutoSum: Count (variant TBD)" + }, + { + "seq": "HUI", + "kind": "command", + "target": "formulas.autoSum", + "excel": "Auto Min", + "note": "AutoSum: Min (variant TBD)" + }, + { + "seq": "HUM", + "kind": "command", + "target": "formulas.autoSum", + "excel": "Auto Max", + "note": "AutoSum: Max (variant TBD)" + }, + { + "seq": "HV", + "kind": "continue", + "excel": "Paste", + "note": "group level:" + }, + { + "seq": "HVA", + "kind": "command", + "target": "edit.pasteSpecial", + "excel": "Paste Values and Number Formatting", + "note": "paste variant, params TBD: what=TBD(values+numfmt)" + }, + { + "seq": "HVB", + "kind": "command", + "target": "edit.pasteSpecial", + "excel": "Paste No Borders", + "note": "paste variant, params TBD: what=TBD(no-borders)" + }, + { + "seq": "HVE", + "kind": "command", + "target": "edit.pasteSpecial", + "excel": "Paste Values and Source Formatting", + "note": "paste variant, params TBD: what=TBD(values+src-fmt)" + }, + { + "seq": "HVF", + "kind": "command", + "target": "edit.pasteSpecial", + "excel": "Paste Formula", + "note": "paste-variant TBD" + }, + { + "seq": "HVI", + "kind": "command", + "target": "edit.pasteSpecial", + "excel": "Paste Linked Picture", + "note": "what=TBD(linked-picture)" + }, + { + "seq": "HVK", + "kind": "command", + "target": "edit.pasteSpecial", + "excel": "Paste Keep Source Formatting", + "note": "paste variant, params TBD: what=TBD(keep-source)" + }, + { + "seq": "HVM", + "kind": "command", + "target": "edit.pasteSpecial", + "excel": "Paste Destination Formatting", + "note": "paste variant, params TBD: what=TBD(dest)" + }, + { + "seq": "HVN", + "kind": "command", + "target": "edit.pasteSpecial", + "excel": "Paste Link", + "note": "paste variant, params TBD: what=TBD(link)" + }, + { + "seq": "HVO", + "kind": "command", + "target": "edit.pasteSpecial", + "excel": "Paste Formula and Formatting", + "note": "paste variant, params TBD: what=TBD(formula+formatting)" + }, + { + "seq": "HVP", + "kind": "command", + "target": "edit.paste", + "excel": "Paste", + "note": "" + }, + { + "seq": "HVR", + "kind": "command", + "target": "edit.pasteSpecial", + "excel": "Paste Formatting", + "note": "paste variant, params TBD: what=formats" + }, + { + "seq": "HVT", + "kind": "command", + "target": "edit.pasteSpecial", + "excel": "Paste Transpose", + "note": "paste variant, params TBD: what=transpose" + }, + { + "seq": "HVU", + "kind": "command", + "target": "edit.pasteSpecial", + "excel": "Paste Picture", + "note": "what=TBD(picture)" + }, + { + "seq": "HVV", + "kind": "command", + "target": "edit.pasteSpecial", + "excel": "Paste Values", + "note": "paste variant, params TBD: what=values" + }, + { + "seq": "HVW", + "kind": "command", + "target": "edit.pasteSpecial", + "excel": "Paste Keep Source Column Widths", + "note": "paste variant, params TBD: what=TBD(col-widths)" + }, + { + "seq": "HW", + "kind": "continue", + "excel": "Wrap Text Menu", + "note": "group level: containment(Wrap Text)" + }, + { + "seq": "HWS", + "kind": "command", + "target": "home.shrinkToFit", + "pending": true, + "excel": "Shrink to Fit", + "note": "Shrink to Fit; reserved until the command lands" + }, + { + "seq": "HWW", + "kind": "command", + "target": "home.wrapText", + "excel": "Wrap Text", + "note": "" + }, + { + "seq": "HX", + "kind": "command", + "target": "edit.cut", + "excel": "Cut", + "note": "" + }, + { + "seq": "NC1", + "kind": "command", + "target": "insert.chart", + "excel": "Column Chart", + "note": "Column chart (kind TBD)" + }, + { + "seq": "NC2", + "kind": "command", + "target": "review.newComment", + "excel": "New Comment", + "note": "" + }, + { + "seq": "NCB", + "kind": "command", + "target": "insert.checkbox", + "excel": "Checkbox", + "note": "" + }, + { + "seq": "ND", + "kind": "command", + "target": "insert.chart", + "excel": "Scatter Chart", + "note": "Scatter (kind TBD)" + }, + { + "seq": "NE", + "kind": "command", + "target": "insert.equation", + "pending": true, + "excel": "Equations", + "note": "Equations; reserved until the command lands" + }, + { + "seq": "NF", + "kind": "continue", + "excel": "Online Pictures", + "note": "group level: containment(Picture)" + }, + { + "seq": "NFP", + "kind": "continue", + "excel": "From Picture Menu", + "note": "group level: containment(Picture)" + }, + { + "seq": "NFPF", + "kind": "command", + "target": "insert.picture", + "excel": "Picture From File", + "note": "containment(Picture)" + }, + { + "seq": "NH1", + "kind": "command", + "target": "pageLayout.headerFooter", + "excel": "Header & Footer", + "note": "" + }, + { + "seq": "NHF", + "kind": "command", + "target": "pageLayout.headerFooter", + "excel": "Header & Footer", + "note": "" + }, + { + "seq": "NHI", + "kind": "command", + "target": "insert.chart", + "excel": "Hierarchy Chart", + "note": "Hierarchy (kind TBD)" + }, + { + "seq": "NI1", + "kind": "command", + "target": "insert.chart", + "excel": "Waterfall Chart", + "note": "Waterfall (kind TBD)" + }, + { + "seq": "NI2", + "kind": "command", + "target": "insert.link", + "excel": "Link", + "note": "" + }, + { + "seq": "NJ", + "kind": "command", + "target": "`insert.object`", + "pending": true, + "excel": "Object", + "note": "insert.object missing; reserved until the command lands" + }, + { + "seq": "NM1T", + "kind": "command", + "target": "insert.picture", + "excel": "SmartArt Picture", + "note": "containment(Picture)" + }, + { + "seq": "NM2", + "kind": "command", + "target": "insert.chart", + "excel": "Map Chart", + "note": "Map (kind TBD)" + }, + { + "seq": "NN1", + "kind": "command", + "target": "insert.chart", + "excel": "Line Chart", + "note": "Line chart (kind TBD)" + }, + { + "seq": "NNS", + "kind": "command", + "target": "insert.icons", + "excel": "Icons", + "note": "" + }, + { + "seq": "NP", + "kind": "continue", + "excel": "Picture", + "note": "group level:" + }, + { + "seq": "NPB", + "kind": "command", + "target": "insert.picture", + "excel": "Picture from File", + "note": "containment(Picture)" + }, + { + "seq": "NPF", + "kind": "command", + "target": "insert.picture", + "excel": "Place in Cell", + "note": "Picture in cell (source TBD)" + }, + { + "seq": "NPI", + "kind": "command", + "target": "insert.picture", + "excel": "Place in Cell Menu", + "note": "Picture in cell (source TBD)" + }, + { + "seq": "NPO", + "kind": "command", + "target": "insert.picture", + "excel": "Place over Cells Menu", + "note": "Picture over cells (source TBD)" + }, + { + "seq": "NQ", + "kind": "command", + "target": "insert.chart", + "excel": "Pie Chart", + "note": "Pie (kind TBD)" + }, + { + "seq": "NR", + "kind": "command", + "target": "insert.recommendedCharts", + "excel": "Recommended Charts", + "note": "" + }, + { + "seq": "NSA", + "kind": "command", + "target": "insert.chart", + "excel": "Statistical Chart", + "note": "Statistical chart (kind TBD)" + }, + { + "seq": "NSC", + "kind": "command", + "target": "insert.screenshot", + "pending": true, + "excel": "Screenshot Menu", + "note": "Screenshot; reserved until the command lands" + }, + { + "seq": "NSD", + "kind": "command", + "target": "insert.chart", + "excel": "Combo Chart", + "note": "Combo (kind TBD)" + }, + { + "seq": "NSF", + "kind": "command", + "target": "`insert.slicer`", + "pending": true, + "excel": "Slicer", + "note": "insert.slicer missing (gap #8); reserved until the command lands" + }, + { + "seq": "NSH", + "kind": "command", + "target": "insert.shape", + "excel": "Shapes", + "note": "" + }, + { + "seq": "NSP", + "kind": "command", + "target": "insert.recommendedPivotTables", + "excel": "Recommended PivotTables", + "note": "" + }, + { + "seq": "NST", + "kind": "command", + "target": "`insert.timeline`", + "pending": true, + "excel": "Timeline", + "note": "insert.timeline missing (gap #8); reserved until the command lands" + }, + { + "seq": "NSZ", + "kind": "command", + "target": "insert.pivotChart", + "pending": true, + "excel": "PivotChart", + "note": "PivotChart; reserved until the command lands" + }, + { + "seq": "NT", + "kind": "command", + "target": "insert.table", + "excel": "Table", + "note": "" + }, + { + "seq": "NU", + "kind": "command", + "target": "insert.symbol", + "excel": "Symbols", + "note": "containment(Symbol)" + }, + { + "seq": "NV", + "kind": "command", + "target": "insert.pivotTable", + "excel": "PivotTable", + "note": "" + }, + { + "seq": "NW", + "kind": "command", + "target": "insert.wordArt", + "pending": true, + "excel": "WordArt", + "note": "WordArt; reserved until the command lands" + }, + { + "seq": "NX", + "kind": "command", + "target": "insert.textBox", + "excel": "Text Box", + "note": "" + }, + { + "seq": "NZK", + "kind": "continue", + "excel": "Sparklines Menu", + "note": "group level:" + }, + { + "seq": "NZKSL", + "kind": "command", + "target": "insert.sparkline", + "excel": "Line Sparkline", + "note": "" + }, + { + "seq": "NZKSO", + "kind": "command", + "target": "insert.sparkline", + "excel": "Column Sparkline", + "note": "" + }, + { + "seq": "NZKSW", + "kind": "command", + "target": "insert.sparkline", + "excel": "Win/Loss Sparkline", + "note": "" + }, + { + "seq": "NZTX", + "kind": "command", + "target": "insert.textBox", + "excel": "Text Box", + "note": "" + }, + { + "seq": "PAE", + "kind": "command", + "target": "arrange.sendBackward", + "excel": "Send Backward", + "note": "" + }, + { + "seq": "PAF", + "kind": "command", + "target": "arrange.bringForward", + "excel": "Bring Forward", + "note": "" + }, + { + "seq": "PB", + "kind": "continue", + "excel": "Breaks", + "note": "group level:" + }, + { + "seq": "PBI", + "kind": "command", + "target": "pageLayout.breaks", + "excel": "Insert Page Break", + "note": "Insert Page Break" + }, + { + "seq": "PBR", + "kind": "command", + "target": "pageLayout.breaks", + "excel": "Remove Page Break", + "note": "Remove Page Break" + }, + { + "seq": "PG", + "kind": "command", + "target": "pageLayout.background", + "excel": "Background", + "note": "" + }, + { + "seq": "PI", + "kind": "command", + "target": "pageLayout.printTitles", + "excel": "Print Titles", + "note": "" + }, + { + "seq": "PM", + "kind": "continue", + "excel": "Margins", + "note": "group level:" + }, + { + "seq": "PMA", + "kind": "command", + "target": "pageLayout.margins", + "excel": "Custom Margins", + "note": "containment(Margins)" + }, + { + "seq": "PO", + "kind": "command", + "target": "pageLayout.orientation", + "excel": "Orientation", + "note": "" + }, + { + "seq": "PPG", + "kind": "command", + "target": "pageLayout.printGridlines", + "excel": "Print Gridlines", + "note": "" + }, + { + "seq": "PPH", + "kind": "command", + "target": "pageLayout.printHeadings", + "excel": "Print Headings", + "note": "" + }, + { + "seq": "PR", + "kind": "continue", + "excel": "Print Area", + "note": "group level:" + }, + { + "seq": "PRS", + "kind": "command", + "target": "pageLayout.printArea", + "excel": "Set Print Area", + "note": "" + }, + { + "seq": "PSP", + "kind": "command", + "target": "pageLayout.pageSetup", + "excel": "Page Setup", + "note": "" + }, + { + "seq": "PSZ", + "kind": "command", + "target": "pageLayout.size", + "excel": "Size", + "note": "" + }, + { + "seq": "PTC", + "kind": "command", + "target": "pageLayout.themeColors", + "excel": "Theme Colors", + "note": "containment(Colors)" + }, + { + "seq": "PTE", + "kind": "command", + "target": "pageLayout.themeEffects", + "excel": "Theme Effects", + "note": "containment(Effects)" + }, + { + "seq": "PTF", + "kind": "command", + "target": "pageLayout.themeFonts", + "excel": "Theme Fonts", + "note": "containment(Fonts)" + }, + { + "seq": "PTH", + "kind": "continue", + "excel": "Themes", + "note": "group level:" + }, + { + "seq": "PTHB", + "kind": "command", + "target": "pageLayout.theme", + "excel": "Browse Themes", + "note": "containment(Themes)" + }, + { + "seq": "PVG", + "kind": "command", + "target": "view.gridlines", + "excel": "View Gridlines", + "note": "" + }, + { + "seq": "PVH", + "kind": "command", + "target": "view.headings", + "excel": "View Headings", + "note": "" + }, + { + "seq": "MA", + "kind": "continue", + "excel": "Remove Arrows Menu", + "note": "group level: containment(Remove Arrows)" + }, + { + "seq": "MAA", + "kind": "command", + "target": "formulas.removeArrows", + "pending": true, + "excel": "Remove All Arrows", + "note": "Remove All Arrows; reserved until the command lands" + }, + { + "seq": "MAP", + "kind": "command", + "target": "formulas.removePrecedentArrows", + "pending": true, + "excel": "Remove Precedent Arrows", + "note": "Remove Precedent Arrows; reserved until the command lands" + }, + { + "seq": "MB", + "kind": "command", + "target": "formulas.calculateNow", + "excel": "Calculate Now", + "note": "" + }, + { + "seq": "MC", + "kind": "command", + "target": "formulas.createFromSelection", + "excel": "Create From Selection", + "note": "" + }, + { + "seq": "MD", + "kind": "command", + "target": "formulas.traceDependents", + "excel": "Trace Dependents", + "note": "" + }, + { + "seq": "ME", + "kind": "continue", + "excel": "Date & Time Menu", + "note": "group level: containment(Date & Time)" + }, + { + "seq": "MEF", + "kind": "command", + "target": "formulas.insertFunction", + "excel": "Date & Time - Insert Function", + "note": "containment(Insert Function)" + }, + { + "seq": "MF", + "kind": "command", + "target": "formulas.insertFunction", + "excel": "Insert Function", + "note": "" + }, + { + "seq": "MG", + "kind": "continue", + "excel": "Math & Trig Menu", + "note": "group level: containment(Math & Trig)" + }, + { + "seq": "MGF", + "kind": "command", + "target": "formulas.insertFunction", + "excel": "Math & Trig - Insert Function", + "note": "containment(Insert Function)" + }, + { + "seq": "MH", + "kind": "command", + "target": "formulas.showFormulas", + "excel": "Show Formulas", + "note": "" + }, + { + "seq": "MI", + "kind": "continue", + "excel": "Financial Menu", + "note": "group level: containment(Financial)" + }, + { + "seq": "MIF", + "kind": "command", + "target": "formulas.insertFunction", + "excel": "Financial - Insert Function", + "note": "containment(Insert Function)" + }, + { + "seq": "MJ", + "kind": "command", + "target": "formulas.calculateSheet", + "excel": "Calculate Sheet", + "note": "" + }, + { + "seq": "MK", + "kind": "continue", + "excel": "Error Checking Menu", + "note": "group level: containment(Error Checking)" + }, + { + "seq": "MKK", + "kind": "command", + "target": "formulas.errorChecking", + "excel": "Error Checking", + "note": "" + }, + { + "seq": "ML", + "kind": "continue", + "excel": "Logical Menu", + "note": "group level: containment(Logical)" + }, + { + "seq": "MLF", + "kind": "command", + "target": "formulas.insertFunction", + "excel": "Logical - Insert Function", + "note": "containment(Insert Function)" + }, + { + "seq": "MM", + "kind": "command", + "target": "formulas.defineName", + "excel": "Define Name", + "note": "" + }, + { + "seq": "MN", + "kind": "command", + "target": "formulas.nameManager", + "excel": "Name Manager", + "note": "" + }, + { + "seq": "MO", + "kind": "continue", + "excel": "Lookup & Reference Menu", + "note": "group level: containment(Lookup & Reference)" + }, + { + "seq": "MOF", + "kind": "command", + "target": "formulas.lookupReference", + "excel": "Lookup & Reference - Insert Function", + "note": "containment(Lookup & Reference)" + }, + { + "seq": "MP", + "kind": "command", + "target": "formulas.tracePrecedents", + "excel": "Trace Precedents", + "note": "" + }, + { + "seq": "MQ", + "kind": "continue", + "excel": "More Functions Menu", + "note": "group level: containment(More Functions)" + }, + { + "seq": "MQCF", + "kind": "command", + "target": "formulas.insertFunction", + "excel": "Cube - Insert Function", + "note": "containment(Insert Function)" + }, + { + "seq": "MQEF", + "kind": "command", + "target": "formulas.insertFunction", + "excel": "Engineering - Insert Function", + "note": "containment(Insert Function)" + }, + { + "seq": "MQIF", + "kind": "command", + "target": "formulas.insertFunction", + "excel": "Information - Insert Function", + "note": "containment(Insert Function)" + }, + { + "seq": "MQOF", + "kind": "command", + "target": "formulas.insertFunction", + "excel": "Compatibility - Insert Function", + "note": "containment(Insert Function)" + }, + { + "seq": "MQSF", + "kind": "command", + "target": "formulas.insertFunction", + "excel": "Statistical - Insert Function", + "note": "containment(Insert Function)" + }, + { + "seq": "MQWF", + "kind": "command", + "target": "formulas.insertFunction", + "excel": "Web - Insert Function", + "note": "containment(Insert Function)" + }, + { + "seq": "MR", + "kind": "continue", + "excel": "Recently Used Menu", + "note": "group level: containment(Recently Used)" + }, + { + "seq": "MRF", + "kind": "command", + "target": "formulas.insertFunction", + "excel": "Recently Used - Insert Function", + "note": "containment(Insert Function)" + }, + { + "seq": "MS", + "kind": "continue", + "excel": "Use in Formula Menu", + "note": "group level: containment(Use in Formula)" + }, + { + "seq": "MSP", + "kind": "command", + "target": "edit.pasteSpecial", + "excel": "Paste Names", + "note": "paste-variant TBD" + }, + { + "seq": "MT", + "kind": "continue", + "excel": "Text Menu", + "note": "group level: containment(Text)" + }, + { + "seq": "MTF", + "kind": "command", + "target": "formulas.insertFunction", + "excel": "Text - Insert Function", + "note": "containment(Insert Function)" + }, + { + "seq": "MU", + "kind": "continue", + "excel": "AutoSum Menu", + "note": "group level:" + }, + { + "seq": "MUA", + "kind": "command", + "target": "formulas.autoSum", + "excel": "Average", + "note": "AutoSum: Average (variant TBD)" + }, + { + "seq": "MUC", + "kind": "command", + "target": "formulas.autoSum", + "excel": "Count Numbers", + "note": "AutoSum: Count (variant TBD)" + }, + { + "seq": "MUF", + "kind": "command", + "target": "formulas.moreFunctions", + "excel": "More Functions (AutoSum)", + "note": "containment(More Functions)" + }, + { + "seq": "MUI", + "kind": "command", + "target": "formulas.autoSum", + "excel": "Min", + "note": "AutoSum: Min (variant TBD)" + }, + { + "seq": "MUM", + "kind": "command", + "target": "formulas.autoSum", + "excel": "Max", + "note": "AutoSum: Max (variant TBD)" + }, + { + "seq": "MUS", + "kind": "command", + "target": "formulas.autoSum", + "excel": "Sum", + "note": "" + }, + { + "seq": "MV", + "kind": "command", + "target": "formulas.evaluateFormula", + "excel": "Evaluate Formula", + "note": "" + }, + { + "seq": "MW", + "kind": "command", + "target": "formulas.watchWindow", + "excel": "Watch Window", + "note": "" + }, + { + "seq": "MX", + "kind": "continue", + "excel": "Calculation Options Menu", + "note": "group level: containment(Calculation Options)" + }, + { + "seq": "MXA", + "kind": "command", + "target": "formulas.calculationOptions", + "excel": "Automatic Calculation", + "note": "Calculation options: Automatic" + }, + { + "seq": "MXM", + "kind": "command", + "target": "formulas.calculationOptions", + "excel": "Manual Calculation", + "note": "Calculation options: Manual" + }, + { + "seq": "MXP", + "kind": "command", + "target": "formulas.calculationOptions", + "excel": "Partial Calculation", + "note": "Calculation options: Partial" + }, + { + "seq": "AB", + "kind": "command", + "target": "data.subtotal", + "excel": "Subtotal", + "note": "" + }, + { + "seq": "AC", + "kind": "command", + "target": "data.clearFilter", + "excel": "Clear Filter", + "note": "" + }, + { + "seq": "AD", + "kind": "command", + "target": "data.consolidate", + "excel": "Consolidate", + "note": "" + }, + { + "seq": "AE", + "kind": "command", + "target": "data.textToColumns", + "excel": "Text to Columns", + "note": "" + }, + { + "seq": "AF1", + "kind": "continue", + "excel": "Data from Picture Menu", + "note": "group level: feature gap; reserved until the command lands" + }, + { + "seq": "AF1C", + "kind": "command", + "target": "insert.picture", + "excel": "Picture from Clipboard (source TBD)" + }, + { + "seq": "AF1P", + "kind": "command", + "target": "insert.picture", + "excel": "Picture from File (source TBD)" + }, + { + "seq": "AFA", + "kind": "command", + "target": "data.fromAccess", + "pending": true, + "excel": "Get External Data: From Access", + "note": "gap #12 Get & Transform; reserved until the command lands" + }, + { + "seq": "AFC", + "kind": "command", + "target": "`data.forecastSheet`", + "pending": true, + "excel": "Forecast Sheet", + "note": "IN FLIGHT: vangel76 PR #325; reserved until the command lands" + }, + { + "seq": "AFE", + "kind": "command", + "target": "`data.analyzeData`", + "pending": true, + "excel": "Analyze Data", + "note": "AI feature GAP; reserved until the command lands" + }, + { + "seq": "AFF", + "kind": "command", + "target": "edit.flashFill", + "excel": "Flash Fill", + "note": "" + }, + { + "seq": "AFO", + "kind": "command", + "target": "data.fromOtherSources", + "pending": true, + "excel": "Get External Data: From Other Sources", + "note": "gap #12; reserved until the command lands" + }, + { + "seq": "AFT", + "kind": "command", + "target": "data.fromText", + "pending": true, + "excel": "Get External Data: From Text", + "note": "gap #12; reserved until the command lands" + }, + { + "seq": "AFW", + "kind": "command", + "target": "data.fromWeb", + "pending": true, + "excel": "Get External Data: From Web", + "note": "reserved until the command lands" + }, + { + "seq": "AG", + "kind": "continue", + "excel": "Group Menu", + "note": "group level: containment(Group)" + }, + { + "seq": "AGA", + "kind": "command", + "target": "data.autoOutline", + "pending": true, + "excel": "Auto Outline", + "note": "Auto Outline; reserved until the command lands" + }, + { + "seq": "AGG", + "kind": "command", + "target": "data.group", + "excel": "Group", + "note": "" + }, + { + "seq": "AH", + "kind": "command", + "target": "data.hideDetail", + "excel": "Hide Detail", + "note": "" + }, + { + "seq": "AJ", + "kind": "command", + "target": "data.showDetail", + "excel": "Show Detail", + "note": "" + }, + { + "seq": "AK", + "kind": "command", + "target": "data.queriesConnections", + "excel": "Edit Links", + "note": "Edit Links (Queries & Connections);" + }, + { + "seq": "AM", + "kind": "command", + "target": "data.removeDuplicates", + "excel": "Remove Duplicates", + "note": "" + }, + { + "seq": "AO", + "kind": "command", + "target": "data.queriesConnections", + "excel": "Queries & Connections", + "note": "" + }, + { + "seq": "AP1", + "kind": "command", + "target": "file.properties", + "excel": "Properties", + "note": "" + }, + { + "seq": "APN", + "kind": "continue", + "excel": "Get Data (Power Query) Menu", + "note": "group level: Power Query variants = GAP" + }, + { + "seq": "APND", + "kind": "command", + "target": "data.fromDatabase", + "pending": true, + "excel": "From Database (Microsoft Query)", + "note": "gap #12; reserved until the command lands" + }, + { + "seq": "APNE", + "kind": "command", + "target": "data.powerQueryEditor", + "pending": true, + "excel": "Launch Power Query Editor", + "note": "gap #12; reserved until the command lands" + }, + { + "seq": "APNG", + "kind": "command", + "target": "data.getData", + "excel": "Get Data (Power Query)", + "note": "containment(Get Data)" + }, + { + "seq": "APNH", + "kind": "command", + "target": "data.fromHtml", + "pending": true, + "excel": "From HTML", + "note": "gap #12; reserved until the command lands" + }, + { + "seq": "APNL", + "kind": "command", + "target": "data.fromSqlServer", + "pending": true, + "excel": "From SQL Server ODBC", + "note": "gap #12; reserved until the command lands" + }, + { + "seq": "APNS", + "kind": "command", + "target": "data.dataSourceSettings", + "pending": true, + "excel": "Data Source Settings", + "note": "gap #12; reserved until the command lands" + }, + { + "seq": "APNT", + "kind": "command", + "target": "data.fromTextLegacy", + "pending": true, + "excel": "From Text (Legacy)", + "note": "gap #12; reserved until the command lands" + }, + { + "seq": "APR", + "kind": "command", + "target": "data.recentSources", + "pending": true, + "excel": "Recent Sources", + "note": "gap #12; reserved until the command lands" + }, + { + "seq": "APS", + "kind": "command", + "target": "data.queriesConnections", + "excel": "Show Queries", + "note": "" + }, + { + "seq": "APT", + "kind": "command", + "target": "data.fromTable", + "pending": true, + "excel": "From Table (query)", + "note": "gap #12; reserved until the command lands" + }, + { + "seq": "AQ", + "kind": "command", + "target": "data.advancedFilter", + "excel": "Advanced Filter", + "note": "" + }, + { + "seq": "AR", + "kind": "continue", + "note": "group: group: Queries & Connections" + }, + { + "seq": "ARA", + "kind": "command", + "target": "data.refreshAll", + "excel": "Refresh All", + "note": "" + }, + { + "seq": "ARC", + "kind": "command", + "target": "data.cancelRefresh", + "pending": true, + "excel": "Cancel Refresh", + "note": "gap #12; reserved until the command lands" + }, + { + "seq": "ARO", + "kind": "command", + "target": "data.connectionProperties", + "pending": true, + "excel": "Connection Properties", + "note": "gap #12; reserved until the command lands" + }, + { + "seq": "ARR", + "kind": "command", + "target": "pivot.refresh", + "excel": "Refresh", + "note": "" + }, + { + "seq": "ARS", + "kind": "command", + "target": "data.refreshStatus", + "pending": true, + "excel": "Refresh Status", + "note": "gap #12; reserved until the command lands" + }, + { + "seq": "ASA", + "kind": "command", + "target": "data.sortAscending", + "excel": "Sort A to Z", + "note": "" + }, + { + "seq": "ASD", + "kind": "command", + "target": "data.sortDescending", + "excel": "Sort Z to A", + "note": "" + }, + { + "seq": "ASS", + "kind": "command", + "target": "data.sort", + "excel": "Sort", + "note": "" + }, + { + "seq": "AT", + "kind": "command", + "target": "data.filter", + "excel": "Filter", + "note": "" + }, + { + "seq": "AU", + "kind": "continue", + "excel": "Ungroup Menu", + "note": "group level: containment(Ungroup)" + }, + { + "seq": "AUC", + "kind": "command", + "target": "data.clearOutline", + "pending": true, + "excel": "Clear Outline", + "note": "feature gap; reserved until the command lands" + }, + { + "seq": "AUU", + "kind": "command", + "target": "data.ungroup", + "excel": "Ungroup", + "note": "" + }, + { + "seq": "AV", + "kind": "continue", + "excel": "Data Validation Menu", + "note": "group level: containment(Data Validation)" + }, + { + "seq": "AVI", + "kind": "command", + "target": "data.circleInvalid", + "excel": "Circle Invalid Data", + "note": "" + }, + { + "seq": "AVR", + "kind": "command", + "target": "data.clearValidationCircles", + "pending": true, + "excel": "Clear Validation Circles", + "note": "reserved until the command lands" + }, + { + "seq": "AVV", + "kind": "command", + "target": "data.validation", + "excel": "Data Validation", + "note": "" + }, + { + "seq": "AW", + "kind": "continue", + "note": "group: group: What-If (goalSeek/scenarioManager/dataTable)" + }, + { + "seq": "AWG", + "kind": "command", + "target": "data.goalSeek", + "excel": "Goal Seek", + "note": "" + }, + { + "seq": "AWS", + "kind": "command", + "target": "data.scenarioManager", + "excel": "Scenario Manager", + "note": "" + }, + { + "seq": "AWT", + "kind": "command", + "target": "data.dataTable", + "excel": "Data Table", + "note": "" + }, + { + "seq": "AX", + "kind": "command", + "target": "data.existingConnections", + "pending": true, + "excel": "Existing Connections", + "note": "gap #12; reserved until the command lands" + }, + { + "seq": "AY", + "kind": "command", + "target": "data.reapply", + "excel": "Reapply Filter", + "note": "containment(Reapply)" + }, + { + "seq": "RA1", + "kind": "command", + "target": "review.checkAccessibility", + "excel": "Check Accessibility", + "note": "" + }, + { + "seq": "RA2", + "kind": "command", + "target": "review.showComments", + "pending": true, + "excel": "Show All Comments", + "note": "Show All Comments; reserved until the command lands" + }, + { + "seq": "RC", + "kind": "command", + "target": "review.newComment", + "excel": "New Comment", + "note": "" + }, + { + "seq": "RD", + "kind": "command", + "target": "review.deleteComment", + "excel": "Delete Comment", + "note": "" + }, + { + "seq": "RG", + "kind": "command", + "target": "review.showChanges", + "pending": true, + "excel": "Track Changes", + "note": "reserved until the command lands" + }, + { + "seq": "RL", + "kind": "command", + "target": "`review.translate`", + "pending": true, + "excel": "Translate", + "note": "feature gap; reserved until the command lands" + }, + { + "seq": "RN", + "kind": "command", + "target": "review.nextComment", + "pending": true, + "excel": "Next Comment", + "note": "Next Comment; reserved until the command lands" + }, + { + "seq": "RO", + "kind": "command", + "target": "review.protectWorkbook", + "excel": "Protect and Share Workbook" + }, + { + "seq": "RPS", + "kind": "command", + "target": "review.protectSheet", + "excel": "Protect Sheet", + "note": "" + }, + { + "seq": "RPW", + "kind": "command", + "target": "review.protectWorkbook", + "excel": "Protect Workbook", + "note": "" + }, + { + "seq": "RRS", + "kind": "command", + "target": "`review.smartLookup`", + "pending": true, + "excel": "Smart Lookup", + "note": "feature gap; reserved until the command lands" + }, + { + "seq": "RS", + "kind": "command", + "target": "review.spelling", + "excel": "Spelling", + "note": "" + }, + { + "seq": "RTN", + "kind": "command", + "target": "review.newNote", + "excel": "New Note", + "note": "" + }, + { + "seq": "RV", + "kind": "command", + "target": "review.previousComment", + "pending": true, + "excel": "Previous Comment", + "note": "Previous Comment; reserved until the command lands" + }, + { + "seq": "RW", + "kind": "command", + "target": "review.shareWorkbook", + "pending": true, + "excel": "Share Workbook", + "note": "reserved until the command lands" + }, + { + "seq": "WA", + "kind": "command", + "target": "view.arrangeAll", + "excel": "Arrange All", + "note": "" + }, + { + "seq": "WB", + "kind": "command", + "target": "view.sideBySide", + "pending": true, + "excel": "View Side by Side", + "note": "reserved until the command lands" + }, + { + "seq": "WC", + "kind": "command", + "target": "view.customViews", + "excel": "Custom Views", + "note": "" + }, + { + "seq": "WF", + "kind": "continue", + "excel": "Freeze Panes Menu", + "note": "group level:" + }, + { + "seq": "WFC", + "kind": "command", + "target": "view.freezeFirstColumn", + "excel": "Freeze First Column", + "note": "" + }, + { + "seq": "WFF", + "kind": "command", + "target": "view.freezePanes", + "excel": "Freeze Panes", + "note": "" + }, + { + "seq": "WFR", + "kind": "command", + "target": "view.freezeTopRow", + "excel": "Freeze Top Row", + "note": "" + }, + { + "seq": "WG", + "kind": "command", + "target": "view.zoomToSelection", + "excel": "Zoom To Selection", + "note": "" + }, + { + "seq": "WH", + "kind": "command", + "target": "view.hideWindow", + "excel": "Hide Window", + "note": "" + }, + { + "seq": "WI", + "kind": "command", + "target": "view.pageBreakPreview", + "excel": "Page Break Preview", + "note": "" + }, + { + "seq": "WJ", + "kind": "command", + "target": "view.zoom", + "excel": "Zoom To 100%", + "note": "" + }, + { + "seq": "WL", + "kind": "command", + "target": "view.normal", + "excel": "Normal View", + "note": "containment(Normal)" + }, + { + "seq": "WM", + "kind": "continue", + "excel": "Macros Menu", + "note": "group level: containment(Macros)" + }, + { + "seq": "WMR", + "kind": "command", + "target": "view.macros", + "excel": "Record Macro", + "note": "Record Macro (macros menu)" + }, + { + "seq": "WMV", + "kind": "command", + "target": "view.macros", + "excel": "View Macros", + "note": "containment(Macros)" + }, + { + "seq": "WN", + "kind": "command", + "target": "view.newWindow", + "excel": "New Window", + "note": "" + }, + { + "seq": "WP", + "kind": "command", + "target": "view.pageLayout", + "excel": "Page Layout View", + "note": "" + }, + { + "seq": "WQ", + "kind": "command", + "target": "view.zoom", + "excel": "Zoom", + "note": "" + }, + { + "seq": "WR", + "kind": "command", + "target": "view.ruler", + "excel": "Ruler", + "note": "" + }, + { + "seq": "WS", + "kind": "command", + "target": "view.split", + "excel": "Split", + "note": "" + }, + { + "seq": "WT", + "kind": "command", + "target": "view.resetWindowPosition", + "pending": true, + "excel": "Reset Window Position", + "note": "reserved until the command lands" + }, + { + "seq": "WU", + "kind": "command", + "target": "view.unhideWindow", + "excel": "Unhide Window", + "note": "" + }, + { + "seq": "WVC", + "kind": "command", + "target": "view.focusCell", + "pending": true, + "excel": "Focus Cell Menu", + "note": "Focus Cell; reserved until the command lands" + }, + { + "seq": "WVF", + "kind": "command", + "target": "view.formulaBar", + "pending": true, + "excel": "Toggle Formula Bar", + "note": "Toggle Formula Bar; reserved until the command lands" + }, + { + "seq": "WVH", + "kind": "command", + "target": "view.headings", + "excel": "Toggle Headings", + "note": "containment(Headings)" + }, + { + "seq": "WVL", + "kind": "command", + "target": "view.synchronousScrolling", + "pending": true, + "excel": "Synchronous Scrolling", + "note": "Synchronous Scrolling; reserved until the command lands" + }, + { + "seq": "WVN", + "kind": "command", + "target": "view.navigation", + "pending": true, + "excel": "Navigation", + "note": "Navigation pane; reserved until the command lands" + }, + { + "seq": "WVR", + "kind": "command", + "target": "view.ruler", + "excel": "Ruler", + "note": "" + }, + { + "seq": "WVV", + "kind": "command", + "target": "view.sideBySide", + "pending": true, + "excel": "View Side by Side", + "note": "reserved until the command lands" + }, + { + "seq": "WW", + "kind": "command", + "target": "view.switchWindows", + "excel": "Switch Windows", + "note": "" + }, + { + "seq": "JAM", + "kind": "command", + "target": "chart.formatSelection", + "excel": "Chart format: Format Selection pane", + "note": "containment(Format Selection)" + }, + { + "seq": "JCA", + "kind": "command", + "target": "chart.addElement", + "excel": "Chart: Add Chart Element", + "note": "containment(Add Chart Element)" + }, + { + "seq": "JCC", + "kind": "command", + "target": "chart.changeType", + "excel": "Chart: Change Chart Type", + "note": "containment(Change Chart Type)" + }, + { + "seq": "JTS", + "kind": "command", + "target": "table.style", + "excel": "Table: table style", + "note": "" + }, + { + "seq": "JTV", + "kind": "command", + "target": "table.summarizePivot", + "excel": "Table: Summarize with PivotTable", + "note": "containment(Summarize with PivotTable)" + }, + { + "seq": "FA", + "kind": "command", + "excel": "Save / Save As page", + "note": "fires immediately in Excel; deeper aliases dropped as unreachable", + "target": "file.saveAs" + }, + { + "seq": "FC", + "kind": "command", + "target": "file.close", + "excel": "Close workbook" + }, + { + "seq": "FD", + "kind": "command", + "target": "file.account", + "pending": true, + "excel": "Account page", + "note": "Account page; reserved until the command lands" + }, + { + "seq": "FEA", + "kind": "command", + "target": "file.exportPdf", + "excel": "Export: create PDF/XPS", + "note": "Export: create PDF/XPS" + }, + { + "seq": "FEC", + "kind": "command", + "target": "file.saveAs", + "excel": "Export: change file type", + "note": "Export: change file type" + }, + { + "seq": "FH", + "kind": "command", + "target": "file.home", + "pending": true, + "excel": "File Home page (recent/pinned/shared/new blank)", + "note": "File Home page; reserved until the command lands" + }, + { + "seq": "FI", + "kind": "command", + "excel": "Info page", + "note": "fires immediately in Excel; deeper aliases dropped as unreachable", + "target": "file.properties" + }, + { + "seq": "FN", + "kind": "command", + "target": "file.new", + "excel": "New page", + "note": "New page" + }, + { + "seq": "FO", + "kind": "command", + "excel": "Open page", + "note": "fires immediately in Excel; deeper aliases dropped as unreachable", + "target": "file.open" + }, + { + "seq": "FP", + "kind": "command", + "target": "file.print", + "excel": "Print page", + "note": "containment(Print)" + }, + { + "seq": "FT", + "kind": "command", + "target": "file.options", + "pending": true, + "excel": "Options dialog", + "note": "Options dialog; reserved until the command lands" + }, + { + "seq": "Q", + "kind": "command", + "target": "ui.search", + "pending": true, + "excel": "Search / Tell Me", + "note": "Alt+Q search box does not exist yet (issue #49)" + }, + { + "seq": "6", + "kind": "command", + "target": "qat.6", + "pending": true, + "excel": "Quick Access Toolbar position 6", + "note": "QAT navigation does not exist yet" + }, + { + "seq": "7", + "kind": "command", + "target": "qat.7", + "pending": true, + "excel": "Quick Access Toolbar position 7", + "note": "QAT navigation does not exist yet" + }, + { + "seq": "8", + "kind": "command", + "target": "qat.8", + "pending": true, + "excel": "Quick Access Toolbar position 8", + "note": "QAT navigation does not exist yet" + }, + { + "seq": "9", + "kind": "command", + "target": "qat.9", + "pending": true, + "excel": "Quick Access Toolbar position 9", + "note": "QAT navigation does not exist yet" + } ] -} +} \ No newline at end of file diff --git a/crates/ui-egui/tests/keytips.rs b/crates/ui-egui/tests/keytips.rs index 7da90f5..81a1ff6 100644 --- a/crates/ui-egui/tests/keytips.rs +++ b/crates/ui-egui/tests/keytips.rs @@ -174,6 +174,7 @@ fn keyboard_opened_paste_menu_accepts_a_mouse_click_after_keytips_cancel() { #[test] fn legacy_paste_special_keeps_formulas_when_requested() { let mut h = harness(copied_row()); + // The legacy Edit route opens the dialog directly; F is a dialog mnemonic. sequence(&mut h, &[Key::E, Key::S], false); assert_eq!(h.state().dialog.as_ref().unwrap().name(), "pasteSpecial"); letter(&mut h, Key::F, false); @@ -306,6 +307,12 @@ fn tab_letters_switch_to_their_ribbon_tabs() { key(&mut h, Key::F10); // disarm assert_eq!(h.state().keytips.prefix(), None); } + // A terminal tab unit with no deeper sequences finishes and clears. + 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); + assert_eq!(h.state().ui.ribbon_tab, "Draw"); + assert_eq!(h.state().keytips.prefix(), None, "terminal tab units finish cleanly"); } #[test] diff --git a/xtask/src/keytips.rs b/xtask/src/keytips.rs index 286a043..baa498c 100644 --- a/xtask/src/keytips.rs +++ b/xtask/src/keytips.rs @@ -8,10 +8,34 @@ use std::path::Path; const TABS: &[&str] = &["Home", "Insert", "Draw", "Page Layout", "Formulas", "Data", "Review", "View", "Automate"]; +/// Format generated source through `rustfmt` so the checked-in file matches +/// the emitter byte-for-byte. +fn rustfmt(src: &str) -> Result { + use std::io::Write; + use std::process::{Command, Stdio}; + let mut child = Command::new("rustfmt") + .args(["--edition", "2024", "--emit", "stdout"]) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .map_err(|e| format!("spawn rustfmt: {e}"))?; + let stdin = child.stdin.as_mut().ok_or("rustfmt: failed to open stdin")?; + stdin.write_all(src.as_bytes()).map_err(|e| format!("write rustfmt stdin: {e}"))?; + let out = child.wait_with_output().map_err(|e| format!("wait rustfmt: {e}"))?; + if !out.status.success() { + return Err(format!("rustfmt failed: {}", String::from_utf8_lossy(&out.stderr))); + } + Ok(String::from_utf8_lossy(&out.stdout).into_owned()) +} + pub fn run(root: &Path, rest: &[&str]) -> Result<(), String> { let json_path = root.join("crates/ui-egui/src/keytips/keytips.json"); let out_path = root.join("crates/ui-egui/src/keytips/keytip_table/generated.rs"); - let generated = generate(&fs::read_to_string(&json_path).map_err(|e| format!("read {}: {e}", json_path.display()))?)?; + let raw = generate(&fs::read_to_string(&json_path).map_err(|e| format!("read {}: {e}", json_path.display()))?)?; + // The table is checked into the tree formatted, so emit through rustfmt: + // otherwise `--check` always fails against the fmt'd file. + let generated = rustfmt(&raw)?; if rest.contains(&"--check") { let on_disk = fs::read_to_string(&out_path).map_err(|e| format!("read {}: {e}", out_path.display()))?; if on_disk != generated { @@ -34,8 +58,8 @@ pub fn generate(source: &str) -> Result { for (i, entry) in seqs.iter().enumerate() { let at = format!("entry {}", i + 1); let seq = entry.get("seq").and_then(|v| v.as_str()).ok_or_else(|| format!("{at}: missing `seq`"))?; - if seq.is_empty() || seq.len() > 4 || !seq.bytes().all(|b| b.is_ascii_alphanumeric()) { - return Err(format!("{at}: seq {seq:?} must be 1-4 ASCII letters/digits")); + if seq.is_empty() || seq.len() > 6 || !seq.bytes().all(|b| b.is_ascii_alphanumeric()) { + return Err(format!("{at}: seq {seq:?} must be 1-6 ASCII letters/digits (Excel's longest are 5, e.g. sparkline paths)")); } if !seen.insert(seq.to_string()) { return Err(format!("{at}: duplicate seq {seq:?}"));