Skip to content

fix(settings): say why a shortcut with only Option or Shift is refused - #2462

Merged
datlechin merged 2 commits into
mainfrom
fix/shortcut-recorder-honesty
Aug 26, 2026
Merged

fix(settings): say why a shortcut with only Option or Shift is refused#2462
datlechin merged 2 commits into
mainfrom
fix/shortcut-recorder-honesty

Conversation

@datlechin

Copy link
Copy Markdown
Member

Found while investigating #2453.

The defect

BoundKey.init?(from:) requires Command or Control (or one of the four bare-recordable keys), so ⌥E, ⇧F and ⌥⇧E all return nil. handleRecordingEvent answered nil with a bare NSSound.beep() and nothing else: no alert, no message, and the field still showing the old combo. The user is left guessing whether the app registered the keystroke at all.

Worse, the app was telling them it should have worked. The recorder's own alert said:

This action needs a modifier key like ⌘ or . A plain key won't reach the menu reliably.

and docs/features/keyboard-shortcuts.mdx:273 said menu actions need "Cmd, Option, Ctrl, or Shift". Both name Option as sufficient. Neither is true.

The change

The capture rule is right and stays: Option and Shift qualify a combo, they never carry one, and a letter held with either alone is a text-input keystroke, not a shortcut. ⌥E is a dead key for accents. What was wrong is that the app promised otherwise and then refused in silence.

  • The recorder gained onUnusableModifiers, so a combo it cannot capture raises the existing Modifier Key Required alert instead of beeping.
  • The alert now says what actually works: "This action needs ⌘ or ⌃. Option and Shift can join them, but cannot hold a shortcut on their own."
  • The docs sentence is corrected to match.
  • optionAndShiftAloneAreNotRecordable pins the rule the alert now states, driving real NSEvents through BoundKey.init(from:) across six modifier combinations.

Verification

Step Result
verify.sh build PASS
verify.sh test (8 keyboard + menu suites) PASS, 48 executed, 48 passed
verify.sh lint TablePro TableProTests 0 violations
verify.sh docs PASS

Not fixed here, and why

The collateral hunt also flagged Clear Selection's recorder row. .clearSelection defaults to bare Escape, but menuKeyEquivalent(for:) rejects bare keys, so the Edit menu item never carries it, and KeyHandlingTableView.cancelOperation clears the selection whatever the binding says. Clearing the row does not stop Escape.

The obvious fix does not work. Gating cancelOperation on the binding breaks the menu path, because MainSplitViewController.clearSelection drives that same selector, so a non-Escape binding would fire the menu item into a gate that refuses it. Making Escape itself configurable means intercepting a key AppKit routes through interpretKeyEvents, in an area that has already shipped a regression (#1490). The remaining option, removing the row, is a product decision rather than a defect fix.

Reported rather than guessed at.

@mintlify

mintlify Bot commented Aug 26, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
TablePro 🟢 Ready View Preview Aug 26, 2026, 12:44 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Signed-off-by: Ngô Quốc Đạt <datlechin@gmail.com>
@datlechin
datlechin merged commit 6bd75d2 into main Aug 26, 2026
1 check passed
@datlechin
datlechin deleted the fix/shortcut-recorder-honesty branch August 26, 2026 14:56
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