mirror of
https://github.com/neovim/neovim.git
synced 2026-05-26 06:48:27 +00:00
fix(api): adjust Visual position after nvim_buf_set_text #30690
Problem: Visual selection could end up in the wrong place after nvim_buf_set_text or nvim_buf_set_lines. In some delete cases, Visual.lnum was already clamped before the line shift happened, so the adjustment got skipped. Solution: Split fix_cursor_cols into reusable fix_pos_col logic and reuse it for Visual updates. Also adjust Visual.lnum before changed_lines so the shift uses the original position before final clamping.
This commit is contained in:
@@ -1021,6 +1021,110 @@ describe('api/buf', function()
|
||||
eq({ 1, 4 }, api.nvim_win_get_cursor(win2))
|
||||
end)
|
||||
|
||||
it('keep visual select position #29558', function()
|
||||
insert([[1234]])
|
||||
api.nvim_win_set_cursor(0, { 1, 1 })
|
||||
feed('vl')
|
||||
exec_lua([[
|
||||
vim.defer_fn(function() vim.api.nvim_buf_set_text(0, 0, 0, 0, 0, { '0' }) end, 50)
|
||||
vim.wait(80)
|
||||
]])
|
||||
local mode = api.nvim_get_mode().mode
|
||||
eq({ '23' }, fn.getregion(fn.getpos('.'), fn.getpos('v'), { type = mode }))
|
||||
eq({ 'v', { '01234' } }, { mode, api.nvim_buf_get_lines(0, 0, -1, false) })
|
||||
feed('<ESC>')
|
||||
|
||||
api.nvim_buf_set_lines(0, 0, -1, false, { '1', '2', '3' })
|
||||
api.nvim_win_set_cursor(0, { 2, 0 })
|
||||
feed('v')
|
||||
exec_lua([[
|
||||
vim.defer_fn(function() vim.api.nvim_buf_set_text(0, 0, 0, 0, 0, { '0', '' }) end, 50)
|
||||
vim.wait(80)
|
||||
]])
|
||||
mode = api.nvim_get_mode().mode
|
||||
eq({ '2' }, fn.getregion(fn.getpos('.'), fn.getpos('v'), { type = mode }))
|
||||
eq({ 'v', { '0', '1', '2', '3' } }, { mode, api.nvim_buf_get_lines(0, 0, -1, false) })
|
||||
feed('<ESC>')
|
||||
|
||||
api.nvim_buf_set_lines(0, 0, -1, false, { '1', '2' })
|
||||
api.nvim_win_set_cursor(0, { 1, 0 })
|
||||
feed('vj')
|
||||
exec_lua([[
|
||||
vim.defer_fn(function() vim.api.nvim_buf_set_text(0, 0, 0, 0, 0, { '0' }) end, 50)
|
||||
vim.wait(80)
|
||||
]])
|
||||
mode = api.nvim_get_mode().mode
|
||||
eq({ '1', '2' }, fn.getregion(fn.getpos('.'), fn.getpos('v'), { type = mode }))
|
||||
eq({ 'v', { '01', '2' } }, { mode, api.nvim_buf_get_lines(0, 0, -1, false) })
|
||||
feed('<ESC>')
|
||||
|
||||
api.nvim_buf_set_lines(0, 0, -1, false, { '123' })
|
||||
api.nvim_win_set_cursor(0, { 1, 1 })
|
||||
feed('v')
|
||||
exec_lua([[
|
||||
vim.defer_fn(function() vim.api.nvim_buf_set_text(0, 0, 0, 0, 0, { '', '' }) end, 50)
|
||||
vim.wait(80)
|
||||
]])
|
||||
mode = api.nvim_get_mode().mode
|
||||
eq({ '2' }, fn.getregion(fn.getpos('.'), fn.getpos('v'), { type = mode }))
|
||||
eq({ 'v', { '', '123' } }, { mode, api.nvim_buf_get_lines(0, 0, -1, false) })
|
||||
feed('<ESC>')
|
||||
|
||||
-- Visual block mode
|
||||
api.nvim_buf_set_lines(0, 0, -1, false, { '123', '456' })
|
||||
api.nvim_win_set_cursor(0, { 1, 0 })
|
||||
feed('<C-v>jl')
|
||||
exec_lua([[
|
||||
vim.defer_fn(function() vim.api.nvim_buf_set_text(0, 0, 0, 0, 0, { '0' }) end, 50)
|
||||
vim.wait(80)
|
||||
]])
|
||||
mode = api.nvim_get_mode().mode
|
||||
eq({ '01', '45' }, fn.getregion(fn.getpos('.'), fn.getpos('v'), { type = mode }))
|
||||
eq(
|
||||
{ string.char(0x16), { '0123', '456' } },
|
||||
{ mode, api.nvim_buf_get_lines(0, 0, -1, false) }
|
||||
)
|
||||
feed('<ESC>')
|
||||
-- also test nvim_buf_set_lines inserts line above visual selection
|
||||
api.nvim_buf_set_lines(0, 0, -1, false, { '1', '2', '3' })
|
||||
api.nvim_win_set_cursor(0, { 2, 0 })
|
||||
feed('v')
|
||||
exec_lua([[
|
||||
vim.defer_fn(function() vim.api.nvim_buf_set_lines(0, 0, 0, false, { 'new' }) end, 50)
|
||||
vim.wait(80)
|
||||
]])
|
||||
mode = api.nvim_get_mode().mode
|
||||
eq({ '2' }, fn.getregion(fn.getpos('.'), fn.getpos('v'), { type = mode }))
|
||||
eq({ 'v', { 'new', '1', '2', '3' } }, { mode, api.nvim_buf_get_lines(0, 0, -1, false) })
|
||||
feed('<ESC>')
|
||||
|
||||
api.nvim_buf_set_lines(0, 0, -1, false, { '1234' })
|
||||
api.nvim_win_set_cursor(0, { 1, 1 })
|
||||
feed('vl')
|
||||
exec_lua([[
|
||||
vim.defer_fn(function()
|
||||
vim.api.nvim_buf_set_text(0, 0, 0, 0, 0, { '0', 'foo' })
|
||||
end, 50)
|
||||
vim.wait(80)
|
||||
]])
|
||||
mode = api.nvim_get_mode().mode
|
||||
eq({ '23' }, fn.getregion(fn.getpos('.'), fn.getpos('v'), { type = mode }))
|
||||
eq({ 'v', { '0', 'foo1234' } }, { mode, api.nvim_buf_get_lines(0, 0, -1, false) })
|
||||
feed('<ESC>')
|
||||
|
||||
api.nvim_buf_set_lines(0, 0, -1, false, { '1', '2', '3', '4', '5', '6', '7', '8', '9', '10' })
|
||||
api.nvim_win_set_cursor(0, { 8, 0 })
|
||||
feed('v')
|
||||
exec_lua([[
|
||||
vim.defer_fn(function() vim.api.nvim_buf_set_lines(0, 0, 5, false, {}) end, 50)
|
||||
vim.wait(80)
|
||||
]])
|
||||
mode = api.nvim_get_mode().mode
|
||||
eq({ '8' }, fn.getregion(fn.getpos('.'), fn.getpos('v'), { type = mode }))
|
||||
eq({ 'v', { '6', '7', '8', '9', '10' } }, { mode, api.nvim_buf_get_lines(0, 0, -1, false) })
|
||||
feed('<ESC>')
|
||||
end)
|
||||
|
||||
describe('when text is being added right at cursor position #22526', function()
|
||||
it('updates the cursor position in NORMAL mode', function()
|
||||
insert([[
|
||||
|
||||
Reference in New Issue
Block a user