Skip to content

Fix Ctrl+K in the command palette - #2394

Merged
lawrencecchen merged 5 commits into
mainfrom
task-ctrl-k-command-palette
Mar 31, 2026
Merged

lawrencecchen merged 5 commits into
mainfrom
task-ctrl-k-command-palette

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Mar 31, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • stop treating Ctrl+J/K as command palette list navigation
  • let AppKit handle native text-editing commands like Ctrl+K in the palette search field
  • add regression coverage for the shortcut helper, app-level routing, and navigation smoke test expectations

Testing

  • CMUX_SKIP_ZIG_BUILD=1 xcodebuild -project GhosttyTabs.xcodeproj -scheme cmux-unit -destination 'platform=macOS' -derivedDataPath /tmp/cmux-task-ctrl-k-command-palette-tests test -only-testing:cmuxTests/CommandPaletteKeyboardNavigationTests -only-testing:cmuxTests/AppDelegateShortcutRoutingTests/testControlKDoesNotRoutePaletteMoveSelectionWhenSearchFieldIsFocused ✅
  • ./scripts/reload.sh --tag task-ctrl-k-command-palette ✅

Task

  • User report: ctrl+k doesnt work (unix thing for jumping to start) in the command pallete

Summary by cubic

Fix Ctrl+K in the command palette and stop empty-state flashes. Ctrl+K now edits text; only Ctrl+N/P (and arrows) move selection.

  • Bug Fixes
    • Preserve “no results” only when current and resolved queries match exactly to stop flicker.
    • Keep only Ctrl+N/P for list navigation and let Ctrl+K reach text editing; clarify open‑palette routing test.

Written for commit 208e741. Summary will update on new commits.

Summary by CodeRabbit

  • Bug Fixes

    • Removed Control+J and Control+K as command-palette navigation shortcuts; Control+N and Control+P still move selection.
    • Changed search behavior so an empty-result state is preserved only when current and resolved queries match exactly.
  • Tests

    • Added and updated tests to cover the Control+J/Control+K removal, ensure Ctrl+K is ignored when search field is focused, and validate the refined empty-state preservation logic.

@vercel

vercel Bot commented Mar 31, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Mar 31, 2026 3:59am

@coderabbitai

coderabbitai Bot commented Mar 31, 2026 •

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 64513be4-06b2-4986-9c22-cdd94df552cf

📥 Commits

Reviewing files that changed from the base of the PR and between 0322e78 and 208e741.

📒 Files selected for processing (1)
  • cmuxTests/AppDelegateShortcutRoutingTests.swift
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmuxTests/AppDelegateShortcutRoutingTests.swift

📝 Walkthrough

Walkthrough

Removed Emacs-style Control+J/Control+K command-palette navigation; tightened empty-state preservation to require exact query equality; updated and added tests to reflect removed key mappings and the revised preservation logic and test preconditions.

Changes

Cohort / File(s) Summary
Command Palette Navigation Implementation
Sources/AppDelegate.swift
Removed Ctrl+J (keyCode 38) and Ctrl+K (keyCode 40) mappings from commandPaletteSelectionDeltaForKeyboardNavigation; retained Ctrl+N/Ctrl+P behavior.
Command Palette Empty-State Logic
Sources/ContentView.swift
commandPaletteShouldPreserveEmptyStateWhileSearchPending(...) now requires exact equality between currentMatchingQuery and resolvedMatchingQuery (removed prefix-match condition).
Unit/Test Updates — Navigation
cmuxTests/ShortcutAndCommandPaletteTests.swift, tests_v2/test_command_palette_navigation_keys.py
Renamed/limited NP-only test to assert only Ctrl+N/P; added testDoesNotTreatControlJKAsPaletteNavigation asserting Ctrl+J/K are not navigation keys; removed Ctrl+J/Ctrl+K from the regression matrix.
Unit/Test Updates — Routing
cmuxTests/AppDelegateShortcutRoutingTests.swift
Changed a test precondition (simulated command-palette visibility now set to true) and added testControlKDoesNotRoutePaletteMoveSelectionWhenSearchFieldIsFocused to assert Ctrl+K does not route move-selection when the search field is focused.
Unit/Test Updates — Search Engine
cmuxTests/CommandPaletteSearchEngineTests.swift
Updated expectation: refining-from-resolved-no-match now asserts false; added testPendingEmptyStateIsPreservedForSameResolvedNoMatchQuery asserting preservation when currentMatchingQuery == resolvedMatchingQuery.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

I nibble keys and hop with grace,
Ctrl+J/K have left the place.
N and P guide the palette fair,
I twitch my whiskers, sniff the air—🐇✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: removing Ctrl+K from command palette navigation to allow it to function as a native text-editing command.
Description check ✅ Passed The description includes a summary of changes and testing performed, matching the required template sections. However, it lacks a demo video and the review trigger checklist is incomplete.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch task-ctrl-k-command-palette

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 4 files

@greptile-apps

greptile-apps Bot commented Mar 31, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a user-reported bug where Ctrl+K (the Unix/Emacs "kill to end of line" text-editing command) was being intercepted by the command palette's keyboard navigation handler and treated as "move selection up" instead of being passed through to the search field for native text editing.

The fix is a two-line deletion from commandPaletteSelectionDeltaForKeyboardNavigation: Ctrl+J (+1) and Ctrl+K (−1) are removed as navigation shortcuts, leaving only Ctrl+N/P and the arrow keys. This lets AppKit handle \\u{0a} and \\u{0b} natively in the palette search field. The change follows the project's two-commit regression test policy (tests first, fix second).

