Skip to content

fix: --no-cmux double-render + rebind preview scroll keys - #4

Merged
nero408 merged 1 commit into
mainfrom
fix/no-cmux-and-scroll-keys
May 18, 2026
Merged

fix: --no-cmux double-render + rebind preview scroll keys#4
nero408 merged 1 commit into
mainfrom
fix/no-cmux-and-scroll-keys

Conversation

@nero408

@nero408 nero408 commented May 18, 2026

Copy link
Copy Markdown
Owner

Two reported bugs from the in-process-preview ship

1. --no-cmux opened both panels

Steps that triggered it:

cmux                         # cmux daemon running
mdmux --no-cmux ~/notes
# press Enter on a file

Expected: one panel (in-process). Got: two. cmux opened a sibling surface and mdmux's own preview pane rendered the same file.

Cause. App::open_selected always called self.cmux.open_markdown, regardless of render_mode. The CLI flag swapped the render mode but the client stayed as the live CliCmux, so every Enter shelled out to the real cmux daemon in addition to loading the preview.

Fix. Branch on render_mode in open_selected and close_markdown_panel. The cmux path runs only when we own a cmux surface; the in-process path runs only when we own the preview pane. Mutually exclusive.

2. Preview scroll keys were the wrong way around

Was Now
J / K → one line J / K → half page
Ctrl-D / U → half page Ctrl-D / U → half page (kept as alias)
j / k → full page when preview is open

The j/k arms are guarded on app.preview.is_some(), so:

  • cmux mode (no in-process preview ever): j/k keep navigating the tree, identical to today.
  • in-process mode, no file open yet: same — j/k move the tree.
  • in-process mode with a preview open: j/k scroll the preview; tree navigation falls back to arrow keys.

Tests

Test What it pins
open_selected_populates_preview_in_inprocess_mode (tightened) Asserts current_md_surface.is_none() — direct regression for issue 1
open_selected_skips_preview_in_cmux_mode (tightened) Symmetric: asserts current_md_surface.is_some() in cmux mode
close_markdown_panel_in_inprocess_does_not_touch_cmux (new) Sets a bogus surface id, calls close, asserts surface is not taken but preview is cleared

cargo test --lib49 passed. Clippy + fmt clean.

Docs

  • README key table now lists j/k (page), J/K (half-page), Ctrl-D/U (alias)
  • README "Without cmux" prose calls out the j/k → preview vs tree fallback to arrows
  • In-app help (?) updated to match

Test plan

  • CI green
  • cmux running, mdmux --no-cmux ~/notes, press Enter → only the in-process preview opens, no cmux pane spawned
  • In cmux mode, press Enter → cmux pane opens as before
  • With preview open, j / k scroll the preview a full page
  • With preview open, J / K scroll half a page
  • With preview open, / move the tree selection
  • In cmux mode, j / k still move the tree (unchanged)

🤖 Generated with Claude Code

Two issues reported after the in-process-preview ship:

## 1. `--no-cmux` opened *both* panels

Steps that triggered the bug:

  $ cmux                         # running cmux daemon
  $ mdmux --no-cmux ~/notes
  > enter on README.md

The user expected one panel (in-process). They got two: cmux opened a
sibling surface *and* mdmux's own preview pane rendered the same file.

Cause: `App::open_selected` always called `self.cmux.open_markdown`,
even with `render_mode == InProcess`. The CLI flag swapped the render
mode but the client stayed as the live `CliCmux`, so every Enter shelled
out to a working cmux daemon in addition to loading the preview.

Fix: branch on `render_mode` in `open_selected` and
`close_markdown_panel`. The cmux path runs only when we own a cmux
surface; the in-process path runs only when we own the preview pane.
Mutually exclusive.

## 2. Preview scroll keys were the wrong way around

Requested binding:

  j / k        — page scroll (full page)
  J / K        — half-page scroll

Was:

  J / K        — one line at a time
  Ctrl-D / U   — half page

New mapping:

  j / k        — full page scroll *when a preview is showing*
  J / K        — half-page scroll
  Ctrl-D / U   — half-page scroll (kept as vim-style alias)
  ↑ / ↓        — tree navigation (unchanged)
  j / k        — tree navigation when no preview is open (unchanged)

The `j` / `k` guards are conditional on `app.preview.is_some()` so cmux
users (no in-process preview) and in-process users who haven't opened a
file yet still get the original tree-navigation behaviour. With a
preview open, the arrow keys take over tree movement.

## Tests

- New: `close_markdown_panel_in_inprocess_does_not_touch_cmux` — sets a
  bogus surface id, calls close, asserts the surface is *not* taken
  (cmux client untouched) but the preview *is* cleared.
- Tightened: `open_selected_populates_preview_in_inprocess_mode` now
  also asserts `current_md_surface.is_none()`, which is the direct
  regression assertion for issue 1.
- Tightened: `open_selected_skips_preview_in_cmux_mode` symmetrically
  asserts `current_md_surface.is_some()`.

`cargo test --lib`: **49 passed**, clippy + fmt clean.

## Docs

- README key table: `j`/`k` listed for page scroll (in-process, preview
  open), `J`/`K` for half-page, `Ctrl-D`/`U` as alias.
- README "Without cmux" section: spells out that with a preview open
  `j`/`k` switch to scrolling and tree navigation falls back to arrows.
- In-app help screen mirrors the same.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@nero408
nero408 merged commit 04377a4 into main May 18, 2026
2 checks passed
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