patch 9.1.0430: getregionpos() doesn't handle one char selection Commit: https://github.com/vim/vim/commit/52a6f348874778cf315b47d9e8b5f818f4b97277 Author: zeertzjq <zeert...@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 <zeert...@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, /**/ -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/vim_dev/E1s9nDO-000OjE-9G%40256bit.org.