Commit: patch 9.1.0430: getregionpos() doesn't handle one char selection

1 view
Skip to first unread message

Christian Brabandt

unread,
May 22, 2024, 10:45:22 AMMay 22
to vim...@googlegroups.com
patch 9.1.0430: getregionpos() doesn't handle one char selection

Commit: https://github.com/vim/vim/commit/52a6f348874778cf315b47d9e8b5f818f4b97277
Author: zeertzjq <zeer...@outlook.com>
Date: Wed May 22 16:42:44 2024 +0200

patch 9.1.0430: getregionpos() doesn't handle one char selection

Problem: getregionpos() doesn't handle one char selection.
Solution: Handle startspaces differently when is_oneChar is set.
Also add a test for an exclusive charwise selection with
multibyte chars (zeertzjq)

closes: #14825

Signed-off-by: zeertzjq <zeer...@outlook.com>
Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index b9dd4d20b..4177a0181 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -1,4 +1,4 @@
-*builtin.txt* For Vim version 9.1. Last change: 2024 May 20
+*builtin.txt* For Vim version 9.1. Last change: 2024 May 22


VIM REFERENCE MANUAL by Bram Moolenaar
@@ -4345,8 +4345,8 @@ getregionpos({pos1}, {pos2} [, {opts}]) *getregionpos()*
the offset in screen columns from the start of the character.
E.g., a position within a <Tab> or after the last character.
If the "off" number of an ending position is non-zero, it is
- the character's number of cells included in the selection,
- otherwise the whole character is included.
+ the offset of the character's first cell not included in the
+ selection, otherwise all its cells are included.

Can also be used as a |method|: >
getpos('.')->getregionpos(getpos("'a"))
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 903205ad3..b65df5dd9 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -5793,7 +5793,6 @@ f_getregionpos(typval_T *argvars, typval_T *rettv)

