mirror of
https://github.com/neovim/neovim.git
synced 2026-08-26 00:51:53 +00:00
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:
@@ -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) {
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user