Skip to content

Make every keyboard shortcut rebindable and drop the iTerm2 preset - #1241

Merged
h0x91b merged 2 commits into
mainfrom
feat/dev3-keyboard-shortcut-editor
Aug 3, 2026
Merged

Make every keyboard shortcut rebindable and drop the iTerm2 preset#1241
h0x91b merged 2 commits into
mainfrom
feat/dev3-keyboard-shortcut-editor

Conversation

@h0x91b

@h0x91b h0x91b commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Summary

Makes every app-level keyboard shortcut rebindable from Settings, and removes the "iTerm2 compatibility" preset in favour of always-on shortcuts you can change one at a time.

The keymap registry now dispatches

src/mainview/keymap.ts used to only document shortcuts — the combos were hand-written a second time as modifier conditions in a 320-line if/else chain in App.tsx, which made rebinding impossible without editing two places. Every branch is now matchesShortcut(e, "<id>"), and display strings are derived from the bindings instead of authored twice.

Bindings match KeyboardEvent.code (layout-independent) with an exact modifier set. A consequence: Mod is now strictly ⌘ on macOS, so the accidental (meta || ctrl) branches are gone and ⌃, / ⌃= / ⌃` reach the terminal where they belong.

Two slots per shortcut

Each shortcut carries a primary combo plus an optional alias, set independently, rather than one flat binding list where "the second way to press it" was an artifact of ordering. Overrides persist per slot — an absent slot keeps its default, null was deliberately emptied — under GlobalSettings.keyboardShortcuts, sparse, so a changed default still reaches everyone who left that row alone.

Settings → Keyboard

A new eighth Settings category. The key chips on each row are the control (no per-row "Change" button — 33 of those is button creep). Taking a combo someone else owns names them first and then empties only the slot that held it. Per-row reset, bulk reset behind confirm(), and a filter that matches the rendered combo as well as the name.

Seven structural shortcuts render read-only with a stated reason rather than being hidden: the g … chord sequences, the ⌘1–9 / ⇧⌘1–9 digit families, the hold-modifier task switcher, Esc, and ⌘R.

The iTerm2 preset is gone

It defaulted to on and existed only to switch four shortcuts off — something the editor now does per row. Deleted: TerminalKeymapPreset, GlobalSettings.terminalKeymap, src/mainview/terminal-keymaps.ts, and all three of its toggles (Settings, the ⓘ popover beside the terminal, and the native Terminal ▸ Keyboard Mode menu).

⌘D, ⌘⇧D, ⌘W and ⌘T are ordinary registry rows in the terminal conflict group, dispatched only while a terminal has focus. Pane navigation (formerly ⌘[ / ⌘]) is dropped rather than rebound: src/bun/tmux/config.ts already binds ⌥+arrows prefix-free, which also removes a latent collision where ⌘[ ran both app-level "back" and pane-focus in the same capture phase.

The ⓘ button now opens the unified ⌘/ overlay on its Terminal tab, which leads with those four combos read from the registry, replacing a partial hover popover.

Also

  • keymap-store.ts suspends all dispatch while the recorder is open — both listeners sit on window in the capture phase and the dispatcher registered first, so stopPropagation is too late and a module flag is the only reliable gate.
  • Contrast pass on both themes: text carrying meaning moved off --text-muted (the ramp's decorative tier, ~2.99:1 on the light settings surface) to --text-tertiary; the Save button moved to --accent-fill because white on --accent is only 2.98:1 in dark theme.
  • Help copy, the UX manifest, and docs/ux/UX_DECISIONS.md updated; decision records 195 and 196.

h0x91b added 2 commits August 3, 2026 14:04
Shortcuts were declared as data in keymap.ts but dispatched by hand-written
modifier conditions in App.tsx, so a combo lived in two places and could not be
rebound. keymap.ts now carries machine-readable bindings and every handler asks
matchesShortcut(e, id); display strings are derived from those bindings.

Settings gains a Keyboard category with a per-row combo recorder, conflict
detection that names the losing shortcut, per-row and bulk reset, and read-only
rows for structural bindings (g-chords, digit families, hold-modifier switcher,
Esc) that state why they are fixed. The tmux keymap preset moves there from
Terminal, and the reference overlay links to the editor.

The app modifier is now strictly platform-exact, so macOS Ctrl aliases for
Ctrl+, / Ctrl+= / Ctrl+` reach the terminal instead of the app.
… preset

Every shortcut now carries two independently-editable slots instead of a flat
binding list, so an alternative combo is something the user adds rather than an
artifact of list order. Overrides persist per slot, where an absent slot keeps
its default and null was deliberately emptied.

The opt-in iTerm2 keymap preset is deleted along with all three of its toggles
(Settings, the terminal info popover, and the native Terminal > Keyboard Mode
menu). Its four pane combos are ordinary registry rows in the terminal conflict
group, unbindable one at a time. Pane navigation is dropped rather than rebound:
tmux already binds Alt+arrows prefix-free, which also removes the Cmd+bracket
collision with app-level back/forward.

The terminal info button now opens the unified shortcuts overlay on its Terminal
tab, which leads with those four combos read from the registry.
@h0x91b
h0x91b enabled auto-merge (squash) August 3, 2026 11:06
@h0x91b
h0x91b merged commit ca6623d into main Aug 3, 2026
9 checks passed
@h0x91b
h0x91b deleted the feat/dev3-keyboard-shortcut-editor branch August 3, 2026 11:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant