Skip to content

Fuzzy filtering for the bare-mox session picker#12

Merged
bthall merged 5 commits into
mainfrom
feat/picker-completion
Jul 9, 2026
Merged

Fuzzy filtering for the bare-mox session picker#12
bthall merged 5 commits into
mainfrom
feat/picker-completion

Conversation

@bthall

@bthall bthall commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Summary

Bare mox now opens an interactive fuzzy picker instead of the static numbered list. Type to filter (prefix beats substring beats subsequence), move with arrows or Ctrl-J/K/N/P, Enter attaches, Esc cancels. It renders inline under the prompt and redraws in place: no alt-screen takeover.

Implementation notes:

  • Raw mode comes from golang.org/x/term (plus x/sys indirect, both Go-team maintained). The go directive moved to 1.25 with it, so CI builds with Go 1.25 now.
  • Rows are plain text truncated to the terminal width, which keeps the redraw math exact.
  • The event loop reads from a plain io.Reader, so the whole interaction is unit tested with scripted keystrokes: filtering, arrow/ctrl navigation, wrap-around, backspace, Ctrl-U, and every cancel path.
  • Terminals that refuse raw mode fall back to the numbered prompt. Non-TTY invocations still print help, so scripts are unaffected.

Tests and lint are green locally. Please give the picker a spin in a real terminal before merging, since the ANSI redraw behavior is the one thing unit tests can't fully prove.

bthall added 5 commits July 6, 2026 19:08
Bare mox now renders an inline, redrawing list under the prompt: typing
filters live (prefix beats substring beats subsequence), arrows and
Ctrl-J/K/N/P move the selection, Enter attaches, Esc/Ctrl-C cancels.
Rows are plain text truncated to the terminal width so redraw math
stays exact. Raw-mode terminal handling comes from golang.org/x/term;
when raw mode is unavailable the numbered prompt remains, and non-TTY
invocations keep printing help.

The event loop reads from a plain io.Reader, so the whole interaction
is unit-tested with scripted keystrokes.
The go directive moved to 1.25 with the x/term dependency.
The action's prebuilt v2.0 binary is built with Go 1.24 and exits 3 on
a go 1.25 module. v2.12.2's staticcheck also flags
WriteString(Sprintf(...)), so those become Fprintf.

Also swap the retired Go Report Card badge for the pkg.go.dev
reference badge.
The hand-rolled ANSI renderer read as homemade. The list component
brings styled two-line items (session name over state/windows/activity/
hosts), built-in fuzzy filtering, pagination, and a help footer, running
inline without an alt-screen takeover. Typing filters immediately (the
filter opens on first keystroke), Enter attaches the highlighted
session, Esc clears the filter and then cancels.

Model updates are driven directly in tests with a command-executing
drain loop, so filtering (which the list applies asynchronously) is
covered without a terminal. Replaces the custom fuzzy matcher, raw-mode
handling, and redraw math; x/term drops back to an indirect dependency.
The list pane carries status dots (green running, dim stopped, yellow
unmanaged), an accent bar on the selection, and a match counter while
filtering; the preview pane shows the highlighted session's live state
plus everything the config knows: hosts, connect template, sync,
arrange, root, window layout. Panels are hand-drawn with title and
key-hint borders, colored strictly from the terminal's 16-color palette
so the user's theme decides the look. Narrow terminals collapse to the
list pane alone.

Filtering is now synchronous (sahilm/fuzzy directly), which also
simplifies the model tests back to plain Update calls; bubbles/list and
its async filter plumbing are gone.
@bthall bthall merged commit 026c7c2 into main Jul 9, 2026
5 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