From e53accf8ec5a2cb4522af8fe477acebea5c0ce1b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 28 Dec 2025 07:01:10 +0800 Subject: [PATCH] vim-patch:9.1.2019: inconsistent cursor encoding past EOL with ve=all MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: When virtualedit is set to all, the cursor is supposed to be permitted to reside anywhere, including on the virtual space beyond the end of the buffer's text. Switching modes triggered a routine that "fixed" a cursor that was past the end of the line by shifting it back to the last actual character in the line and compensating with a virtual column offset. While visually identical, this re-encoding changed the underlying byte index, causing position-reporting functions to return inconsistent values after a mode change. Solution: Skip this coordinate adjustment when virtual editing is fully enabled. By treating the line terminator as a valid, stable position, the cursor’s internal representation remains unchanged when entering or exiting Visual mode, ensuring consistent coordinate reporting. Add a regression test to check this functionality. (McAuley Penney) fixes: vim/vim#16276 closes: vim/vim#19009 https://github.com/vim/vim/commit/491f0fa4574207b311f399a5a454033c79772872 Co-authored-by: McAuley Penney --- src/nvim/ops.c | 1 + test/old/testdir/test_virtualedit.vim | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 5abccd7a47..c32935f49e 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -1793,6 +1793,7 @@ void adjust_cursor_eol(void) const bool adj_cursor = (curwin->w_cursor.col > 0 && gchar_cursor() == NUL && (cur_ve_flags & kOptVeFlagOnemore) == 0 + && (cur_ve_flags & kOptVeFlagAll) == 0 && !(restart_edit || (State & MODE_INSERT))); if (!adj_cursor) { return; diff --git a/test/old/testdir/test_virtualedit.vim b/test/old/testdir/test_virtualedit.vim index def96ca64f..7f54d750e9 100644 --- a/test/old/testdir/test_virtualedit.vim +++ b/test/old/testdir/test_virtualedit.vim @@ -732,4 +732,24 @@ func Test_virtualedit_set_cursor_pos_maxcol() bwipe! endfunc +" Verify that getpos() remains consistent when the cursor is past EOL after toggling Visual mode with virtualedit=all. +func Test_virtualedit_getpos_stable_past_eol_after_visual() + new + set virtualedit=all + call setline(1, 'abc') + + normal! gg$3l + let p1 = getpos('.') + + normal! v + redraw + normal! \ + + let p2 = getpos('.') + call assert_equal(p1, p2, 'Position should not be re-encoded after leaving Visual mode') + + set virtualedit& + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab