mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:9.1.0430: getregionpos() doesn't handle one char selection (#28924)
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: vim/vim#14825
52a6f34887
This commit is contained in:
parent
3d43bdc81e
commit
5cbd6d9b9f
4
runtime/doc/builtin.txt
generated
4
runtime/doc/builtin.txt
generated
@ -2985,8 +2985,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.
|
||||||
|
|
||||||
getregtype([{regname}]) *getregtype()*
|
getregtype([{regname}]) *getregtype()*
|
||||||
The result is a String, which is type of register {regname}.
|
The result is a String, which is type of register {regname}.
|
||||||
|
4
runtime/lua/vim/_meta/vimfn.lua
generated
4
runtime/lua/vim/_meta/vimfn.lua
generated
@ -3596,8 +3596,8 @@ function vim.fn.getregion(pos1, pos2, opts) end
|
|||||||
--- 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.
|
||||||
---
|
---
|
||||||
--- @param pos1 table
|
--- @param pos1 table
|
||||||
--- @param pos2 table
|
--- @param pos2 table
|
||||||
|
@ -4433,8 +4433,8 @@ M.funcs = {
|
|||||||
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.
|
||||||
]=],
|
]=],
|
||||||
name = 'getregionpos',
|
name = 'getregionpos',
|
||||||
params = { { 'pos1', 'table' }, { 'pos2', 'table' }, { 'opts', 'table' } },
|
params = { { 'pos1', 'table' }, { 'pos2', 'table' }, { 'opts', 'table' } },
|
||||||
|
@ -3041,7 +3041,6 @@ static void f_getregionpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (linenr_T lnum = p1.lnum; lnum <= p2.lnum; lnum++) {
|
for (linenr_T 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 == kMTLineWise) {
|
if (region_type == kMTLineWise) {
|
||||||
@ -3050,19 +3049,34 @@ static void f_getregionpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr
|
|||||||
ret_p2.col = MAXCOL;
|
ret_p2.col = MAXCOL;
|
||||||
ret_p2.coladd = 0;
|
ret_p2.coladd = 0;
|
||||||
} else {
|
} else {
|
||||||
|
struct block_def bd;
|
||||||
|
|
||||||
if (region_type == kMTBlockWise) {
|
if (region_type == kMTBlockWise) {
|
||||||
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 == kMTBlockWise) {
|
||||||
|
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;
|
||||||
} else {
|
} else {
|
||||||
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;
|
||||||
} else {
|
} else {
|
||||||
|
@ -4253,11 +4253,12 @@ void charwise_block_prep(pos_T start, pos_T end, struct block_def *bdp, linenr_T
|
|||||||
{
|
{
|
||||||
colnr_T startcol = 0;
|
colnr_T startcol = 0;
|
||||||
colnr_T endcol = MAXCOL;
|
colnr_T endcol = MAXCOL;
|
||||||
bool is_oneChar = false;
|
|
||||||
colnr_T cs, ce;
|
colnr_T cs, ce;
|
||||||
char *p = ml_get(lnum);
|
char *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) {
|
||||||
@ -4287,7 +4288,7 @@ void charwise_block_prep(pos_T start, pos_T end, struct block_def *bdp, linenr_T
|
|||||||
&& utf_head_off(p, p + endcol) == 0)) {
|
&& utf_head_off(p, p + endcol) == 0)) {
|
||||||
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;
|
||||||
} else {
|
} else {
|
||||||
@ -4300,7 +4301,7 @@ void charwise_block_prep(pos_T start, pos_T end, struct block_def *bdp, linenr_T
|
|||||||
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;
|
||||||
|
@ -1893,7 +1893,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>" }))
|
||||||
@ -1904,6 +1904,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"],
|
||||||
@ -1914,8 +1915,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])
|
||||||
@ -2001,6 +2011,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
|
||||||
@ -2037,7 +2048,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([
|
||||||
@ -2046,13 +2074,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>" }))
|
||||||
|
Loading…
Reference in New Issue
Block a user