For a reversed Visual selection, getpos("'<") reports the buffer-relative start while setpos("'<", ...) updates the endpoint associated with the selection direction. setcharpos() follows the same path, so the get/set APIs are inconsistent. Fixes #19049.
Resolve '< and '> to the logical buffer-relative endpoints before updating them. When a new endpoint crosses the other, clamp the range; when one endpoint is deleted, preserve the remaining endpoint so the range can be recreated. Update builtin.txt and add regression coverage for forward and reverse selections, crossing, deletion and recreation, independent initialization, and setcharpos().
make -C srcmake -C src/testdir -W test_marks.vim -W test_visual.vim -W test_codestyle.vim test_marks.res test_visual.res test_codestyle.resgit diff --checkFocused test counts: test_marks 14/14, test_visual 81/81, test_codestyle 5/5.
AI-assisted: Codex
https://github.com/vim/vim/pull/21023
(3 files)
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.![]()
Thanks, but that visual marks are clamped is not correct I think. Take the following test:
diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim index beea4c431..f2e7a1489 100644 --- a/src/testdir/test_visual.vim +++ b/src/testdir/test_visual.vim @@ -3065,4 +3065,14 @@ func Test_visual_ended_in_unloaded_buffer() %bw! endfunc +func Test_visual_clamp() + new + call setline(1, ['one', 'two', 'three']) + normal! 2GVjy + call setpos("'>", [0, 1, 1, 0]) + '<,'>d + call assert_equal(['three'], getline(1,'$')) + bw! +endfunc + " vim: shiftwidth=2 sts=2 expandtab
clamping here means after setting the '> mark both visual marks point to line 1 and we suddenly lost the original visual selection, which means we are deleting an unexpected range. That is too much surprising and I think we should not do this.
Is there a reason we need to do the clamping on setting the mark? I believe we don't need to do it and leave it to getmark() to return the marks in the correct order.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.![]()
You're right. Your example exposed a bug in the clamping logic: moving '> before '< discarded the previous endpoint. I removed the clamping. setpos() now resolves the requested logical mark and updates only that endpoint, while getmark() handles the ordering.
I added your linewise case and the inverse crossing case; both now preserve the full range.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.![]()
I found an existing compatibility constraint while testing the revised approach. Consider a reversed stored selection with endpoints 7,1:
setpos("\x27<", 2) followed by setpos("\x27>", 8) would ideally produce logical range 2..8.setpos("\x27<", 8), then setpos("\x27>", 10)) must produce 8..10.After the first call, both cases are reversed stored endpoints followed by setting \x27> beyond the high endpoint. Without tracking call history, choosing the logical endpoint preserves the first case but breaks the existing pair-replacement behavior; choosing the stored endpoint does the reverse.
Which behavior should take precedence when a call crosses the old range? I can keep this fix limited to non-crossing updates (the original report), or make logical endpoint naming take precedence across crossings.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.![]()