feat(stack): fzf-style interactive picker for mergify stack open#1704
Conversation
Merge Protections🟢 All 6 merge protections satisfied — ready to merge. Show 6 satisfied protections🟢 🤖 Continuous Integration
🟢 👀 Review Requirements
🟢 Enforce conventional commitMake sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
🟢 🔎 Reviews
🟢 📕 PR description
🟢 🚦 Auto-queueWhen all merge protections are satisfied, this pull request will be queued automatically. |
There was a problem hiding this comment.
Pull request overview
Adds an interactive, fzf-style fuzzy picker to mergify stack open when no <commit> is provided and all stdio streams are TTYs, while preserving the existing non-interactive “open leaf PR” behavior for scripts/pipes. The picker implementation is introduced behind a new mergify-tui boundary and wired into stack open via an injectable selector callback for testability.
Changes:
- Introduces
mergify_tui::select::fuzzy_select()(dialoguerFuzzySelect) with match highlighting and cancellation mapping. - Extends
mergify stack opento optionally run an injected selector (TTY-gated in the binary) and adds aCancelledoutcome. - Updates CLI schema snapshot/help text and adds new dependencies (
dialoguer,ctrlc,console) in the workspace.
Reviewed changes
Copilot reviewed 8 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| crates/mergify-tui/src/theme.rs | Exposes colors_enabled() to allow picker theming to follow the existing color policy. |
| crates/mergify-tui/src/select.rs | New fuzzy-picker wrapper around dialoguer, including SIGINT/cursor-restore logic. |
| crates/mergify-tui/src/lib.rs | Exports the new select module and fuzzy_select() API. |
| crates/mergify-tui/Cargo.toml | Adds dialoguer, ctrlc, and console dependencies for picker functionality. |
| crates/mergify-stack/src/commands/open.rs | Adds selector injection, label building, interactive selection, and Cancelled outcome. |
| crates/mergify-cli/src/snapshots/mergify__tests__cli_schema_golden.snap | Updates the stack open commit help/longHelp text in the schema snapshot. |
| crates/mergify-cli/src/main.rs | Wires TTY gating and injects mergify_tui::fuzzy_select into stack open; maps Cancelled to success. |
| Cargo.toml | Adds shared workspace dependencies for picker support. |
| Cargo.lock | Locks new transitive dependencies pulled in by dialoguer/ctrlc/console. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Wraps dialoguer::FuzzySelect behind the mergify-tui boundary: shared theming policy, Esc/Ctrl-C-as-cancel contract, and no direct dialoguer dependency in command crates. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Change-Id: Idde18b02d2d99120dda58e1cf46f2c2d8cf2c844
open::Options gains an injectable Selector (None = today's leaf default) and Outcome::Cancelled for a dismissed picker. Pure label/selection helpers are unit-tested without a TTY; the explicit-commit and non-TTY paths are untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Change-Id: I7c344cbe182329006802bbbb6221898b47d779ea
With no <commit> argument on a TTY, stack open now shows a fuzzy picker over the stack (type to filter, HEAD preselected, Esc/Ctrl-C cancels with exit 0). Non-TTY and explicit-commit invocations are byte-identical to before. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Change-Id: I540f15b2f6e87fdf5a9f18a90e1d769b242225ee
console re-raises SIGINT from the raw-mode key reader, so Ctrl-C killed the process at 130 with dialoguer's hidden cursor leaked. A lazily installed handler now restores the cursor and exits 130 (the fzf convention). The picker gate also requires stderr to be a TTY — that's where dialoguer draws — and the redundant max_length cap is gone along with the terminal_size dependency. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Change-Id: I6985543c4881a539da3a264bc13e547cf6d88409
Closes the window where a Ctrl-C arriving during the picker's error path could observe PICKER_ACTIVE already false and skip the cursor restore. Also retires comments still describing the pre-130 Ctrl-C contract and the stdout-only TTY gate. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Change-Id: I8a8acff6d00307546da9360e75fe0b0f58ac00ad
ac3c3ab to
d998d21
Compare
Bounds-check the injected selector's index (typed CliError instead of an index panic) and make the leaf-default arm panic-free if the empty-stack guard ever moves. Addresses Copilot review on #1704. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Change-Id: I4413404e83ae59af9e0950a088707ad3e03cbbac
Merge Queue Status
This pull request spent 8 minutes 5 seconds in the queue, including 7 minutes 46 seconds running CI. Required conditions to merge
|
What
mergify stack openwith no<commit>argument on a terminal now shows an fzf-style fuzzy picker over the stack's PRs — type to filter (skim'sSkimMatcherV2viadialoguer::FuzzySelect), matched characters highlighted, leaf (HEAD) preselected, Enter opens the PR in the browser.The Python CLI had an interactive picker; the Rust port dropped it ("left out of the port for now"). This restores it, upgraded from an arrow-key list to fuzzy filtering.
Behavior
mergify stack open(stdin+stdout+stderr all TTYs)mergify stack opennon-TTYmergify stack open <commit>Entries without a PR are listed as
(no PR) <title> (<sha7>)so the stack shape stays visible; selecting one fails with the existing "runmergify stack pushfirst" error.Design notes
mergify_tui::select::fuzzy_select()boundary — command crates never depend on it, and future pickers (checkout,edit,reword) reuse the same entry point. Dep isdialoguer 0.12, default-features = false, features = ["fuzzy-select"].open::Optionsgains an injectableSelectorcallback (same testability-by-parameter pattern asqueue pause'sconfirm), so cancel/label logic is unit-tested without a TTY.ctrlchandler restores the cursor and exits 130. (consoleis pinned to the same 0.16 dialoguer uses; single copy in the lockfile.)mergify stack open 2>/dev/nullwould sit in raw mode drawing nothing.commitargument's clap doc was updated; the CLI-schema golden snapshot regenerated (that one description only).Test plan
Interrupted→ cancel fallback), label building, leaf-default index, selector error mapping (19 new/updated tests; workspace suite green)$?= 0, Ctrl-C →$?= 130 with cursor visible,2>/dev/nullopens leaf silently🤖 Generated with Claude Code