Skip to content

Add smooth Vim and Emacs viewer navigation - #7921

Merged
lawrencecchen merged 45 commits into
mainfrom
task-viewer-vim-emacs-navigation
Jul 13, 2026
Merged

lawrencecchen merged 45 commits into
mainfrom
task-viewer-vim-emacs-navigation

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Jul 12, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • share smooth keyboard navigation between diff and Markdown viewers
  • add configurable Ctrl-D/U half-page and Ctrl-N/P line motions
  • accumulate repeated smooth motions so held keys remain responsive

Testing

  • bun test test/viewer-navigation.test.ts test/app.test.tsx
  • bun run typecheck
  • bun run lint
  • swift test --filter onlyFocusedContentActionsAllowBareFirstStrokes
  • tagged cloud build vnav
  • live tagged dogfood: diff j moved 0 to 18 px; Ctrl-D moved to 307 px; Markdown viewer rendered and received focused key input

Issues

  • Related: user-requested viewer navigation improvement

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Note

Medium Risk
Changes focus-scoped global shortcut routing and bare-key bindings in viewers, which can steal keystrokes if context clauses drift, but scope is limited to diff/Markdown viewer focus.

Overview
Adds shared smooth keyboard navigation for diff and Markdown viewers via new viewer-navigation.js, wired into the Markdown shell so the native app can drive the same scroll actions (j/k, Ctrl-D/U, Ctrl-N/P, G/gg) with accumulated smooth scrolling when keys repeat.

