Skip to content

fix: wrong mode after :term then quickly stopi->close->new picker->starti#2688

Merged
phanen merged 1 commit intomainfrom
stopinsert-hack
Apr 20, 2026
Merged

fix: wrong mode after :term then quickly stopi->close->new picker->starti#2688
phanen merged 1 commit intomainfrom
stopinsert-hack

Conversation

@phanen
Copy link
Copy Markdown
Collaborator

@phanen phanen commented Apr 20, 2026

Fix #2685.

reuse=true should also work, but it break previewer for some reason.

Summary by CodeRabbit

  • Refactor
    • Safer invocation flow for built-in actions, reducing launch failures and unexpected behavior when invoking features.
    • Improved window-close handling with deferred mode transitions to avoid terminal/insert-mode glitches and stray mode changes during close.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 20, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 40d9fd7d-ec0d-4490-809b-007e2b8e8186

📥 Commits

Reviewing files that changed from the base of the PR and between 4ad4431 and 194a3d2.

📒 Files selected for processing (2)
  • lua/fzf-lua/actions.lua
  • lua/fzf-lua/win.lua
🚧 Files skipped from review as they are similar to previous changes (2)
  • lua/fzf-lua/actions.lua
  • lua/fzf-lua/win.lua

📝 Walkthrough

Walkthrough

Adds a deferred stop-insert helper and a global one-shot hook for invoking builtin actions: win.lua implements stopinsert(ctx) which defers :stopinsert and schedules a stored callback via autocmds; actions.lua resolves builtins with vim.F.nil_wrap(...) and routes execution through the global hook when present.

Changes

Cohort / File(s) Summary
Builtin Action Execution
lua/fzf-lua/actions.lua
M.run_builtin now resolves the requested builtin with vim.F.nil_wrap(require "fzf-lua"[method]) and, if _G.fzf_lua_stopinsert_hack exists, passes the resolved function to it instead of calling the function immediately.
Window / Stopinsert Helper
lua/fzf-lua/win.lua
Introduced local stopinsert(ctx) and replaced direct vim.cmd("stopinsert") in FzfWin:close with the helper. The helper clears/sets _G.fzf_lua_stopinsert_hack, conditionally runs :stopinsert when ctx.mode == "nt", and installs one-shot User + ModeChanged autocmds to schedule and then clear the deferred callback.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant FzfLua as actions.lua
    participant Win as win.lua
    participant Neovim

    User->>FzfLua: select builtin entry
    FzfLua->>FzfLua: resolve method via vim.F.nil_wrap(require ...)
    alt global hook present
        FzfLua->>Win: pass resolved fn to _G.fzf_lua_stopinsert_hack
        Win->>Neovim: maybe execute :stopinsert (if ctx.mode == "nt" and mode differs)
        Win->>Neovim: register one-shot User & ModeChanged autocmds
        Neovim->>Win: ModeChanged to nt fires
        Win->>Neovim: schedule execution of stored User autocmds
        Neovim->>FzfLua: invoke resolved builtin (deferred)
    else no hook
        FzfLua->>FzfLua: call resolved fn() directly
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped a mode and left a tiny track,
A one-shot hook to call the thing back,
Autocmds ready, scheduled with care,
Buffers stay put — I nibble the air. 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: fixing mode handling after terminal interactions followed by picker operations.
Linked Issues check ✅ Passed The code changes address issue #2685's objectives by implementing proper mode handling and buffer preservation through deferred autocmd execution rather than immediate commands.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing mode handling and terminal buffer deletion issues; no unrelated modifications are present.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch stopinsert-hack

Warning

Review ran into problems

🔥 Problems

Timed out fetching pipeline failures after 30000ms


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lua/fzf-lua/win.lua (1)

1169-1201: ⚠️ Potential issue | 🟡 Minor

Verify the ModeChanged→User-autocmd event ordering and add test coverage for rapid :FzfLua invocations from terminal mode.

The mechanism depends on this synchronization:

  1. stopinsert(ctx) registers the ModeChanged listener at line 1178, having just issued stopinsert at line 1172.
  2. run_builtin (line 519–520) registers the User listener before the queued ModeChanged event is processed.

If Neovim processes the ModeChanged event before the User autocmd is registered (e.g., if both are in the same event-loop cycle or if action dispatch is deferred), nvim_exec_autocmds("User", …) runs with no listener, and the selected builtin entry is dropped. The schedule_wrap on line 1175 schedules the callback once the event fires, but does not defer the event firing itself. A race is possible if the two registration events are not strictly ordered.

Additionally, the change from unconditional to conditional stopinsert (line 1171 guard) should be tested for any non-terminal-mode workflows that previously depended on unconditional restoration (see the comment at line 1197 about restoring normal mode).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lua/fzf-lua/win.lua` around lines 1169 - 1201, The ModeChanged→User autocmd
registration can race and drop the selected entry; in stopinsert ensure the User
autocmd (the callback stored into _G.fzf_lua_stopinsert_hack) is
created/registered before you register the ModeChanged autocmd or otherwise
ensure ordering (e.g. assign and register the User autocmd first, or defer
ModeChanged registration with vim.schedule) so nvim_exec_autocmds("User", ...)
always finds the listener; update stopinsert (and the places that call it such
as FzfWin:close and run_builtin) to guarantee the User handler exists before
ModeChanged can fire and add tests simulating rapid :FzfLua invocations from
terminal mode and a test for the conditional stopinsert guard to cover
non-terminal-mode workflows.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@lua/fzf-lua/win.lua`:
- Around line 1169-1201: The ModeChanged→User autocmd registration can race and
drop the selected entry; in stopinsert ensure the User autocmd (the callback
stored into _G.fzf_lua_stopinsert_hack) is created/registered before you
register the ModeChanged autocmd or otherwise ensure ordering (e.g. assign and
register the User autocmd first, or defer ModeChanged registration with
vim.schedule) so nvim_exec_autocmds("User", ...) always finds the listener;
update stopinsert (and the places that call it such as FzfWin:close and
run_builtin) to guarantee the User handler exists before ModeChanged can fire
and add tests simulating rapid :FzfLua invocations from terminal mode and a test
for the conditional stopinsert guard to cover non-terminal-mode workflows.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 35325ec5-3f5f-420f-8603-2446f6ed2ac7

📥 Commits

Reviewing files that changed from the base of the PR and between 423533d and c86c091.

📒 Files selected for processing (2)
  • lua/fzf-lua/actions.lua
  • lua/fzf-lua/win.lua

@phanen phanen merged commit 3da04a9 into main Apr 20, 2026
11 checks passed
@phanen phanen deleted the stopinsert-hack branch April 20, 2026 15:28
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.

Bug: FzfLua builtin > buffers deletes terminal buffer

1 participant