commit bd01bd6564790d977095447ae70082c97fbbd480
parent 4db58f78b49feb685555580e44fd338525331be3
Author: zeertzjq <zeertzjq@outlook.com>
Date: Mon, 26 May 2025 06:51:15 +0800
vim-patch:9.1.1407: Can't use getpos('v') in OptionSet when using setbufvar() (#34177)
Problem: Can't use getpos('v') in OptionSet when using setbufvar().
Solution: Don't reset Visual selection when switching to the same
buffer (zeertzjq).
closes: vim/vim#17373
https://github.com/vim/vim/commit/5717ee33db0048a496e8bed0b0cb20133b3f76ca
Diffstat:
4 files changed, 63 insertions(+), 3 deletions(-)
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
@@ -1268,9 +1268,10 @@ void aucmd_prepbuf(aco_save_T *aco, buf_T *buf)
{
win_T *win;
bool need_append = true; // Append `aucmd_win` to the window list.
+ const bool same_buffer = buf == curbuf;
// Find a window that is for the new buffer
- if (buf == curbuf) { // be quick when buf is curbuf
+ if (same_buffer) { // be quick when buf is curbuf
win = curwin;
} else {
win = NULL;
@@ -1360,9 +1361,11 @@ void aucmd_prepbuf(aco_save_T *aco, buf_T *buf)
aco->new_curwin_handle = curwin->handle;
set_bufref(&aco->new_curbuf, curbuf);
- // disable the Visual area, the position may be invalid in another buffer
aco->save_VIsual_active = VIsual_active;
- VIsual_active = false;
+ if (!same_buffer) {
+ // disable the Visual area, position may be invalid in another buffer
+ VIsual_active = false;
+ }
}
/// Cleanup after executing autocommands for a (hidden) buffer.
diff --git a/test/functional/legacy/autocmd_spec.lua b/test/functional/legacy/autocmd_spec.lua
@@ -11,6 +11,30 @@ local eq = t.eq
before_each(clear)
+local function expected_empty()
+ eq({}, api.nvim_get_vvar('errors'))
+end
+
+-- oldtest: Test_get_Visual_selection_in_curbuf_autocmd()
+it('autocmd can get Visual selection when using setbufvar() on curbuf', function()
+ n.exec([[
+ new
+ autocmd OptionSet list let b:text = getregion(getpos('.'), getpos('v'))
+ call setline(1, 'foo bar baz')
+
+ normal! gg0fbvtb
+ setlocal list
+ call assert_equal(['bar '], b:text)
+ exe "normal! \<Esc>"
+
+ normal! v0
+ call setbufvar('%', '&list', v:false)
+ call assert_equal(['foo bar '], b:text)
+ exe "normal! \<Esc>"
+ ]])
+ expected_empty()
+end)
+
-- oldtest: Test_autocmd_invalidates_undo_on_textchanged()
it('no E440 in quickfix window when autocommand invalidates undo', function()
write_file(
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
@@ -3955,6 +3955,17 @@ stack traceback:
]]
)
end)
+
+ it('can get Visual selection in current buffer #34162', function()
+ insert('foo bar baz')
+ feed('gg0fbvtb')
+ local text = exec_lua([[
+ return vim.api.nvim_buf_call(0, function()
+ return vim.fn.getregion(vim.fn.getpos('.'), vim.fn.getpos('v'))
+ end)
+ ]])
+ eq({ 'bar ' }, text)
+ end)
end)
describe('vim.api.nvim_win_call', function()
diff --git a/test/old/testdir/test_autocmd.vim b/test/old/testdir/test_autocmd.vim
@@ -3598,6 +3598,28 @@ func Test_Visual_doautoall_redraw()
%bwipe!
endfunc
+func Test_get_Visual_selection_in_curbuf_autocmd()
+ throw 'Skipped: use test/functional/legacy/autocmd_spec.lua'
+ call test_override('starting', 1)
+ new
+ autocmd OptionSet list let b:text = getregion(getpos('.'), getpos('v'))
+ call setline(1, 'foo bar baz')
+
+ normal! gg0fbvtb
+ setlocal list
+ call assert_equal(['bar '], b:text)
+ exe "normal! \<Esc>"
+
+ normal! v0
+ call setbufvar('%', '&list', v:false)
+ call assert_equal(['foo bar '], b:text)
+ exe "normal! \<Esc>"
+
+ autocmd! OptionSet list
+ bwipe!
+ call test_override('starting', 0)
+endfunc
+
" This was using freed memory.
func Test_BufNew_arglocal()
arglocal