fix(spell): avoid invalid window state after async spell select (#41346)

Problem:
When `z=` delegates to `vim.ui.select()`, the picker may change the
current window before returning. `spell_suggest()` then continues to the
cursor restoration branch with the new window and assigns `prev_cursor`,
which belongs to the original window. This can leave Normal mode with an
invalid cursor position and produce E315.

Solution:
Clean up the spell suggestion state and return immediately after handing
control to `vim.ui.select()`.
This commit is contained in:
not_compiled
2026-08-17 08:46:11 +05:30
committed by GitHub
parent 581ce0b3da
commit 8c0bf18374
2 changed files with 36 additions and 0 deletions

View File

@@ -585,11 +585,16 @@ void spell_suggest(int count)
}
} else {
// Hand off to (async) vim.ui.select().
curwin->w_p_spell = wo_spell_save;
select_spell_suggestion(&sug);
lines_left = Rows; // avoid more prompt
// don't delay for 'smd' in normal_cmd()
msg_scroll = msg_scroll_save;
spell_find_cleanup(&sug);
xfree(line);
return;
}
if (selected > 0 && selected <= sug.su_ga.ga_len && u_save_cursor() == OK) {

View File

@@ -229,6 +229,37 @@ describe('vim.ui.select()', function()
eq(got.items[1].word, api.nvim_buf_get_lines(0, 0, -1, false)[1])
end)
it('does not produce E315 when picker changes the current window', function()
prepare_test()
api.nvim_buf_set_lines(0, 0, -1, false, {
'Praesent enim diam,',
'Praesent enim diam,',
'Praesent enim diam,',
'Praesent enim diam,',
'Praesent enim diam,',
})
-- Keep the cursor beyond the popup's single line to reproduce E315.
api.nvim_win_set_cursor(0, { 5, 0 })
exec_lua(function()
vim.ui.select = function()
local buf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_open_win(buf, true, {
row = 10,
col = 10,
height = 10,
width = 10,
relative = 'editor',
style = 'minimal',
})
end
vim.cmd('normal! wz=')
end)
end)
it('does nothing when the user cancels', function()
prepare_test()