Skip to content

fix(picker/fzf): bugfix pass — hide/resume opt-out + reload action field index#303

Merged
barrettruth merged 2 commits intomainfrom
fix/bugfix
Apr 17, 2026
Merged

fix(picker/fzf): bugfix pass — hide/resume opt-out + reload action field index#303
barrettruth merged 2 commits intomainfrom
fix/bugfix

Conversation

@barrettruth
Copy link
Copy Markdown
Owner

Problem

Two picker bugs after #300:

  1. <c-c> on a forge picker could revive an older fzf-lua session instead of cleanly exiting. fzf-lua's default hide/resume behavior keeps a stack of previously-run pickers and restores the previous one on abort, which conflicts with forge's own back-flow navigation.
  2. In the CI picker (and any other picker that uses entry_source), every action is registered with reload = true. fzf-lua converts those into fzf-level execute-silent(...)+reload(...) binds via shell.stringify_data2(fn, opts, v.field_index or "{+}"). We never set field_index, so fzf expanded the full tab-delimited line. selected_index expected the last \t(%d+)$ to be the index column — true before feat(pickers): unify <c-s> state toggle across pr, issue, ci with per-row labels #300, but feat(pickers): unify <c-s> state toggle across pr, issue, ci with per-row labels #300 appended a per-row header column after the index whenever a dynamic label was present, so the regex either matched the numeric track_id at the head or nothing at all. Every reload action (including <cr>, <c-w>, <c-x> in the CI picker) dispatched with entry = nil and silently no-oped.

Solution

Two independent commits on this branch:

  1. fix(picker/fzf): opt out of fzf-lua hide/resume so <c-c> fully exits — pass no_hide = true and no_resume = true to fzf_exec. Forge manages its own picker navigation (back action + picker session) so fzf-lua's hide-stack is unnecessary and actively harmful here.
  2. fix(picker/fzf): pass only the index field to reload actions — set field_index = tracked and '{3}' or '{2}' on each reload-mode action. fzf now passes just the index column to action_fn, matching what --accept-nth already does for non-reload actions, and works identically whether or not the hidden header column is present.

Regression tests added for both: no_hide/no_resume on any forge picker, and field_index plus a dispatch round-trip on tracked/untracked pickers. 502 busted tests, full local CI clean (stylua / selene / prettier / nix fmt / lua-language-server / vimdoc-language-server / busted).

Supersedes #302.

Forge already manages its own picker navigation and back flow through
the back action and picker sessions. fzf-lua's default hide/resume
state would keep older pickers alive in its own stack, so aborting
the current picker with <c-c> could surface a stale session from an
earlier flow instead of fully exiting.

Pass no_hide = true and no_resume = true to fzf_exec so the hide-stack
is never populated and <c-c> terminates the active forge picker flow
cleanly.

Adds a regression test asserting both flags are on captured.opts for
any forge picker.
Pickers that use entry_source mark every action as reload=true.
fzf-lua converts those into fzf-level execute-silent(...)+reload(...)
binds via shell.stringify_data2(fn, opts, field_index or "{+}"). With
the default "{+}" placeholder, fzf expands the full tab-delimited
line when the bind fires.

selected_index expects the index column to be the last tab-delimited
field. That held before #300 (line layout track_id<TAB>text<TAB>index).
#300 appended a per-row header column whenever a dynamic label was
present, shifting the layout to track_id<TAB>text<TAB>index<TAB>header,
so the trailing-digits regex started matching the numeric track_id (or
nothing at all) and every reload action in the CI picker dispatched
with entry = nil, silently no-oping.

Pin field_index on each reload-mode action to the index column:
"{3}" for tracked pickers, "{2}" for untracked. fzf now passes just
the index string to action_fn, matching what --accept-nth already
does for non-reload actions, and works identically whether or not
the hidden header column is present.

Adds regression tests asserting the field_index value on tracked
and untracked pickers, plus a dispatch round-trip.
@barrettruth barrettruth merged commit 6caa5bd into main Apr 17, 2026
1 check passed
@barrettruth barrettruth deleted the fix/bugfix branch April 17, 2026 22:11
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