From d1ca5519834cfa2eb25ba48c62e5b5d21905e10f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 26 May 2025 06:51:15 +0800 Subject: [PATCH] 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 (cherry picked from commit bd01bd6564790d977095447ae70082c97fbbd480) --- src/nvim/autocmd.c | 9 ++++++--- test/functional/legacy/autocmd_spec.lua | 24 ++++++++++++++++++++++++ test/functional/lua/vim_spec.lua | 11 +++++++++++ test/old/testdir/test_autocmd.vim | 22 ++++++++++++++++++++++ 4 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index 53cd861a9c..189e9d558b 100644 --- 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 index 1071776b68..3a40ca4df8 100644 --- 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! \" + + normal! v0 + call setbufvar('%', '&list', v:false) + call assert_equal(['foo bar '], b:text) + exe "normal! \" + ]]) + 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 index cbd571439d..524974adc7 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -3930,6 +3930,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 index a35049d468..c25f2e5814 100644 --- a/test/old/testdir/test_autocmd.vim +++ b/test/old/testdir/test_autocmd.vim @@ -3458,6 +3458,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! \" + + normal! v0 + call setbufvar('%', '&list', v:false) + call assert_equal(['foo bar '], b:text) + exe "normal! \" + + autocmd! OptionSet list + bwipe! + call test_override('starting', 0) +endfunc + " This was using freed memory. func Test_BufNew_arglocal() arglocal