Skip to content

fix(nvim): keep cursor position when picker closes from insert mode (#968) - #969

Merged
dkovalenko-oai merged 1 commit into
mainfrom
triage-bot/issue-968
Nov 6, 2026
Merged

dkovalenko-oai merged 1 commit into
mainfrom
triage-bot/issue-968

Conversation

@gustav-fff

@gustav-fff gustav-fff commented Oct 25, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #968

Root cause

M.close() runs stopinsert (lua/fff/picker_ui/layout_manager.lua:81), but this is deferred until mapping returns. Floats close first, so Insert mode ends in original window and <Esc> semantics move its cursor one cell left. This hits every close from insert mode: vim-mode <C-c> (ui_creator.lua:359), and default-mode <Esc> too. Vim-mode <Esc><Esc> is fine because close happens from normal mode.

Fix

When close() runs in insert mode, remember cursor of window we return to and restore it on one-shot ModeChanged i:*, but only if window still shows same buffer. This fires before scheduled file-open in select(), so jump locations are not touched.

Steps to reproduce

make build
printf 'hello world foo bar\n' > /tmp/a.txt
nvim --clean -u NONE --cmd "set rtp^=$PWD" --cmd "lua require('fff').setup({ prompt_vim_mode = true })" /tmp/a.txt

Inside nvim:

:call cursor(1, 7)
:lua require('fff').find_files()
" press <C-c>
:echo getcurpos()[1:2]

Expected [1, 7], actual on main: [1, 6]. Same with prompt_vim_mode = false and <Esc>.

Headless version (no UI needed):

SOCK=/tmp/fff968.sock
nvim --clean -u NONE --headless --listen $SOCK --cmd "set rtp^=$PWD" --cmd "lua require('fff').setup({ prompt_vim_mode = true })" /tmp/a.txt &
sleep 1
nvim --server $SOCK --remote-expr 'execute("call cursor(1, 7)")'
nvim --server $SOCK --remote-expr 'luaeval("require(\"fff\").find_files() or 1")'; sleep 1
nvim --server $SOCK --remote-send '<C-c>'; sleep 1
nvim --server $SOCK --remote-expr 'string(getcurpos()[1:2])'   # main: [1, 6]  fix: [1, 7]
nvim --server $SOCK --remote-expr 'execute("qa!")'

How verified

Same headless RPC harness, before -> after:

  • vim mode <C-c>: [1,6] -> [1,7]
  • default mode <Esc>: [1,6] -> [1,7]
  • vim mode <Esc><Esc>, <Esc>q: [1,7] both, unchanged
  • col 0, end of line, multibyte char (ö, byte col 9): position kept
  • live_grep select in same buffer (line 2): [2,13] both, location jump unchanged
  • select other file: opens b.txt at [1,1], unchanged
  • make test-lua: 11 specs, 0 failed
  • stylua --check: clean
  • make test-lua-snap: same 16 local snapshot diffs with and without this change (local ranking differs), not caused by it

Automated triage via Gustav. Honk-Honk 🪿

Summary by CodeRabbit

  • Bug Fixes
    • Closing the picker while in Insert mode now restores the cursor to its original position when the original window and buffer are still available.

…968)

stopinsert is deferred, so Insert mode ended in the original window after
the picker floats closed and moved its cursor one cell left. Restore the
cursor once Insert mode actually ends.

Closes #968
@coderabbitai

coderabbitai Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Walkthrough

When the picker closes in Insert mode, the layout manager captures the original window, buffer, and cursor. After Insert mode ends, it restores the cursor if the window remains valid and displays the original buffer.

Changes: Cursor restoration

Layer / File(s) Summary
Capture and restore cursor after close
lua/fff/picker_ui/layout_manager.lua
A one-shot ModeChanged autocmd restores the captured cursor after Insert mode ends if the original window remains valid and displays the original buffer. M.close invokes the helper when the current mode is Insert.

Priority: Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Low

Suggested reviewers: dmtrkovalenko

Merge Risk: Minimal · up to 0a5ed

No concrete current-head merge risk is established by the supplied review evidence.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 1 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: preserving the cursor position when the Neovim picker closes from Insert mode.
Linked Issues check Passed Issue #968 requires the Neovim plugin to preserve the return window cursor when the picker closes from Insert mode with . The change captures the current window, buffer, and cursor after picker w…
Out of Scope Changes check Passed The diff only adds cursor preservation logic in lua/fff/picker_ui/layout_manager.lua and invokes it during picker close. The default-mode <Esc> case is the same cursor-shift defect and supports is…
Full details: Linked Issues check

Explanation

Issue #968 requires the Neovim plugin to preserve the return window cursor when the picker closes from Insert mode with <C-c>. The change captures the current window, buffer, and cursor after picker windows close, then restores the cursor on the one-shot ModeChanged i:* event when the window still shows the same buffer. The reported RPC checks show [1,7] after vim-mode &lt;C-c&gt; and default-mode &lt;Esc&gt;. The reported Lua tests and formatting checks pass.

Full details: Out of Scope Changes check

Explanation

The diff only adds cursor preservation logic in lua/fff/picker_ui/layout_manager.lua and invokes it during picker close. The default-mode &lt;Esc&gt; case is the same cursor-shift defect and supports issue #968. No unrelated product behavior is changed.

Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔇 Additional comments: 1
lua/fff/picker_ui/layout_manager.lua-31-32: 1

31-32: Minor · Functional Correctness · Quick win

⚠️ Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.

Preserve cursor moves made by FFFClose handlers.

If an FFFClose handler moves the cursor within the return window’s buffer, this callback restores the earlier position when Insert mode ends. The window and buffer checks do not distinguish that move from the stopinsert shift. Limit restoration to the shift caused by leaving Insert mode. FFFClose runs after this callback is registered at Line 168; ModeChanged runs after the mode changes. (neovim.io)


Review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e0d5abb2-e974-46f6-965b-7e8670aabbf2
Commits

Reviewing files that changed from the base of the PR and between 7353971 and 0a5edfc.

Files selected for processing: 1
  • lua/fff/picker_ui/layout_manager.lua

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

@dkovalenko-oai
dkovalenko-oai merged commit 5d21e4b into main Nov 6, 2026
54 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.

[Bug]: nvim: cursor moves left when prompt_vim_mode = true and when the picker is closed with <C-c>

2 participants