Skip to content

sp open: interactive fuzzy picker when no id is given (#10) - #24

Merged
rwrife merged 1 commit into
mainfrom
issue-10-fuzzy-open
Jul 8, 2026
Merged

sp open: interactive fuzzy picker when no id is given (#10)#24
rwrife merged 1 commit into
mainfrom
issue-10-fuzzy-open

Conversation

@rwrife

@rwrife rwrife commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Closes #10

What changed

sp open with no id now launches an interactive picker over the live scratches instead of requiring an id up front.

New internal/picker package (stdlib-only, no new deps)

  • match.go — pure, I/O-free fuzzy matcher. Case-insensitive subsequence match over each scratch's id + name + tags, ranked with bonuses for contiguous runs and word-boundary hits (so tdotodo, and a clean prefix outranks a scattered match). Fully unit-tested.
  • select.go — front-ends chosen in priority order:
    1. fzf, when installed + on a TTY (the issue's "detect and defer to fzf if present").
    2. Built-in filter prompt on a TTY without fzf: numbered list, type to fuzzy-filter, number to pick, blank line takes the top match, q/Esc/Ctrl-C/EOF cancels.
    3. One-shot numbered prompt when not a TTY — the required graceful degradation for pipes/scripts.

Wiring

  • sp open is now MaximumNArgs(1): sp open <id> keeps its exact old behavior; sp open (bare) runs the picker. Added --no-fzf to force the built-in picker.
  • Extracted openScratch as the shared tail so a picked scratch opens identically to an explicit id (one $EDITOR launch site preserved).
  • render.PickerLabel renders each row (id, name, age, expires-in, tags) — presentation stays in render; the picker owns interaction only. Plain (no ANSI) since the labels are also the fuzzy-match/fzf input.

Acceptance criteria

  • sp open with no id opens an interactive selector (name, age, expires-in, tags visible)
  • Keyboard-driven fuzzy filter; Enter/number opens the highlighted scratch in $EDITOR
  • Works without an external fzf dependency (built-in prompt); detects and defers to fzf if present
  • Esc/Ctrl-C/q cancels cleanly with no changes
  • Degrades to a numbered prompt when not a TTY

Notes / deviations

  • I went with a dependency-light built-in prompt rather than pulling in bubbletea/huh. Rationale: keeps go.mod unchanged (no go mod tidy churn, smaller supply-chain surface) and makes the whole selection flow headlessly unit-testable. The interaction still satisfies "keyboard-driven fuzzy filter" without raw-mode TUI. Happy to swap in a bubbletea TUI in a follow-up if you'd prefer the richer full-screen feel.
  • The "extend to sp cat/rm/resurrect" idea from the issue notes is intentionally not in scope here; the picker package is structured so those can reuse Select later.

Testing

  • 22 new tests across internal/picker (matcher + all three front-ends incl. fzf via injected fakes, and every cancel path) plus internal/cli (sp open picker end-to-end) and internal/render (label).
  • go build ./... && go vet ./... && go test ./... all green; gofmt clean; go mod tidy produces no diff.

@rwrife rwrife mentioned this pull request Jul 7, 2026
5 tasks
@rwrife
rwrife merged commit d6faf8a into main Jul 8, 2026
1 check passed
@rwrife
rwrife deleted the issue-10-fuzzy-open branch July 8, 2026 09:02
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.

[feature] Fuzzy picker for sp open

1 participant