Key changes:

  • Sources/AppDelegate.swift — removes Ctrl+J/K from commandPaletteSelectionDeltaForKeyboardNavigation; comment updated to explain the intentional exclusion
  • cmuxTests/ShortcutAndCommandPaletteTests.swift — renames the N/P test to scope it correctly; adds testDoesNotTreatControlJKAsPaletteNavigation asserting nil for all four Ctrl+J/K variants (printable + control char, both keys)
  • cmuxTests/AppDelegateShortcutRoutingTests.swift — adds an integration test verifying that Ctrl+K neither emits .commandPaletteMoveSelection nor is consumed by debugHandleCustomShortcut when the palette search field is focused
  • tests_v2/test_command_palette_navigation_keys.py — removes ctrl+j / ctrl+k from the E2E navigation combo loops and updates the module docstring

Confidence Score: 5/5

Safe to merge — the fix is a minimal two-line deletion with consistent unit, integration, and E2E test coverage.

The only finding is a P2 test-clarity note about setCommandPaletteVisible(false, …) in the new integration test. The test still exercises the correct routing path because commandPaletteInteractiveInTargetWindow is true via the overlay and responder checks, so no behavioral gap exists. All remaining findings are P2 or lower.

Minor test-readability concern in cmuxTests/AppDelegateShortcutRoutingTests.swift at line 2476.

Important Files Changed

Filename Overview
Sources/AppDelegate.swift Removes Ctrl+J/K as palette-navigation shortcuts from commandPaletteSelectionDeltaForKeyboardNavigation, keeping only Ctrl+N/P alongside arrow keys; lets AppKit handle Ctrl+K as native text editing in the search field.
cmuxTests/ShortcutAndCommandPaletteTests.swift Renames the N/P navigation test to clarify its scope, and adds testDoesNotTreatControlJKAsPaletteNavigation asserting nil for all Ctrl+J/K variants.
cmuxTests/AppDelegateShortcutRoutingTests.swift Adds integration test verifying Ctrl+K does not emit .commandPaletteMoveSelection and is not consumed by the shortcut handler; setCommandPaletteVisible(false, …) leaves the test in an intermediate state rather than the fully-visible state, though it still exercises the routing path correctly.
tests_v2/test_command_palette_navigation_keys.py Removes ctrl+j and ctrl+k from E2E navigation combo smoke-test loops and updates the module docstring to match.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Key event: Ctrl+K in palette search field] --> B[handleCustomShortcut]
    B --> C[commandPaletteSelectionDeltaForKeyboardNavigation]
    C --> D{key is Ctrl+N/P or arrow key?}
    D -- Yes --> E[return delta ±1]
    D -- No --> F[return nil]
    E --> G[post .commandPaletteMoveSelection — event consumed]
    F --> H[shouldConsumeShortcutWhileCommandPaletteVisible]
    H --> I{flags contain .command or is Escape?}
    I -- Yes --> J[consume / block]
    I -- No — Ctrl+K → false --> K[return false — event NOT consumed]
    K --> L[AppKit handles Ctrl+K: kill-to-end-of-line in search field ✓]

    style E fill:#f66,color:#fff
    style G fill:#f66,color:#fff
    style K fill:#6a6,color:#fff
    style L fill:#6a6,color:#fff
Loading

Reviews (1): Last reviewed commit: "Let ctrl-k reach command palette text ed..." | Re-trigger Greptile

Comment thread cmuxTests/AppDelegateShortcutRoutingTests.swift
@lawrencecchen
lawrencecchen merged commit 56deaf6 into main Mar 31, 2026
11 of 14 checks passed
@lawrencecchen
lawrencecchen deleted the task-ctrl-k-command-palette branch March 31, 2026 04:00

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="cmuxTests/AppDelegateShortcutRoutingTests.swift">

<violation number="1" location="cmuxTests/AppDelegateShortcutRoutingTests.swift:2355">
P2: This change removes the lag-state scenario from the test: setting command-palette visibility to `true` makes it equivalent to the normal visible-Escape test, so regressions in pending-open/visibility-sync handling can slip through.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

// Simulate a visibility sync lag/race where AppDelegate does not yet know the palette is open.
appDelegate.setCommandPaletteVisible(false, for: window)
// Model the normal open-palette state so the test reads like the user-facing scenario.
appDelegate.setCommandPaletteVisible(true, for: window)

@cubic-dev-ai cubic-dev-ai Bot Mar 31, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This change removes the lag-state scenario from the test: setting command-palette visibility to true makes it equivalent to the normal visible-Escape test, so regressions in pending-open/visibility-sync handling can slip through.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At cmuxTests/AppDelegateShortcutRoutingTests.swift, line 2355:

<comment>This change removes the lag-state scenario from the test: setting command-palette visibility to `true` makes it equivalent to the normal visible-Escape test, so regressions in pending-open/visibility-sync handling can slip through.</comment>

<file context>
@@ -2351,8 +2351,8 @@ final class AppDelegateShortcutRoutingTests: XCTestCase {
-        // Simulate a visibility sync lag/race where AppDelegate does not yet know the palette is open.
-        appDelegate.setCommandPaletteVisible(false, for: window)
+        // Model the normal open-palette state so the test reads like the user-facing scenario.
+        appDelegate.setCommandPaletteVisible(true, for: window)
 
         guard let escapeEvent = makeKeyDownEvent(
</file context>
Suggested change
appDelegate.setCommandPaletteVisible(true, for: window)
appDelegate.setCommandPaletteVisible(false, for: window)
Fix with Cubic

bn-l pushed a commit to bn-l/cmux that referenced this pull request Apr 3, 2026
…and-palette

Fix Ctrl+K in the command palette

This branch was successfully deployed

1 active deployment
Preview — 208e741d Deployed Mar 31, 2026 by vercel[bot]
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