for (lnum = p1.lnum; lnum <= p2.lnum; lnum++)
{
- struct block_def bd;
pos_T ret_p1, ret_p2;

if (region_type == MLINE)
@@ -5805,11 +5804,28 @@ f_getregionpos(typval_T *argvars, typval_T *rettv)
}
else
{
+ struct block_def bd;
+
if (region_type == MBLOCK)
block_prep(&oa, &bd, lnum, FALSE);
else
charwise_block_prep(p1, p2, &bd, lnum, inclusive);
- if (bd.startspaces > 0)
+
+ if (bd.is_oneChar) // selection entirely inside one char
+ {
+ if (region_type == MBLOCK)
+ {
+ ret_p1.col = bd.textcol;
+ ret_p1.coladd = bd.start_char_vcols
+ - (bd.start_vcol - oa.start_vcol);
+ }
+ else
+ {
+ ret_p1.col = p1.col + 1;
+ ret_p1.coladd = p1.coladd;
+ }
+ }
+ else if (bd.startspaces > 0)
{
ret_p1.col = bd.textcol;
ret_p1.coladd = bd.start_char_vcols - bd.startspaces;
@@ -5819,7 +5835,13 @@ f_getregionpos(typval_T *argvars, typval_T *rettv)
ret_p1.col = bd.textcol + 1;
ret_p1.coladd = 0;
}
- if (bd.endspaces > 0)
+
+ if (bd.is_oneChar) // selection entirely inside one char
+ {
+ ret_p2.col = ret_p1.col;
+ ret_p2.coladd = ret_p1.coladd + bd.startspaces;
+ }
+ else if (bd.endspaces > 0)
{
ret_p2.col = bd.textcol + bd.textlen + 1;
ret_p2.coladd = bd.endspaces;
diff --git a/src/ops.c b/src/ops.c
index 605a66494..1dd36ab28 100644
--- a/src/ops.c
+++ b/src/ops.c
@@ -2444,13 +2444,13 @@ charwise_block_prep(
int inclusive)
{
colnr_T startcol = 0, endcol = MAXCOL;
- int is_oneChar = FALSE;
colnr_T cs, ce;
char_u *p;

p = ml_get(lnum);
bdp->startspaces = 0;
bdp->endspaces = 0;
+ bdp->is_oneChar = FALSE;
bdp->start_char_vcols = 0;

if (lnum == start.lnum)
@@ -2487,7 +2487,7 @@ charwise_block_prep(
if (start.lnum == end.lnum && start.col == end.col)
{
// Special case: inside a single char
- is_oneChar = TRUE;
+ bdp->is_oneChar = TRUE;
bdp->startspaces = end.coladd - start.coladd + inclusive;
endcol = startcol;
}
@@ -2501,7 +2501,7 @@ charwise_block_prep(
}
if (endcol == MAXCOL)
endcol = ml_get_len(lnum);
- if (startcol > endcol || is_oneChar)
+ if (startcol > endcol || bdp->is_oneChar)
bdp->textlen = 0;
else
bdp->textlen = endcol - startcol + inclusive;
diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim
index 8c850d1ac..621be298d 100644
--- a/src/testdir/test_visual.vim
+++ b/src/testdir/test_visual.vim
@@ -1889,7 +1889,7 @@ func Test_visual_getregion()
\ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
call assert_equal([
\ [[bufnr('%'), 1, 5, 0], [bufnr('%'), 1, 5, 0]],
- \ [[bufnr('%'), 2, 10, 1], [bufnr('%'), 2, 10, 0]],
+ \ [[bufnr('%'), 2, 10, 1], [bufnr('%'), 2, 10, 2]],
\ [[bufnr('%'), 3, 5, 0], [bufnr('%'), 3, 5, 0]],
\ ],
\ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
@@ -1900,6 +1900,7 @@ func Test_visual_getregion()
\ ],
\ getregionpos(getpos('v'), getpos('.'), {'type': 'v' }))

+ #" characterwise selection with multibyte chars
call cursor(1, 1)
call feedkeys("\<Esc>vj", 'xt')
call assert_equal(['abcdefghijk«', "\U0001f1e6"],
@@ -1910,8 +1911,17 @@ func Test_visual_getregion()
\ ],
\ getregionpos(getpos('v'), getpos('.'), {'type': 'v' }))

+ set selection=exclusive
+ call feedkeys('l', 'xt')
+ call assert_equal(['abcdefghijk«', "\U0001f1e6"],
+ \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+ call assert_equal([
+ \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 13, 0]],
+ \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 4, 0]],
+ \ ],
+ \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' }))
+
#" marks on multibyte chars
- :set selection=exclusive
call setpos("'a", [0, 1, 11, 0])
call setpos("'b", [0, 2, 16, 0])
call setpos("'c", [0, 2, 0, 0])
@@ -1997,6 +2007,7 @@ func Test_visual_getregion()
call assert_equal(["c", "x z"],
\ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
set selection&
+ bwipe!

#" Exclusive selection 2
new
@@ -2033,7 +2044,24 @@ func Test_visual_getregion()
set virtualedit=all

call cursor(1, 1)
- call feedkeys("\<Esc>2lv2lj", 'xt')
+ call feedkeys("\<Esc>lv2l", 'xt')
+ call assert_equal([' '],
+ \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+ call assert_equal([
+ \ [[bufnr('%'), 1, 2, 0], [bufnr('%'), 1, 2, 2]],
+ \ ],
+ \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' }))
+
+ call cursor(1, 1)
+ call feedkeys("\<Esc>2lv2l", 'xt')
+ call assert_equal([' '],
+ \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+ call assert_equal([
+ \ [[bufnr('%'), 1, 2, 1], [bufnr('%'), 1, 2, 3]],
+ \ ],
+ \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' }))
+
+ call feedkeys('j', 'xt')
call assert_equal([' c', 'x '],
\ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
call assert_equal([
@@ -2042,13 +2070,34 @@ func Test_visual_getregion()
\ ],
\ getregionpos(getpos('v'), getpos('.'), {'type': 'v' }))

+ call cursor(1, 1)
+ call feedkeys("\<Esc>6l\<C-v>2lj", 'xt')
+ call assert_equal([' ', ' '],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+ call assert_equal([
+ \ [[bufnr('%'), 1, 2, 5], [bufnr('%'), 1, 2, 7]],
+ \ [[bufnr('%'), 2, 2, 5], [bufnr('%'), 2, 2, 7]],
+ \ ],
+ \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+
+ call cursor(1, 1)
+ call feedkeys("\<Esc>l\<C-v>2l2j", 'xt')
+ call assert_equal([' ', ' ', ' '],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+ call assert_equal([
+ \ [[bufnr('%'), 1, 2, 0], [bufnr('%'), 1, 2, 2]],
+ \ [[bufnr('%'), 2, 2, 0], [bufnr('%'), 2, 2, 2]],
+ \ [[bufnr('%'), 3, 0, 0], [bufnr('%'), 3, 0, 2]],
+ \ ],
+ \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+
call cursor(1, 1)
call feedkeys("\<Esc>2l\<C-v>2l2j", 'xt')
call assert_equal([' ', ' ', ' '],
\ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
call assert_equal([
- \ [[bufnr('%'), 1, 2, 5], [bufnr('%'), 1, 2, 0]],
- \ [[bufnr('%'), 2, 2, 5], [bufnr('%'), 2, 2, 0]],
+ \ [[bufnr('%'), 1, 2, 1], [bufnr('%'), 1, 2, 3]],
+ \ [[bufnr('%'), 2, 2, 1], [bufnr('%'), 2, 2, 3]],
\ [[bufnr('%'), 3, 0, 0], [bufnr('%'), 3, 0, 2]],
\ ],
\ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
diff --git a/src/version.c b/src/version.c
index b2f04169f..28dad4526 100644
--- a/src/version.c
+++ b/src/version.c
@@ -704,6 +704,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 430,
/**/
429,
/**/
Reply all
Reply to author
Forward
0 new messages