Add setting to hide Cmd-hold shortcut hints (#765)

* Add setting to hide Cmd-hold shortcut hints

* Bump bonsplit for Cmd-hold pane hint toggle

* Document tagged app link format in agent notes

* Disable Ctrl pane hints when hold-hints toggle is off
This commit is contained in:
Lawrence Chen 2026-03-02 19:56:27 -08:00 committed by GitHub
parent 5bbdd87c29
commit 919f77b6dc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 125 additions and 27 deletions

View file

@ -16,6 +16,14 @@ After making code changes, always run the reload script with a tag to launch the
./scripts/reload.sh --tag fix-zsh-autosuggestions
```
When reporting a tagged reload result in chat, use this exact clickable format:
```markdown
=======================================================
[<tag-name>: file:///tmp/cmux-<tag-name>.app](file:///tmp/cmux-<tag-name>.app)
=======================================================
```
After making code changes, always run the build:
```bash

View file

@ -5810,8 +5810,12 @@ struct VerticalTabsSidebar: View {
enum SidebarCommandHintPolicy {
static let intentionalHoldDelay: TimeInterval = 0.30
static func shouldShowHints(for modifierFlags: NSEvent.ModifierFlags) -> Bool {
modifierFlags.intersection(.deviceIndependentFlagsMask) == [.command]
static func shouldShowHints(
for modifierFlags: NSEvent.ModifierFlags,
defaults: UserDefaults = .standard
) -> Bool {
ShortcutHintDebugSettings.showHintsOnCommandHoldEnabled(defaults: defaults) &&
modifierFlags.intersection(.deviceIndependentFlagsMask) == [.command]
}
static func isCurrentWindow(
@ -5832,9 +5836,10 @@ enum SidebarCommandHintPolicy {
hostWindowNumber: Int?,
hostWindowIsKey: Bool,
eventWindowNumber: Int?,
keyWindowNumber: Int?
keyWindowNumber: Int?,
defaults: UserDefaults = .standard
) -> Bool {
shouldShowHints(for: modifierFlags) &&
shouldShowHints(for: modifierFlags, defaults: defaults) &&
isCurrentWindow(
hostWindowNumber: hostWindowNumber,
hostWindowIsKey: hostWindowIsKey,
@ -5852,6 +5857,7 @@ enum ShortcutHintDebugSettings {
static let paneHintXKey = "shortcutHintPaneTabXOffset"
static let paneHintYKey = "shortcutHintPaneTabYOffset"
static let alwaysShowHintsKey = "shortcutHintAlwaysShow"
static let showHintsOnCommandHoldKey = "shortcutHintShowOnCommandHold"
static let defaultSidebarHintX = 0.0
static let defaultSidebarHintY = 0.0
@ -5860,12 +5866,20 @@ enum ShortcutHintDebugSettings {
static let defaultPaneHintX = 0.0
static let defaultPaneHintY = 0.0
static let defaultAlwaysShowHints = false
static let defaultShowHintsOnCommandHold = true
static let offsetRange: ClosedRange<Double> = -20...20
static func clamped(_ value: Double) -> Double {
min(max(value, offsetRange.lowerBound), offsetRange.upperBound)
}
static func showHintsOnCommandHoldEnabled(defaults: UserDefaults = .standard) -> Bool {
guard defaults.object(forKey: showHintsOnCommandHoldKey) != nil else {
return defaultShowHintsOnCommandHold
}
return defaults.bool(forKey: showHintsOnCommandHoldKey)
}
}
enum SidebarDragLifecycleNotification {

View file

@ -1313,6 +1313,7 @@ private enum DebugWindowConfigSnapshot {
shortcutHintPaneTabXOffset=\(String(format: "%.1f", doubleValue(defaults, key: ShortcutHintDebugSettings.paneHintXKey, fallback: ShortcutHintDebugSettings.defaultPaneHintX)))
shortcutHintPaneTabYOffset=\(String(format: "%.1f", doubleValue(defaults, key: ShortcutHintDebugSettings.paneHintYKey, fallback: ShortcutHintDebugSettings.defaultPaneHintY)))
shortcutHintAlwaysShow=\(boolValue(defaults, key: ShortcutHintDebugSettings.alwaysShowHintsKey, fallback: ShortcutHintDebugSettings.defaultAlwaysShowHints))
shortcutHintShowOnCommandHold=\(boolValue(defaults, key: ShortcutHintDebugSettings.showHintsOnCommandHoldKey, fallback: ShortcutHintDebugSettings.defaultShowHintsOnCommandHold))
"""
let backgroundPayload = """
@ -2746,6 +2747,8 @@ struct SettingsView: View {
@AppStorage("sidebarShowPullRequest") private var sidebarShowPullRequest = true
@AppStorage(BrowserLinkOpenSettings.openSidebarPullRequestLinksInCmuxBrowserKey)
private var openSidebarPullRequestLinksInCmuxBrowser = BrowserLinkOpenSettings.defaultOpenSidebarPullRequestLinksInCmuxBrowser
@AppStorage(ShortcutHintDebugSettings.showHintsOnCommandHoldKey)
private var showShortcutHintsOnCommandHold = ShortcutHintDebugSettings.defaultShowHintsOnCommandHold
@AppStorage("sidebarShowPorts") private var sidebarShowPorts = true
@AppStorage("sidebarShowLog") private var sidebarShowLog = true
@AppStorage("sidebarShowProgress") private var sidebarShowProgress = true
@ -3460,6 +3463,19 @@ struct SettingsView: View {
SettingsSectionHeader(title: "Keyboard Shortcuts")
SettingsCard {
SettingsCardRow(
"Show Cmd/Ctrl-Hold Shortcut Hints",
subtitle: showShortcutHintsOnCommandHold
? "Holding Cmd (sidebar/titlebar) or Ctrl/Cmd (pane tabs) shows shortcut hint pills."
: "Holding Cmd or Ctrl keeps shortcut hint pills hidden."
) {
Toggle("", isOn: $showShortcutHintsOnCommandHold)
.labelsHidden()
.controlSize(.small)
}
SettingsCardDivider()
let actions = KeyboardShortcutSettings.Action.allCases
ForEach(Array(actions.enumerated()), id: \.element.id) { index, action in
ShortcutSettingRow(action: action)
@ -3642,6 +3658,7 @@ struct SettingsView: View {
sidebarShowBranchDirectory = true
sidebarShowPullRequest = true
openSidebarPullRequestLinksInCmuxBrowser = BrowserLinkOpenSettings.defaultOpenSidebarPullRequestLinksInCmuxBrowser
showShortcutHintsOnCommandHold = ShortcutHintDebugSettings.defaultShowHintsOnCommandHold
sidebarShowPorts = true
sidebarShowLog = true
sidebarShowProgress = true

View file

@ -2554,11 +2554,31 @@ final class CommandPaletteSelectionScrollBehaviorTests: XCTestCase {
final class SidebarCommandHintPolicyTests: XCTestCase {
func testCommandHintRequiresCommandOnlyModifier() {
XCTAssertTrue(SidebarCommandHintPolicy.shouldShowHints(for: [.command]))
XCTAssertFalse(SidebarCommandHintPolicy.shouldShowHints(for: []))
XCTAssertFalse(SidebarCommandHintPolicy.shouldShowHints(for: [.command, .shift]))
XCTAssertFalse(SidebarCommandHintPolicy.shouldShowHints(for: [.command, .option]))
XCTAssertFalse(SidebarCommandHintPolicy.shouldShowHints(for: [.command, .control]))
withDefaultsSuite { defaults in
defaults.set(true, forKey: ShortcutHintDebugSettings.showHintsOnCommandHoldKey)
XCTAssertTrue(SidebarCommandHintPolicy.shouldShowHints(for: [.command], defaults: defaults))
XCTAssertFalse(SidebarCommandHintPolicy.shouldShowHints(for: [], defaults: defaults))
XCTAssertFalse(SidebarCommandHintPolicy.shouldShowHints(for: [.command, .shift], defaults: defaults))
XCTAssertFalse(SidebarCommandHintPolicy.shouldShowHints(for: [.command, .option], defaults: defaults))
XCTAssertFalse(SidebarCommandHintPolicy.shouldShowHints(for: [.command, .control], defaults: defaults))
}
}
func testCommandHintCanBeDisabledInSettings() {
withDefaultsSuite { defaults in
defaults.set(false, forKey: ShortcutHintDebugSettings.showHintsOnCommandHoldKey)
XCTAssertFalse(SidebarCommandHintPolicy.shouldShowHints(for: [.command], defaults: defaults))
}
}
func testCommandHintDefaultsToEnabledWhenSettingMissing() {
withDefaultsSuite { defaults in
defaults.removeObject(forKey: ShortcutHintDebugSettings.showHintsOnCommandHoldKey)
XCTAssertTrue(SidebarCommandHintPolicy.shouldShowHints(for: [.command], defaults: defaults))
}
}
func testCommandHintUsesIntentionalHoldDelay() {
@ -2595,25 +2615,43 @@ final class SidebarCommandHintPolicyTests: XCTestCase {
}
func testWindowScopedCommandHintsUseKeyWindowWhenNoEventWindowIsAvailable() {
XCTAssertTrue(
SidebarCommandHintPolicy.shouldShowHints(
for: [.command],
hostWindowNumber: 42,
hostWindowIsKey: true,
eventWindowNumber: nil,
keyWindowNumber: 42
)
)
withDefaultsSuite { defaults in
defaults.set(true, forKey: ShortcutHintDebugSettings.showHintsOnCommandHoldKey)
XCTAssertFalse(
SidebarCommandHintPolicy.shouldShowHints(
for: [.command],
hostWindowNumber: 42,
hostWindowIsKey: true,
eventWindowNumber: nil,
keyWindowNumber: 7
XCTAssertTrue(
SidebarCommandHintPolicy.shouldShowHints(
for: [.command],
hostWindowNumber: 42,
hostWindowIsKey: true,
eventWindowNumber: nil,
keyWindowNumber: 42,
defaults: defaults
)
)
)
XCTAssertFalse(
SidebarCommandHintPolicy.shouldShowHints(
for: [.command],
hostWindowNumber: 42,
hostWindowIsKey: true,
eventWindowNumber: nil,
keyWindowNumber: 7,
defaults: defaults
)
)
}
}
private func withDefaultsSuite(_ body: (UserDefaults) -> Void) {
let suiteName = "SidebarCommandHintPolicyTests-\(UUID().uuidString)"
guard let defaults = UserDefaults(suiteName: suiteName) else {
XCTFail("Failed to create defaults suite")
return
}
defaults.removePersistentDomain(forName: suiteName)
body(defaults)
defaults.removePersistentDomain(forName: suiteName)
}
}
@ -2633,6 +2671,27 @@ final class ShortcutHintDebugSettingsTests: XCTestCase {
XCTAssertEqual(ShortcutHintDebugSettings.defaultPaneHintX, 0.0)
XCTAssertEqual(ShortcutHintDebugSettings.defaultPaneHintY, 0.0)
XCTAssertFalse(ShortcutHintDebugSettings.defaultAlwaysShowHints)
XCTAssertTrue(ShortcutHintDebugSettings.defaultShowHintsOnCommandHold)
}
func testShowHintsOnCommandHoldSettingRespectsStoredValue() {
let suiteName = "ShortcutHintDebugSettingsTests-\(UUID().uuidString)"
guard let defaults = UserDefaults(suiteName: suiteName) else {
XCTFail("Failed to create defaults suite")
return
}
defaults.removePersistentDomain(forName: suiteName)
defer { defaults.removePersistentDomain(forName: suiteName) }
defaults.removeObject(forKey: ShortcutHintDebugSettings.showHintsOnCommandHoldKey)
XCTAssertTrue(ShortcutHintDebugSettings.showHintsOnCommandHoldEnabled(defaults: defaults))
defaults.set(false, forKey: ShortcutHintDebugSettings.showHintsOnCommandHoldKey)
XCTAssertFalse(ShortcutHintDebugSettings.showHintsOnCommandHoldEnabled(defaults: defaults))
defaults.set(true, forKey: ShortcutHintDebugSettings.showHintsOnCommandHoldKey)
XCTAssertTrue(ShortcutHintDebugSettings.showHintsOnCommandHoldEnabled(defaults: defaults))
}
}

2
vendor/bonsplit vendored

@ -1 +1 @@
Subproject commit 335facd9fd1d81a3c71fea69345af30f7e3601f9
Subproject commit 89a4fd1288a706ae4b766f323191d6570b7123aa