Skip to content

(shortcuts): configurable session-nav keybindings; free Ctrl+Arrow - #47

Merged
JeanBaptisteRenard merged 2 commits into
mainfrom
feat/configurable-shortcuts
Jun 10, 2026
Merged

(shortcuts): configurable session-nav keybindings; free Ctrl+Arrow#47
JeanBaptisteRenard merged 2 commits into
mainfrom
feat/configurable-shortcuts

Conversation

@JeanBaptisteRenard

Copy link
Copy Markdown
Collaborator

Why

The session-nav arrow shortcut was bound to Ctrl/Cmd+Arrow, which hijacked Ctrl+Left/Right — the terminal word-jump everyone uses while editing. This frees those keys and makes all session-nav shortcuts user-configurable.

What

  • New default: arrow navigation moves to Ctrl/Cmd+Shift+Arrow (Shift, not Alt — Ctrl+Alt+Arrow is a common Linux workspace-switch binding). Ctrl+Left/Right word-jump is now free in the terminal.
  • Configurable: new Keyboard Shortcuts section in Global Settings with click-to-capture rebind buttons. Persisted under global.shortcuts, applied live (no restart).
  • Bracket nav (Ctrl/Cmd+Shift+[ / ]) and grid toggle (Ctrl/Cmd+Shift+G) unchanged as defaults but also rebindable.
Action Before After (default)
Navigate sessions / grid Ctrl+Arrow Ctrl+Shift+Arrow
Prev / next session Ctrl+Shift+[ / ] unchanged
Toggle grid Ctrl+Shift+G unchanged
Terminal word-jump hijacked Ctrl+Left/Right free

How

  • public/shortcuts.js (new) — single source of truth: DEFAULT_SHORTCUTS, SHORTCUT_DEFS, matchShortcut/normalizeShortcuts/formatBinding/captureBinding. Dual-mode (renderer <script> + require() in tests).
  • grid-view.js — live appShortcuts + setAppShortcuts; isSessionNavKey/handleSessionNavKey delegate to the matcher.
  • app.js / terminal-manager.js — grid-toggle via matchShortcut; load stored bindings at startup; window._applyShortcuts for live apply.
  • settings-panel.js + style.css — rebind UI.
  • eslint.config.js — register new cross-file globals + dedicated dual-mode block.

Tests

test/shortcuts.test.js — 10 unit tests, including the headline regression (bare Ctrl+Arrow is not a nav shortcut). task check green (0 errors).

🤖 Generated with Claude Code

The session-nav arrow shortcut hijacked Ctrl+Left/Right, robbing the
terminal of word-jump while editing. Move the default to Ctrl/Cmd+Shift+
Arrow (Shift, not Alt — Ctrl+Alt+Arrow is a common Linux workspace-switch
binding) and expose all session-nav bindings as re-bindable in Global
Settings.

- public/shortcuts.js: single source of truth (DEFAULT_SHORTCUTS,
  SHORTCUT_DEFS, matchShortcut/normalizeShortcuts/formatBinding/
  captureBinding); dual-mode (renderer <script> + require() in tests)
- grid-view.js: live appShortcuts + setAppShortcuts; isSessionNavKey/
  handleSessionNavKey delegate to the matcher
- app.js / terminal-manager.js: grid-toggle goes through matchShortcut;
  load stored bindings at startup; window._applyShortcuts for live apply
- settings-panel.js + style.css: 'Keyboard Shortcuts' section with
  click-to-capture rebind buttons (global scope), persisted under
  global.shortcuts, applied without restart
- eslint.config.js: register new cross-file globals + dedicated dual-mode
  block allowing the CJS export footer
- test/shortcuts.test.js: 10 unit tests incl. the Ctrl+Arrow regression
…fier

Review fixes for PR #47:
- MAJOR: the keydown capture listener lived on document and leaked app-wide
  if the settings viewer was dismissed mid-capture via any path that bypasses
  closeSettingsViewer (hideAllViewers, sidebar/tab clicks). Move the listeners
  onto the button element itself; a blur (incl. panel dismissal) cancels
  capture, and re-opening the viewer discards the old listeners with the
  replaced DOM — no app-wide keyboard interception is possible.
- MINOR: captureBinding now refuses a combo that holds the cross-modifier
  (Ctrl on mac / Meta elsewhere); matchShortcut rejects such events, so
  capturing it would have produced an unmatchable binding.
- doc: note shortcuts.js load-order dependency in index.html.
@JeanBaptisteRenard
JeanBaptisteRenard merged commit 9caf97d into main Jun 10, 2026
7 checks passed
@JeanBaptisteRenard
JeanBaptisteRenard deleted the feat/configurable-shortcuts branch June 10, 2026 15:36
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