Expands Settings / CLI shortcut surface: half-page and Emacs line motions, ]f / [f next/previous file in the diff viewer, defaults centralized in CMUXCLI+DiffViewerShortcuts, and scroll bindings now apply under browser or markdown focus (file jumps stay browser/diff-focused). Scroll shortcut labels are renamed to “Viewers:” with new localizations; hasPriorityShortcutRouting moves to its own file and command palette next/previous join priority routing.

Reviewed by Cursor Bugbot for commit 5bb76e6. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Adds smooth Vim/Emacs scrolling to diff and Markdown viewers and ]f/[f next/previous file navigation. Adds a readiness handshake so viewer keys only route when loaded and not in inputs; tightens diff viewer trust with live HTTP session renewal; fixes visible-order file jumps and preserves search/input focus.

  • New Features

    • Shared viewer-navigation.js adds line, half-page, and edge motions with held-key accumulation; exposed as __cmuxPerformViewerNavigationAction (Markdown) and __cmuxPerformDiffViewerNavigationAction (diff).
    • Defaults: j/k, Ctrl-D/U, Ctrl-N/P, G/gg; diff-only ]f/[f from the visible file.
    • Shortcut labels show “Viewers:” and CLI defaults are centralized in CMUXCLI+DiffViewerShortcuts.
  • Bug Fixes

    • Viewer shortcuts route via a native ViewerNavigationKeyRouter to the focused webview; chords stable; bare keys scoped; ignored while typing; command palette next/previous use priority routing with the “effectively visible” context.
    • Trusted diff sessions only (custom scheme or registered live HTTP); token-shaped URLs without an active session are rejected; trusted state cached and renewed on activity; live HTTP diffs validated by page identity and session.
    • Readiness handshake: navigation activates only after the viewer confirms load and non-editable focus; resets on navigation; viewer state restored after canceled navigations.
    • Smooth targets reset on manual/native scroll and before file jumps; next/previous file navigation respects visible order and edges; diff file search and Markdown input focus are preserved.
    • Fix command palette event monitor weak capture to avoid stale window references; split viewer navigation support types for clarity and reuse.

Written for commit 27b664e. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Added smooth keyboard scrolling shortcuts for both diff and Markdown viewers, including half-page and Emacs-style “one smooth step” navigation.
    • Added diff viewer next/previous file navigation with mnemonic two-key chords.
    • Enabled consistent viewer shortcut behavior with centralized viewer-navigation handling.
  • Improvements

    • Updated shortcut labels and naming to use “Viewers:” where relevant, including new localized entries.
    • Scrolling shortcuts are now ignored while typing in editable fields.
  • Tests

    • Added/updated coverage for viewer-navigation scrolling and chord behavior.

@vercel

vercel Bot commented Jul 12, 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 Jul 13, 2026 3:56pm
cmux-staging Building Building Preview, Comment Jul 13, 2026 3:56pm

@coderabbitai

coderabbitai Bot commented Jul 12, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds shared keyboard navigation for diff and Markdown viewers, including new scrolling and adjacent-file actions, shortcut routing, embedded JavaScript integration, localized labels, schemas, CLI mappings, and Swift/TypeScript coverage.

Changes

Viewer navigation shortcuts

Layer / File(s) Summary
Shortcut actions and routing
Packages/macOS/CmuxSettings/..., Sources/KeyboardShortcut*.swift, CLI/*, Resources/Localizable.xcstrings, web/data/*
Adds viewer scrolling and file-navigation actions, default bindings, focus routing, labels, localization, schema entries, CLI mappings, and shortcut catalog metadata.
Viewer navigation runtime and embedding
Resources/markdown-viewer/*, Sources/Panels/MarkdownViewerAssets.swift, webviews/src/global.d.ts
Adds shared shortcut matching, smooth scrolling, chord handling, interaction resets, teardown, bundled asset injection, and global APIs.
Native and diff viewer integration
Sources/Panels/MarkdownWebSupport.swift, webviews/src/App.tsx, Resources/markdown-viewer/webviews-app/chunks/diffSurface.mjs, cmux.xcodeproj/project.pbxproj
Routes native Markdown events and diff-viewer scrolling through shared navigation while retaining file search and adjacent-file dispatch.
Navigation and shortcut validation
cmuxTests/*, webviews/test/*, Packages/macOS/CmuxSettings/Tests/*
Tests default chords, smooth scrolling, editable-control filtering, unbound shortcuts, native shell integration, and adjacent-file behavior.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ShortcutSettings
  participant MarkdownWebView
  participant ViewerBridge
  participant CmuxViewerNavigation
  participant ViewerScroller
  ShortcutSettings->>MarkdownWebView: resolve configured shortcut
  MarkdownWebView->>ViewerBridge: send navigation action
  ViewerBridge->>CmuxViewerNavigation: performAction(action, scroller)
  CmuxViewerNavigation->>ViewerScroller: apply smooth scroll motion
Loading

Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 2 warnings)

Check name Status Explanation Resolution
Cmux Full Internationalization ❌ Error New diff-viewer shortcut labels (half-page, Emacs, next/previous file) only have en/ja in Localizable.xcstrings and web/data/cmux-shortcuts.ts, but 20 locales are supported. Add translations for every existing catalog/routing locale on those new keys, and move any web-facing shortcut copy through locale-backed messages for all supported locales.
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.
Description check ⚠️ Warning The description has Summary and Testing, but it omits required Demo Video, Review Trigger, and Checklist sections from the template. Add the missing Demo Video, Review Trigger, and Checklist sections, and ensure the behavior-change video link is included or explicitly noted as unavailable.
✅ Passed checks (22 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed The diff only adds value-enum cases and keeps new viewer asset/webview classes explicitly @MainActor; no new Sendable reference sharing or background UI access appears.
Cmux Swift Blocking Runtime ✅ Passed No production Swift code adds semaphores, waits, sleeps, asyncAfter, main.sync, or locks; only test-only continuation scaffolding and a non-blocking chord timeout appear.
Cmux Browser Automation Off-Main ✅ Passed PR only adds viewer key routing/hooks in MarkdownWebSupport/App.tsx; it does not move any browser.* socket command or policy routing in TerminalController/ControlCommandExecutionPolicy.
Cmux Expensive Synchronous Load ✅ Passed Touched Swift changes are shortcut/navigation plumbing and bundled asset loading; no new RestorableAgentSessionIndex, shared-index, transcript, or JSONL history loads on interactive paths.
Cmux Cache Substitution Correctness ✅ Passed The PR diff only deletes a test; no Swift/TS/JS production path changed, so no cache-substitution risk exists.
Cmux No Hacky Sleeps ✅ Passed No new hacky sleeps: the 700ms chord timeout in App.tsx pre-existed, and diffSurface.mjs’s 50ms batching helper is unchanged from parent.
Cmux Algorithmic Complexity ✅ Passed New scans are over tiny fixed arrays (8 motions, 3 bindings); adjacentItemId is a single O(n) lookup per user action, with no nested rescans or batch joins.
Cmux Swift Concurrency ✅ Passed PASS: the Swift changes are synchronous metadata/navigation wiring; no new Dispatch/Combine patterns or fire-and-forget Tasks were introduced. Existing Task/continuation uses are allowed boundaries.
Cmux Swift @Concurrent ✅ Passed No changed Swift code introduces bad @concurrent usage; added async helpers are UI-bound (@MainActor tests/WebKit), with no nonisolated-heavy async boundary issues.
Cmux Swift File And Package Boundaries ✅ Passed Touched Swift changes are small and focused; no new oversized file or large growth, and reusable shortcut policy lives in CmuxSettings rather than the app target.
Cmux Swiftpm Lockfiles ✅ Passed PR only adds source-file refs in project.pbxproj; no SwiftPM package refs or Package.resolved diffs are present.
Cmux Swift Logging ✅ Passed PASS: Patch adds no production logging. Diff search found no new print/debugPrint/dump/NSLog/Logger in runtime Swift; remaining prints are CLI output and existing DEBUG-only NSLog.
Cmux User-Facing Error Privacy ✅ Passed New user-facing errors are generic (e.g. missing patch URL, clipboard unavailable, refs load failed) and do not expose vendors, secrets, or raw upstream details.
Cmux Swiftui State Layout ✅ Passed Touched Swift files add shortcut enums and a WKWebView bridge; no new @Observable/@Published/GeometryReader/List/ForEach patterns were introduced.
Cmux Architecture Rethink ✅ Passed Swift changes add a clear MarkdownWebView key-handling bridge and shortcut context updates; no sleeps, locks, polling, or duplicate owners were introduced.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed No standalone cmux-owned window/controller code changed; the only NSWindow is a test-only fixture, which the rule allows.
Cmux Source Artifacts ✅ Passed No temp/cache/log/screenshot paths found; the only bundle-like file is under the repo’s normal checked-in web chunk tree, alongside source, tests, and localization edits.
Cmux No Test Or Debug Seam In Production Source ✅ Passed Touched production Swift files add navigation behavior and internal CLI sharing, but no new #if DEBUG/test-only members or seam-style accessors were added.
Cmux No Ambient Global State ✅ Passed Changed Swift behavior stays on existing types (CMUXCLI, MarkdownWebView, ShortcutAction); no new file-scope func/var or singleton was added.
Title check ✅ Passed The title clearly summarizes the main change: shared smooth Vim/Emacs viewer navigation.
✨ 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-viewer-vim-emacs-navigation

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.

@greptile-apps

greptile-apps Bot commented Jul 12, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds shared keyboard navigation to the diff and Markdown viewers. The main changes are:

  • Smooth Vim and Emacs scrolling with repeated-motion accumulation.
  • Configurable half-page, line, edge, and diff file-navigation shortcuts.
  • Focus-aware native routing and editable-field protection.
  • Viewer readiness checks and stronger live diff-session validation.
  • Shared navigation assets and focused Swift and web tests.

Confidence Score: 5/5

This looks safe to merge.

  • Manual scrolling now clears pending smooth targets.
  • Diff file jumps reset pending targets before changing position.
  • No separate blocking issue remains in the updated navigation paths.

Important Files Changed

Filename Overview
Resources/markdown-viewer/viewer-navigation.js Adds shared smooth motion, repeated-motion accumulation, and target reset handling.
Resources/markdown-viewer/shell.html Connects shared navigation and manual-input resets to the Markdown viewer.
webviews/src/App.tsx Connects native navigation actions and visible-order file jumps to the diff viewer.
Sources/Panels/ViewerNavigationKeyRouter.swift Routes viewer shortcuts according to focus, readiness, and editable-field state.

Reviews (38): Last reviewed commit: "Split viewer navigation support types" | Re-trigger Greptile

Comment thread Resources/markdown-viewer/viewer-navigation.js

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Sources/KeyboardShortcutActionContext.swift (1)

93-133: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

overlaps() logic is correct but dense; a matrix unit test would future-proof it.

Traced every new .viewerPanel pairing against the corresponding isAvailable/defaultWhenClause predicates (lines 27-91) and found no mismatches — the branch ordering and exclusions are correct, including the canvasLayoutOutsideFocusedContent interaction. Given the code_block_complexity_high nature of this function and that it now has 7 cases with pairwise special-casing, a small parametrized test enumerating all ShortcutContext × ShortcutContext combinations (asserting overlaps agrees with simultaneous-truth of the underlying isAvailable flags) would catch regressions here more cheaply than manual tracing on future edits.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/KeyboardShortcutActionContext.swift` around lines 93 - 133, Add a
parametrized matrix unit test for ShortcutContext.overlaps, covering every
ShortcutContext × ShortcutContext pairing and asserting the result matches
simultaneous truth of the corresponding isAvailable predicates. Keep the
existing overlaps implementation unchanged and use the test to guard future
pairing or exclusion changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmuxTests/MarkdownPanelTests.swift`:
- Around line 669-715: Update testMarkdownViewerUsesSmoothVimAndEmacsNavigation
to save the current KeyboardShortcutSettings, install explicit bindings for the
tested j, Ctrl-D, and Ctrl-P shortcuts before loading shellHTML, and restore the
original settings in the existing defer cleanup. Keep the test’s navigation
assertions unchanged.

In `@Sources/Panels/MarkdownViewerAssets.swift`:
- Around line 70-87: Mark the pure helper methods viewerShortcutJSONObject and
viewerShortcutStrokeJSONObject as nonisolated, since they only transform their
value arguments and do not access main-actor state. Keep the
KeyboardShortcutSettings snapshot main-actor isolated and verify StoredShortcut
and ShortcutStroke support nonisolated use.

---

Outside diff comments:
In `@Sources/KeyboardShortcutActionContext.swift`:
- Around line 93-133: Add a parametrized matrix unit test for
ShortcutContext.overlaps, covering every ShortcutContext × ShortcutContext
pairing and asserting the result matches simultaneous truth of the corresponding
isAvailable predicates. Keep the existing overlaps implementation unchanged and
use the test to guard future pairing or exclusion changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 84540e9b-826f-47ff-bbef-16e3fb672582

📥 Commits

Reviewing files that changed from the base of the PR and between 2e199ea and 389eca8.

📒 Files selected for processing (18)
  • CLI/cmux_open.swift
  • Packages/macOS/CmuxSettings/Sources/CmuxSettings/Values/ShortcutAction+Defaults.swift
  • Packages/macOS/CmuxSettings/Sources/CmuxSettings/Values/ShortcutAction.swift
  • Packages/macOS/CmuxSettings/Tests/CmuxSettingsTests/ShortcutActionNumberedDigitTests.swift
  • Resources/Localizable.xcstrings
  • Resources/markdown-viewer/shell.html
  • Resources/markdown-viewer/viewer-navigation.js
  • Resources/markdown-viewer/webviews-app/chunks/diffSurface.mjs
  • Sources/KeyboardShortcutActionContext.swift
  • Sources/KeyboardShortcutSettings.swift
  • Sources/Panels/MarkdownViewerAssets.swift
  • cmuxTests/CMUXOpenCommandTests.swift
  • cmuxTests/MarkdownPanelTests.swift
  • web/data/cmux-shortcuts.ts
  • web/data/cmux.schema.json
  • webviews/src/App.tsx
  • webviews/src/global.d.ts
  • webviews/test/viewer-navigation.test.ts

Comment thread cmuxTests/MarkdownPanelTests.swift Outdated
Comment thread Sources/Panels/MarkdownViewerAssets.swift Outdated

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Sources/Panels/MarkdownWebSupport.swift`:
- Around line 36-38: Remove the DEBUG-only onViewerNavigationActionForTesting
property from MarkdownWebSupport, along with any production references to it.
Preserve viewer navigation behavior and update tests to observe emitted
JavaScript or use a test subclass instead.
- Around line 71-86: Update the chord handling around
pendingViewerNavigationChordPrefix to track a 700 ms expiration deadline,
matching viewer-navigation.js. When processing a pending prefix, clear it if the
deadline has passed so the current event is evaluated as a new first stroke;
only perform the two-stroke action while the prefix remains valid, and set or
refresh the deadline when accepting a new first stroke.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: e7830eb8-ab1c-4805-b0b0-967d377aeae6

📥 Commits

Reviewing files that changed from the base of the PR and between 389eca8 and a334389.

📒 Files selected for processing (9)
  • Packages/macOS/CmuxSettings/Sources/CmuxSettings/Values/ShortcutAction.swift
  • Resources/markdown-viewer/shell.html
  • Resources/markdown-viewer/viewer-navigation.js
  • Resources/markdown-viewer/webviews-app/chunks/diffSurface.mjs
  • Sources/Panels/MarkdownWebSupport.swift
  • cmuxTests/MarkdownPanelTests.swift
  • web/data/cmux-shortcuts.ts
  • webviews/src/global.d.ts
  • webviews/test/viewer-navigation.test.ts

Comment thread Sources/Panels/MarkdownWebSupport.swift Outdated
Comment thread Sources/Panels/MarkdownWebSupport.swift Outdated
Comment thread Resources/markdown-viewer/shell.html Outdated

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmuxTests/CMUXOpenCommandTests.swift`:
- Around line 376-388: Split the tuple-based XCTAssertEqual checks in the
shortcut assertions into separate field-level assertions so they compile without
requiring (String?, Bool?) Equatable conformance. Update the checks for
diffViewerScrollDown, diffViewerScrollUp, diffViewerNextFile, and
diffViewerPreviousFile while preserving each expected key and control value.

In `@webviews/src/App.tsx`:
- Around line 330-336: Memoize the adjacent-file navigation callbacks with
useCallback: wrap scrollToItem and jumpAdjacentFile in App, preserving their
existing behavior and including only their actual dependencies, so
useKeyboardShortcuts receives a stable onJumpAdjacentFile reference and does not
recreate listeners on unrelated state updates.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 954aaf2f-cd86-4fb7-94a3-0f7305cc51e9

📥 Commits

Reviewing files that changed from the base of the PR and between a334389 and 8553b4e.

📒 Files selected for processing (17)
  • CLI/cmux_open.swift
  • Packages/macOS/CmuxSettings/Sources/CmuxSettings/Values/ShortcutAction+Defaults.swift
  • Packages/macOS/CmuxSettings/Sources/CmuxSettings/Values/ShortcutAction+PriorityRouting.swift
  • Packages/macOS/CmuxSettings/Sources/CmuxSettings/Values/ShortcutAction.swift
  • Packages/macOS/CmuxSettings/Tests/CmuxSettingsTests/ShortcutActionNumberedDigitTests.swift
  • Resources/Localizable.xcstrings
  • Resources/markdown-viewer/webviews-app/chunks/diffSurface.mjs
  • Sources/KeyboardShortcutActionContext.swift
  • Sources/KeyboardShortcutSettings.swift
  • Sources/Panels/MarkdownWebSupport.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/CMUXOpenCommandTests.swift
  • cmuxTests/ViewerNavigationTests.swift
  • web/data/cmux-shortcuts.ts
  • web/data/cmux.schema.json
  • webviews/src/App.tsx
  • webviews/test/app.test.tsx
💤 Files with no reviewable changes (1)
  • Sources/Panels/MarkdownWebSupport.swift

Comment thread cmuxTests/CMUXOpenCommandTests.swift Outdated
Comment thread webviews/src/App.tsx Outdated
Comment thread Resources/markdown-viewer/viewer-navigation.js

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Sources/KeyboardShortcutActionContext.swift (1)

141-171: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Unreachable guard added to canvasLayoutOutsideFocusedContent branch.

The new self != .viewerPanel && other != .viewerPanel conditions at lines 169-170 can never be evaluated: the earlier if self == .viewerPanel || other == .viewerPanel { ... return ... } block (lines 141-149) unconditionally returns (it has a default: return false case) whenever either side is .viewerPanel, so control never reaches the canvasLayoutOutsideFocusedContent branch for that pairing. The result happens to be correct (false either way), but the added condition is dead code that misrepresents the actual control flow.

♻️ Proposed cleanup
             if self == .canvasLayoutOutsideFocusedContent || other == .canvasLayoutOutsideFocusedContent {
                 return self != .browserPanel
                     && other != .browserPanel
                     && self != .browserOrFilePreviewTextEditor
                     && other != .browserOrFilePreviewTextEditor
                     && self != .markdownPanel
-                    && other != .markdownPanel
-                    && self != .viewerPanel
-                    && other != .viewerPanel
+                    && other != .markdownPanel
             }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/KeyboardShortcutActionContext.swift` around lines 141 - 171, Remove
the redundant self != .viewerPanel and other != .viewerPanel conditions from the
canvasLayoutOutsideFocusedContent branch in the surrounding keyboard shortcut
context comparison logic. The earlier viewerPanel branch already returns for any
pairing involving .viewerPanel; preserve the remaining exclusions and behavior
of the canvasLayoutOutsideFocusedContent check.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmuxTests/ViewerNavigationTests.swift`:
- Around line 84-92: Strengthen the timeout test around
handleViewerNavigationKey by inspecting window.__cmuxNativeNavigationCalls after
the g@10 and g@11 presses and asserting no navigation calls occurred, confirming
the stale chord expired. Then retain the existing assertions after g@11.1 to
verify the newly armed chord completes the navigation, and ensure the 10→11
interval exceeds Self.viewerNavigationChordTimeout.

In `@Resources/markdown-viewer/webviews-app/chunks/diffSurface.mjs`:
- Line 1: Review the source implementation of CmuxViewerNavigation.install and
the existing pn file-navigation handler to determine whether both use the same
DOM and lifecycle scope. If they do, route diffViewerOpenFileSearch,
diffViewerNextFile, and diffViewerPreviousFile through the shared
CmuxViewerNavigation chord handling and remove pn’s duplicate pending-chord,
timeout, and matching logic; otherwise preserve the separation and document the
distinct scope in the implementation.

---

Outside diff comments:
In `@Sources/KeyboardShortcutActionContext.swift`:
- Around line 141-171: Remove the redundant self != .viewerPanel and other !=
.viewerPanel conditions from the canvasLayoutOutsideFocusedContent branch in the
surrounding keyboard shortcut context comparison logic. The earlier viewerPanel
branch already returns for any pairing involving .viewerPanel; preserve the
remaining exclusions and behavior of the canvasLayoutOutsideFocusedContent
check.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: bd104525-d032-415b-93f6-b9c538189ce4

📥 Commits

Reviewing files that changed from the base of the PR and between 8553b4e and 05d761c.

⛔ Files ignored due to path filters (1)
  • .github/swift-file-length-budget.tsv is excluded by !**/*.tsv
📒 Files selected for processing (12)
  • CLI/CMUXCLI+DiffViewerShortcuts.swift
  • CLI/cmux_open.swift
  • Resources/markdown-viewer/shell.html
  • Resources/markdown-viewer/viewer-navigation.js
  • Resources/markdown-viewer/webviews-app/chunks/diffSurface.mjs
  • Sources/KeyboardShortcutActionContext.swift
  • Sources/KeyboardShortcutSettings.swift
  • Sources/Panels/MarkdownViewerAssets.swift
  • Sources/Panels/MarkdownWebSupport.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/ViewerNavigationTests.swift
  • webviews/test/viewer-navigation.test.ts
💤 Files with no reviewable changes (2)
  • Sources/Panels/MarkdownViewerAssets.swift
  • Resources/markdown-viewer/shell.html

Comment thread cmuxTests/ViewerNavigationTests.swift
Comment thread Resources/markdown-viewer/webviews-app/chunks/diffSurface.mjs Outdated
Comment thread Resources/markdown-viewer/shell.html
Comment thread Resources/markdown-viewer/viewer-navigation.js
Comment thread Resources/markdown-viewer/viewer-navigation.js
Comment thread Resources/markdown-viewer/viewer-navigation.js
@cursor

cursor Bot commented Jul 13, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@lawrencecchen
lawrencecchen merged commit c1253dd into main Jul 13, 2026
34 checks passed
@lawrencecchen
lawrencecchen deleted the task-viewer-vim-emacs-navigation branch July 13, 2026 16:42
hhsw2015 pushed a commit to hhsw2015/cmux that referenced this pull request Jul 16, 2026
* Add smooth Vim and Emacs viewer navigation

* Fix Markdown viewer key routing and scroll step

* Add Vim diff file navigation

* Fix viewer navigation review findings

* Fix viewer navigation test module import

* Remove unavailable CLI test dependency

* Reset Markdown smooth scroll after manual input

* Reset smooth scroll for native navigation keys

* Fix viewer shortcut context and chord stability

* Fix command palette context availability

* Fix viewer shortcut context routing

* Route viewer shortcuts through native context

* Navigate from visible diff file

* Cache viewer bindings and preserve search input

* Preserve editable Markdown input

* Reset smooth target before file jumps

* Extract viewer navigation helpers

* Wire viewer helpers into app target

* Route shortcuts in live remote diffs

* Confirm live diff viewer page identity

* Reset diff identity on navigation

* Isolate diff viewer focus identity

* Track isolated editable focus deeply

* Align palette shortcut visibility context

* Route all viewer key entrypoints safely

* Scope viewer keys to focused webview

* Split CmuxWebView support helpers

* Import shortcut settings in viewer tests

* Test inactive diff viewer URL trust

* Trust only active diff viewer sessions

* Test live HTTP diff viewer trust

* Register live HTTP diff viewer sessions

* Cache trusted viewer state off key path

* Test cancelled diff navigation state

* Restore viewer state after cancelled navigation

* Close viewer navigation ordering gaps

* Preserve diff search focus state

* Handshake viewer navigation readiness

* Test live diff viewer trust renewal

* Renew active diff viewer trust

* Fix merged command palette weak capture

* Split viewer navigation support types

(cherry picked from commit c1253dd)
@lawrencecchen
lawrencecchen restored the task-viewer-vim-emacs-navigation branch July 18, 2026 10:25

This branch was successfully deployed

1 active deployment
Preview – cmux — 27b664e6 Deployed Jul 13, 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