1
0
forked from aniani/vim

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 <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
zeertzjq
2024-05-22 16:42:44 +02:00
committed by Christian Brabandt
parent 95ff39f8e3
commit 52a6f34887
5 changed files with 87 additions and 14 deletions

View File

@@ -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 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. the offset in screen columns from the start of the character.
E.g., a position within a <Tab> or after the last 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 If the "off" number of an ending position is non-zero, it is
the character's number of cells included in the selection, the offset of the character's first cell not included in the
otherwise the whole character is included. selection, otherwise all its cells are included.
Can also be used as a |method|: > Can also be used as a |method|: >
getpos('.')->getregionpos(getpos("'a")) getpos('.')->getregionpos(getpos("'a"))

View File

@@ -5793,7 +5793,6 @@ f_getregionpos(typval_T *argvars, typval_T *rettv)
for (lnum = p1.lnum; lnum <= p2.lnum; lnum++) for (lnum = p1.lnum; lnum <= p2.lnum; lnum++)
{ {
struct block_def bd;
pos_T ret_p1, ret_p2; pos_T ret_p1, ret_p2;
if (region_type == MLINE) if (region_type == MLINE)
@@ -5805,11 +5804,28 @@ f_getregionpos(typval_T *argvars, typval_T *rettv)
} }
else else
{ {
struct block_def bd;
if (region_type == MBLOCK) if (region_type == MBLOCK)
block_prep(&oa, &bd, lnum, FALSE); block_prep(&oa, &bd, lnum, FALSE);
else else
charwise_block_prep(p1, p2, &bd, lnum, inclusive); 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.col = bd.textcol;
ret_p1.coladd = bd.start_char_vcols - bd.startspaces; 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.col = bd.textcol + 1;
ret_p1.coladd = 0; 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.col = bd.textcol + bd.textlen + 1;
ret_p2.coladd = bd.endspaces; ret_p2.coladd = bd.endspaces;

View File

@@ -2444,13 +2444,13 @@ charwise_block_prep(
int inclusive) int inclusive)
{ {
colnr_T startcol = 0, endcol = MAXCOL; colnr_T startcol = 0, endcol = MAXCOL;
int is_oneChar = FALSE;
colnr_T cs, ce; colnr_T cs, ce;
char_u *p; char_u *p;
p = ml_get(lnum); p = ml_get(lnum);
bdp->startspaces = 0; bdp->startspaces = 0;
bdp->endspaces = 0; bdp->endspaces = 0;
bdp->is_oneChar = FALSE;
bdp->start_char_vcols = 0; bdp->start_char_vcols = 0;
if (lnum == start.lnum) if (lnum == start.lnum)
@@ -2487,7 +2487,7 @@ charwise_block_prep(
if (start.lnum == end.lnum && start.col == end.col) if (start.lnum == end.lnum && start.col == end.col)
{ {
// Special case: inside a single char // Special case: inside a single char
is_oneChar = TRUE; bdp->is_oneChar = TRUE;
bdp->startspaces = end.coladd - start.coladd + inclusive; bdp->startspaces = end.coladd - start.coladd + inclusive;
endcol = startcol; endcol = startcol;
} }
@@ -2501,7 +2501,7 @@ charwise_block_prep(
} }
if (endcol == MAXCOL) if (endcol == MAXCOL)
endcol = ml_get_len(lnum); endcol = ml_get_len(lnum);
if (startcol > endcol || is_oneChar) if (startcol > endcol || bdp->is_oneChar)
bdp->textlen = 0; bdp->textlen = 0;
else else
bdp->textlen = endcol - startcol + inclusive; bdp->textlen = endcol - startcol + inclusive;

View File

@@ -1889,7 +1889,7 @@ func Test_visual_getregion()
\ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
call assert_equal([ call assert_equal([
\ [[bufnr('%'), 1, 5, 0], [bufnr('%'), 1, 5, 0]], \ [[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]], \ [[bufnr('%'), 3, 5, 0], [bufnr('%'), 3, 5, 0]],
\ ], \ ],
\ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" })) \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
@@ -1900,6 +1900,7 @@ func Test_visual_getregion()
\ ], \ ],
\ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' }))
#" characterwise selection with multibyte chars
call cursor(1, 1) call cursor(1, 1)
call feedkeys("\<Esc>vj", 'xt') call feedkeys("\<Esc>vj", 'xt')
call assert_equal(['abcdefghijk«', "\U0001f1e6"], call assert_equal(['abcdefghijk«', "\U0001f1e6"],
@@ -1910,8 +1911,17 @@ func Test_visual_getregion()
\ ], \ ],
\ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) \ 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 #" marks on multibyte chars
:set selection=exclusive
call setpos("'a", [0, 1, 11, 0]) call setpos("'a", [0, 1, 11, 0])
call setpos("'b", [0, 2, 16, 0]) call setpos("'b", [0, 2, 16, 0])
call setpos("'c", [0, 2, 0, 0]) call setpos("'c", [0, 2, 0, 0])
@@ -1997,6 +2007,7 @@ func Test_visual_getregion()
call assert_equal(["c", "x\tz"], call assert_equal(["c", "x\tz"],
\ getregion(getpos('v'), getpos('.'), {'type': 'v' })) \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
set selection& set selection&
bwipe!
#" Exclusive selection 2 #" Exclusive selection 2
new new
@@ -2033,7 +2044,24 @@ func Test_visual_getregion()
set virtualedit=all set virtualedit=all
call cursor(1, 1) 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 '], call assert_equal([' c', 'x '],
\ getregion(getpos('v'), getpos('.'), {'type': 'v' })) \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
call assert_equal([ call assert_equal([
@@ -2042,13 +2070,34 @@ func Test_visual_getregion()
\ ], \ ],
\ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) \ 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 cursor(1, 1)
call feedkeys("\<Esc>2l\<C-v>2l2j", 'xt') call feedkeys("\<Esc>2l\<C-v>2l2j", 'xt')
call assert_equal([' ', ' ', ' '], call assert_equal([' ', ' ', ' '],
\ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
call assert_equal([ call assert_equal([
\ [[bufnr('%'), 1, 2, 5], [bufnr('%'), 1, 2, 0]], \ [[bufnr('%'), 1, 2, 1], [bufnr('%'), 1, 2, 3]],
\ [[bufnr('%'), 2, 2, 5], [bufnr('%'), 2, 2, 0]], \ [[bufnr('%'), 2, 2, 1], [bufnr('%'), 2, 2, 3]],
\ [[bufnr('%'), 3, 0, 0], [bufnr('%'), 3, 0, 2]], \ [[bufnr('%'), 3, 0, 0], [bufnr('%'), 3, 0, 2]],
\ ], \ ],
\ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" })) \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" }))

View File

@@ -704,6 +704,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
430,
/**/ /**/
429, 429,
/**/ /**/