aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/builtin.txt4
-rw-r--r--runtime/lua/vim/_meta/vimfn.lua4
-rw-r--r--src/nvim/eval.lua4
-rw-r--r--src/nvim/eval/funcs.c20
-rw-r--r--src/nvim/ops.c7
-rw-r--r--test/old/testdir/test_visual.vim59
6 files changed, 81 insertions, 17 deletions
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index e0921cf477..2c1c6675c1 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -2985,8 +2985,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.
getregtype([{regname}]) *getregtype()*
The result is a String, which is type of register {regname}.
diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua
index dee65a40c7..e00b2e6acd 100644
--- a/runtime/lua/vim/_meta/vimfn.lua
+++ b/runtime/lua/vim/_meta/vimfn.lua
@@ -3596,8 +3596,8 @@ function vim.fn.getregion(pos1, pos2, opts) end
--- 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.
---
--- @param pos1 table
--- @param pos2 table
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index 58f2ac0acf..b377643917 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -4433,8 +4433,8 @@ M.funcs = {
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.
]=],
name = 'getregionpos',
params = { { 'pos1', 'table' }, { 'pos2', 'table' }, { 'opts', 'table' } },
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 1d01f3ad98..7453bbb601 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -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++) {
- struct block_def bd;
pos_T ret_p1, ret_p2;
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.coladd = 0;
} else {
+ struct block_def bd;
+
if (region_type == kMTBlockWise) {
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 == 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.coladd = bd.start_char_vcols - bd.startspaces;
} else {
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;
} else {
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 707cf5ca9a..5c1e291ac6 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -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 endcol = MAXCOL;
- bool is_oneChar = false;
colnr_T cs, ce;
char *p = ml_get(lnum);
+
bdp->startspaces = 0;
bdp->endspaces = 0;
+ bdp->is_oneChar = false;
bdp->start_char_vcols = 0;
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)) {
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;
} else {
@@ -4300,7 +4301,7 @@ void charwise_block_prep(pos_T start, pos_T end, struct block_def *bdp, linenr_T
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/test/old/testdir/test_visual.vim b/test/old/testdir/test_visual.vim
index fa82531170..a682455227 100644
--- a/test/old/testdir/test_visual.vim
+++ b/test/old/testdir/test_visual.vim
@@ -1893,7 +1893,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>" }))
@@ -1904,6 +1904,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"],
@@ -1914,8 +1915,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])
@@ -2001,6 +2011,7 @@ func Test_visual_getregion()
call assert_equal(["c", "x\tz"],
\ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
set selection&
+ bwipe!
#" Exclusive selection 2
new
@@ -2037,7 +2048,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([
@@ -2047,12 +2075,33 @@ 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>" }))