From fe85394cb97f5ba073a8c85ac7ee1b82db49c366 Mon Sep 17 00:00:00 2001 From: Micah Alpern Date: Thu, 11 Jun 2026 11:22:40 -0700 Subject: [PATCH] Fix Neovim Terminal detail page rendering the Home Row Mods editor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Micah's visual check of the new Neovim Terminal detail page (#893) found it rendering the HRM interactive keyboard instead of the pack's motions. Two compounding causes: 1. PackDetailView.isHomeRowModsPack was a heuristic — "≥4 bindings on home-row keys" — which misfires on any Vim-flavored pack: Neovim's bindings include j, k, l, d. Replaced with an exact associatedCollectionID == homeRowMods check. No other pack matched the heuristic (all other home-row-adjacent packs have empty bindings), so this is behavior-preserving outside the bug. 2. The Neovim pack carried 19 explicit PackBindingTemplates (added in #891 to satisfy testPackBindingsMatchCollectionMappings). The idiomatic shape for table-style packs (Vim Navigation, Mission Control, Numpad) is the opposite: EMPTY bindings, so Pack Detail falls through to MappingTableContent and renders the collection's mappings — single source of truth, identical styling to Rules. Reverted bindings to [] with a comment. The invariant test skips empty-bindings packs by design, so it stays green. Net: the Neovim detail page now shows the activation hint + the 19-motion table, exactly like Vim Navigation's page. Verified: PackCollectionIntegration / PackOwnership / PackRegistry suites green; deployed via quick-deploy for visual confirmation. Co-Authored-By: Claude Fable 5 --- .../Services/Packs/PackRegistry.swift | 28 ++++--------------- .../UI/Gallery/PackDetailView.swift | 10 +++---- 2 files changed, 9 insertions(+), 29 deletions(-) diff --git a/Sources/KeyPathAppKit/Services/Packs/PackRegistry.swift b/Sources/KeyPathAppKit/Services/Packs/PackRegistry.swift index 39ff9e611..aa6405a7f 100644 --- a/Sources/KeyPathAppKit/Services/Packs/PackRegistry.swift +++ b/Sources/KeyPathAppKit/Services/Packs/PackRegistry.swift @@ -752,29 +752,11 @@ public enum PackRegistry { category: "Navigation", iconSymbol: "terminal", quickSettings: [], - // Bindings mirror the collection's 19 mappings 1:1 — - // testPackBindingsMatchCollectionMappings enforces the count. - bindings: [ - PackBindingTemplate(input: "h", output: "left", title: "H → Left"), - PackBindingTemplate(input: "j", output: "down", title: "J → Down"), - PackBindingTemplate(input: "k", output: "up", title: "K → Up"), - PackBindingTemplate(input: "l", output: "right", title: "L → Right"), - PackBindingTemplate(input: "w", output: "A-right", title: "W → Word forward"), - PackBindingTemplate(input: "b", output: "A-left", title: "B → Word back"), - PackBindingTemplate(input: "e", output: "A-right", title: "E → End of word"), - PackBindingTemplate(input: "0", output: "M-left", title: "0 → Line start"), - PackBindingTemplate(input: "4", output: "M-right", title: "$ → Line end"), - PackBindingTemplate(input: "g", output: "M-up", title: "G → Document top/bottom"), - PackBindingTemplate(input: "/", output: "M-f", title: "/ → Find"), - PackBindingTemplate(input: "n", output: "M-g", title: "N → Next match"), - PackBindingTemplate(input: "y", output: "M-c", title: "Y → Yank (copy)"), - PackBindingTemplate(input: "p", output: "M-v", title: "P → Put (paste)"), - PackBindingTemplate(input: "x", output: "del", title: "X → Delete character"), - PackBindingTemplate(input: "r", output: "M-S-z", title: "R → Redo"), - PackBindingTemplate(input: "d", output: "A-bspc", title: "D → Delete previous word"), - PackBindingTemplate(input: "u", output: "M-z", title: "U → Undo"), - PackBindingTemplate(input: "o", output: "M-right ret", title: "O → Open line below"), - ], + // Intentionally empty: table-style packs (Vim Navigation, Mission + // Control, Numpad) leave bindings empty so Pack Detail renders the + // collection's mappings via MappingTableContent — the collection's + // 19 motions are the single source of truth. + bindings: [], associatedCollectionID: RuleCollectionIdentifier.neovimTerminal ) diff --git a/Sources/KeyPathAppKit/UI/Gallery/PackDetailView.swift b/Sources/KeyPathAppKit/UI/Gallery/PackDetailView.swift index 4102da924..7dc9bc78e 100644 --- a/Sources/KeyPathAppKit/UI/Gallery/PackDetailView.swift +++ b/Sources/KeyPathAppKit/UI/Gallery/PackDetailView.swift @@ -473,12 +473,10 @@ struct PackDetailView: View { /// interactive keyboard + modifier controls instead of the generic /// tap-hold picker. var isHomeRowModsPack: Bool { - let homeRowKeys: Set = ["a", "s", "d", "f", "j", "k", "l", "scln", ";"] - let inputs = Set(pack.bindings.map { $0.input.lowercased() }) - // Consider it a home-row pack if at least 4 of its bindings are on - // the home row — covers light and full variants without listing - // every combination. - return inputs.intersection(homeRowKeys).count >= 4 + // Exact match — the old ≥4-home-row-bindings heuristic misfired on + // any Vim-flavored pack whose bindings happen to use j/k/l/d + // (Neovim Terminal rendered the HRM editor as its detail body). + pack.associatedCollectionID == RuleCollectionIdentifier.homeRowMods } /// Match the pack to an existing `RuleCollection` that carries a