set noshowmode
set virtualedit=all
set noruler
" getregionpos
nnoremap gp :echom "== getpos() results == " . string(getpos('.'))<CR>
function! ReportGetRegionPos()
let l:options = { 'type': mode(), 'eol': 1 }
let l:pos = getregionpos(getpos('v'), getpos('.'), options)
echom "== getregionpos() results == " . string(l:pos)
endfunction
augroup ReportGetRegionPos
autocmd!
autocmd ModeChanged *:[vV\x16] if &operatorfunc ==# '' |
\ call ReportGetRegionPos() |
\ endif
autocmd CursorMoved * if mode() ==# 'v' || mode() ==# 'V' || mode() ==# "\<C-V>" |
\ call ReportGetRegionPos() |
\ endif
augroup END
$ echo "Lorem ipsum dolor sit amet, consectetur adipiscing elit." > test.txt
Navigate to the end of the line using virtual edit. Stay in this position for the rest of the steps.
activate getpos('.') and check result.
activate getpos('.') and check result. The second time, they will still be the same.
Enter visual mode (activating getregionpos()), check the result. It should still be the same as the two activations of getpos('.').
Exit visual mode and activate getpos again. This result should be different, exactly one less column than before.
Enter visual mode again, thereby activating getregionpos again. The result should be the same as the last result of getpos, one less than the original value. We see that, in this case, getregionpos is accurately reflecting this change in getpos.
https://github.com/user-attachments/assets/b095964e-838a-4dbd-8049-b9a650fc687c
The expected behavior is that getpos() will consistently report the position the user is in.
VIM - Vi IMproved 9.1 (2024 Jan 02, compiled Nov 15 2024 03:05:17) Included patches: 1-866 Compiled by Arch Linux
OS: Arch Linux
Kernel: Linux 6.12.4-arch1-1
Terminal: Wezterm
$TERM: wezterm
shell: zsh 5.9 (x86_64-pc-linux-gnu)
No response
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
This is unrelated to getregionpos(). The same happens without the autocommands.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
Hmm, the bug doesn't happen if 'virtualedit' contains both all and onemore. It seems that onemore disables some cursor adjustments that are unaffected by all, but the help for 'virtualedit' says:
It doesn't make sense to combine "all" with "onemore", but you will
not get a warning for it.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
I've found some time and energy to work on this.
The issue comes from adjust_cursor_eol() in src/ops.c, particularly this conditional:
unsigned int cur_ve_flags = get_ve_flags(); int adj_cursor = (curwin->w_cursor.col > 0 && gchar_cursor() == NUL && (cur_ve_flags & VE_ONEMORE) == 0 && !(restart_edit || (State & MODE_INSERT))); if (!adj_cursor) return;
adjust_cursor_eol() seems intended to fix the cursor when it sits past the end of the line by moving it back onto the last real (printable?) character. Applying the cursor position change under the VE_ALL condition causes the cursor’s internal position to change even though the cursor hasn’t moved. So, we then see output from getpos('.') where, in certain situations, the cursor doens't go anywhere but its internal position is encoded differently. This change is not applied in the VE_ONEMORE case, so including onemore prevents it from happening.
With virtualedit=all, we expect that the cursor can sit in the virtual space past the end of the line and that this position will not simply change across mode changes. I think that skipping the adjustment when VE_ALL is set gives us the behavior that users (at least me) expect out of virtualedit=all.
With the following change, the errant behavior disappears:
unsigned int cur_ve_flags = get_ve_flags();
int adj_cursor = (curwin->w_cursor.col > 0
&& gchar_cursor() == NUL
&& (cur_ve_flags & VE_ONEMORE) == 0
+ && (cur_ve_flags & VE_ALL) == 0
&& !(restart_edit || (State & MODE_INSERT)));
if (!adj_cursor)
return; To test to make sure that this didn't break anything, I tried to find and run all of the relevant tests:
cd src/testdir rg -l "virtualedit|VE_ALL|VE_ONEMORE|coladd|adjust_cursor_eol" . \ | sed -n 's#^\./\(test_[^/]*\)\.vim$#\1.res#p' \ | sort -u \ | xargs make
Important
The comments associated with the virtualedit options enum found in src/option.h indicate that both VE_BLOCK and VE_INSERT "include 'all'". I haven't done anything to assess whether these options should be accounted for in the conditional that I changed. The only checking I've done that may be related is just running the tests.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()