Skip to content

feat(picker): digit jump buffer + Enter in session chooser (#247)#248

Merged
psmux merged 1 commit into
masterfrom
feat/247-session-picker-digit-jump
Apr 21, 2026
Merged

feat(picker): digit jump buffer + Enter in session chooser (#247)#248
psmux merged 1 commit into
masterfrom
feat/247-session-picker-digit-jump

Conversation

@tarikguney

@tarikguney tarikguney commented Apr 21, 2026

Copy link
Copy Markdown
Collaborator

Closes #247.

Summary

Make the session picker (PREF s) accept a number-then-Enter jump, similar to how windows are selected by digit. Also closes the pre-existing side-effect where character keys typed into the picker leaked through to the focused pane's PTY.

Behavior (while picker is open)

  • 1..9, 0 — append to a jump buffer, shown at the bottom as go to 12
  • Enter — parse buffer as 1-based index and jump; empty buffer falls back to the arrow-cursor selection (existing behavior, unchanged)
  • Backspace — delete the last digit from the buffer
  • Esc — clear buffer and close picker
  • Up/Down/PageUp/PageDown/Home/End — arrow cursor navigation (unchanged)
  • x — kill session at the arrow cursor (unchanged)

Out-of-range or unparseable buffer on Enter is a silent no-op — buffer stays so the user can Backspace and fix. Killing a session clears the buffer since indexes shift.

UI changes

  • Every row is now numbered with a right-aligned dynamic-width column so the digit-to-session mapping is visible without trial and error.
  • Overlay height grows by 2 rows when the buffer indicator is active.
  • All non-handled character keys are absorbed while the picker is open (fixes the input-leakage side effect).

Test plan

  • cargo build --release clean
  • tests/test_issue247_session_picker_digit.ps1 — 14/14 passing. Covers: state declaration, digit-buffer accumulator, no immediate-switch shortcut, Enter parses buffer as 1-based, Backspace pops, Esc clears, leak-guard catch-all, title hint, dynamic row numbering, buffer preview rendering, dynamic overlay height, and functional verification that the picker data source (port files + session-info over TCP) reaches multiple sessions.
  • Manual: C-b s, type a number, press Enter — jumps to that session. Backspace edits. Esc closes without side effects. Non-digit chars no longer leak to the PTY.

While the session picker (PREF s) is open:
- Digits accumulate into a jump buffer shown at the bottom as "go to N".
- Enter parses the buffer as a 1-based index and jumps; empty buffer
  falls back to the arrow cursor selection.
- Backspace edits the buffer; Esc clears it and closes the picker.
- Every row is numbered with a right-aligned dynamic-width column so
  the digit-to-session mapping is visible without trial and error.
- Overlay height grows to accommodate the buffer indicator.

Also absorbs all other character keys while the picker is open so they
cannot leak through to the focused pane's PTY — fixes the pre-existing
input-leakage side effect of the picker.

Fixes #247.
@psmux psmux merged commit bf0a14a into master Apr 21, 2026
8 checks passed
@psmux psmux deleted the feat/247-session-picker-digit-jump branch April 21, 2026 11:05
@psmux

psmux commented Apr 21, 2026

Copy link
Copy Markdown
Owner

Merged in bf0a14a. Thank you for the thoughtful contribution Tarik.

What I really appreciated about this one:

  • The state lives where it belongs (client side, alongside the rest of the picker state) and the buffer is cleared on every entry into and exit from the picker, so there are no stale indexes after a kill or a re open.
  • Enter falls back to the arrow cursor when the buffer is empty, so the existing muscle memory still works. No surprises for current users.
  • The leak guard catch all on KeyCode::Char(_) is a quiet but real fix. The pre existing input bleed into the focused pane was annoying and easy to miss in a review, glad you folded it in.
  • Dynamic overlay height plus the right aligned numbered column makes the picker feel native, not bolted on.
  • The 14 case test script under tests covers state, all four key paths (digit, Enter, Backspace, Esc), the leak guard, every renderer change, and a real TCP session-info round trip across three live sessions. Solid practical proof.

Verified locally before merging:

  • .\scripts\build.ps1 clean on Windows
  • tests\test_issue247_session_picker_digit.ps1 14 of 14 passing
  • cargo test --release --bin psmux 1744 of 1744 passing, no regressions
  • Merged via rebase so your commit lands on master with you as the author

Will go out in the next release. Thanks again for the clean PR and the test coverage that came with it.

psmux added a commit that referenced this pull request Apr 25, 2026
…stomize-mode

PR #248 added digit+Enter quick-jump to the session picker. This commit
extends the same UX to every other interactive picker in the client.

choose-tree / choose-window
  - tree_num_buffer accumulates typed digits alongside picker state
  - Enter uses the buffer as a 1-based row index when non-empty,
    falls back to the arrow cursor otherwise
  - Backspace edits the buffer; Esc clears it and closes
  - catch-all KeyCode::Char(_) guard absorbs non-handled keys so
    they cannot leak through to the focused pane PTY
  - Every row is rendered with a right-aligned dynamic-width 1-based
    number so the mapping is visible
  - 'go to N' indicator shown at the bottom when buffer is non-empty
  - Overlay height grows by 2 rows when the indicator is active
  - PageUp / PageDown / Home / End added (were missing before)
  - Title updated: 'digits+enter=jump  Enter=switch ...'

choose-buffer
  - buffer_num_buffer with identical digit/Enter/Backspace/Esc/leak-guard
  - Enter jumps then pastes; d-delete clears the buffer (indexes shift)
  - Row numbers prepended to each 'bufferN: M bytes: ...' label
  - Overlay height grows by 2 rows when the indicator is active
  - PageUp / PageDown / Home / End added
  - Title updated: 'digits+enter=jump, Enter=paste ...'

customize-mode
  - customize_num_buffer accumulates digits while not editing a value
  - Customize state lives server-side, so Enter computes a navigate
    delta (target_pos - current_pos) and dispatches
    customize-navigate <delta> to jump precisely
  - Buffer is cleared when editing starts or the overlay closes
  - 1-based row numbers shown as a prefix on each option row
  - 'go to N' indicator rendered at the bottom in a cyan bar
  - Header updated: 'digits+Enter:jump  Enter:edit ...'

tests/test_picker_digit_jump_all.ps1  35/35 passing
  - State declarations for all three buffers
  - Picker-open clears buffer
  - Digit / Enter / Backspace / Esc handlers
  - Leak-guard catch-all
  - Renderer: row numbering, 'go to N', title hints
  - Functional: choose-tree data (5 windows), choose-buffer data
    (3 buffers over TCP), customize data (56 options via show-options)
  - Layer-2: visible client survives multi-window CLI-driven session

test_issue247_session_picker_digit.ps1  14/14 still passing (no regression)
@psmux

psmux commented Apr 25, 2026

Copy link
Copy Markdown
Owner

Hey Tarik, your PR was the perfect foundation for something I wanted to extend further.

The digit-jump UX you built for the session picker was so clean that I rolled it out to every other interactive picker in the client, all landed in commit 0f774f4 on master just now.

What is covered now:

choose-tree / choose-window (C-b w)
The tree picker gets its own tree_num_buffer with the exact same flow: digits append, Enter jumps using a 1-based index (falls back to the arrow cursor when the buffer is empty), Backspace edits, Esc clears and closes. I also slipped in the leak-guard catch-all and PageUp / PageDown / Home / End which were missing before. Every row gets a right-aligned numbered prefix and the 2-row "go to N" indicator grows the overlay height the same way yours does.

choose-buffer (C-b =)
Same treatment with buffer_num_buffer. One small nuance: when the user presses d to delete an entry the buffer is cleared (indexes shift, just like you did with x in the session picker). Row labels now look like 1. buffer0: 17 bytes: "hello" so the number is front and center.

customize-mode (C-b : then customize-mode, or however it is bound)
This one is different because customize state lives server-side. There is no local list to index into directly. So when the user types a number and presses Enter, the client computes target_pos - current_pos from the mirrored srv_customize_options slice and dispatches customize-navigate <delta>. It still feels like an instant jump. Digits are ignored while the user is actively editing a value (the buffer is auto-cleared on edit start) so there is no interference with value input.

Tests
tests/test_picker_digit_jump_all.ps1 covers all three pickers with 35 cases: state declarations, picker-open clears, digit/Enter/Backspace/Esc handlers, leak guards, renderer row numbering, "go to N" indicators, title hints, and functional verification that each picker actually has rows to jump to (5 windows, 3 buffers over TCP, 56 options via show-options). Layer-2 visible-client check too. 35 of 35 passing.

Your original test_issue247_session_picker_digit.ps1 still runs 14 of 14, no regressions.

Really appreciated the clean architecture you set up in #248. Having a tight, isolated per-picker buffer with clear open/close/kill lifecycle made it straightforward to replicate everywhere. Good pattern.

@tarikguney

Copy link
Copy Markdown
Collaborator Author

Loved this!

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.

Quick session switching by number (parity with window switching)

2 participants