aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/builtin.txt13
-rw-r--r--runtime/lua/vim/_meta/vimfn.lua14
-rw-r--r--src/nvim/eval.lua17
-rw-r--r--src/nvim/eval/funcs.c27
-rw-r--r--test/old/testdir/test_cursor_func.vim19
-rw-r--r--test/old/testdir/test_functions.vim22
6 files changed, 92 insertions, 20 deletions
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 94e9223ee9..9a662761c4 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -8399,7 +8399,7 @@ values({dict}) *values()*
in arbitrary order. Also see |items()| and |keys()|.
Returns zero if {dict} is not a |Dict|.
-virtcol({expr} [, {list}]) *virtcol()*
+virtcol({expr} [, {list} [, {winid}]]) *virtcol()*
The result is a Number, which is the screen column of the file
position given with {expr}. That is, the last screen position
occupied by the character at that position, when the screen
@@ -8431,10 +8431,13 @@ virtcol({expr} [, {list}]) *virtcol()*
returns the cursor position. Differs from |'<| in
that it's updated right away.
- If {list} is present and non-zero then virtcol() returns a List
- with the first and last screen position occupied by the
+ If {list} is present and non-zero then virtcol() returns a
+ List with the first and last screen position occupied by the
character.
+ With the optional {winid} argument the values are obtained for
+ that window instead of the current window.
+
Note that only marks in the current file can be used.
Examples: >vim
" With text "foo^Lbar" and cursor on the "^L":
@@ -8446,8 +8449,8 @@ virtcol({expr} [, {list}]) *virtcol()*
" With text " there", with 't at 'h':
echo virtcol("'t") " returns 6
-< Techo he first column is 1. 0 is returned for an error.
- A echo more advanced example that echoes the maximum length of
+< The first column is 1. 0 or [0, 0] is returned for an error.
+ A more advanced example that echoes the maximum length of
all lines: >vim
echo max(map(range(1, line('$')), "virtcol([v:val, '$'])"))
diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua
index ce325ce1f8..8ae6dd5f10 100644
--- a/runtime/lua/vim/_meta/vimfn.lua
+++ b/runtime/lua/vim/_meta/vimfn.lua
@@ -10013,10 +10013,13 @@ function vim.fn.values(dict) end
--- returns the cursor position. Differs from |'<| in
--- that it's updated right away.
---
---- If {list} is present and non-zero then virtcol() returns a List
---- with the first and last screen position occupied by the
+--- If {list} is present and non-zero then virtcol() returns a
+--- List with the first and last screen position occupied by the
--- character.
---
+--- With the optional {winid} argument the values are obtained for
+--- that window instead of the current window.
+---
--- Note that only marks in the current file can be used.
--- Examples: >vim
--- " With text "foo^Lbar" and cursor on the "^L":
@@ -10028,15 +10031,16 @@ function vim.fn.values(dict) end
--- " With text " there", with 't at 'h':
---
--- echo virtcol("'t") " returns 6
---- <Techo he first column is 1. 0 is returned for an error.
---- A echo more advanced example that echoes the maximum length of
+--- <The first column is 1. 0 or [0, 0] is returned for an error.
+--- A more advanced example that echoes the maximum length of
--- all lines: >vim
--- echo max(map(range(1, line('$')), "virtcol([v:val, '$'])"))
---
--- @param expr any
--- @param list? any
+--- @param winid? integer
--- @return any
-function vim.fn.virtcol(expr, list) end
+function vim.fn.virtcol(expr, list, winid) end
--- The result is a Number, which is the byte index of the
--- character in window {winid} at buffer line {lnum} and virtual
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index e019e8fcab..2b89d34a6d 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -11893,7 +11893,7 @@ M.funcs = {
signature = 'values({dict})',
},
virtcol = {
- args = { 1, 2 },
+ args = { 1, 3 },
base = 1,
desc = [=[
The result is a Number, which is the screen column of the file
@@ -11927,10 +11927,13 @@ M.funcs = {
returns the cursor position. Differs from |'<| in
that it's updated right away.
- If {list} is present and non-zero then virtcol() returns a List
- with the first and last screen position occupied by the
+ If {list} is present and non-zero then virtcol() returns a
+ List with the first and last screen position occupied by the
character.
+ With the optional {winid} argument the values are obtained for
+ that window instead of the current window.
+
Note that only marks in the current file can be used.
Examples: >vim
" With text "foo^Lbar" and cursor on the "^L":
@@ -11942,15 +11945,15 @@ M.funcs = {
" With text " there", with 't at 'h':
echo virtcol("'t") " returns 6
- <Techo he first column is 1. 0 is returned for an error.
- A echo more advanced example that echoes the maximum length of
+ <The first column is 1. 0 or [0, 0] is returned for an error.
+ A more advanced example that echoes the maximum length of
all lines: >vim
echo max(map(range(1, line('$')), "virtcol([v:val, '$'])"))
]=],
name = 'virtcol',
- params = { { 'expr', 'any' }, { 'list', 'any' } },
- signature = 'virtcol({expr} [, {list}])',
+ params = { { 'expr', 'any' }, { 'list', 'any' }, { 'winid', 'integer' } },
+ signature = 'virtcol({expr} [, {list} [, {winid}]])',
},
virtcol2col = {
args = 3,
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index e8224671dc..9926530d58 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -8748,13 +8748,31 @@ static void f_type(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->vval.v_number = n;
}
-/// "virtcol(string, bool)" function
+/// "virtcol({expr}, [, {list} [, {winid}]])" function
static void f_virtcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
colnr_T vcol_start = 0;
colnr_T vcol_end = 0;
- int fnum = curbuf->b_fnum;
+ switchwin_T switchwin;
+ bool winchanged = false;
+
+ if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) {
+ // use the window specified in the third argument
+ tabpage_T *tp;
+ win_T *wp = win_id2wp_tp((int)tv_get_number(&argvars[2]), &tp);
+ if (wp == NULL || tp == NULL) {
+ goto theend;
+ }
+ if (switch_win_noblock(&switchwin, wp, tp, true) != OK) {
+ goto theend;
+ }
+
+ check_cursor();
+ winchanged = true;
+ }
+
+ int fnum = curbuf->b_fnum;
pos_T *fp = var2fpos(&argvars[0], false, &fnum, false);
if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count
&& fnum == curbuf->b_fnum) {
@@ -8772,6 +8790,7 @@ static void f_virtcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
vcol_end++;
}
+theend:
if (argvars[1].v_type != VAR_UNKNOWN && tv_get_bool(&argvars[1])) {
tv_list_alloc_ret(rettv, 2);
tv_list_append_number(rettv->vval.v_list, vcol_start);
@@ -8779,6 +8798,10 @@ static void f_virtcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
} else {
rettv->vval.v_number = vcol_end;
}
+
+ if (winchanged) {
+ restore_win_noblock(&switchwin, true);
+ }
}
/// "visualmode()" function
diff --git a/test/old/testdir/test_cursor_func.vim b/test/old/testdir/test_cursor_func.vim
index 3d6ad8405c..e8b30226de 100644
--- a/test/old/testdir/test_cursor_func.vim
+++ b/test/old/testdir/test_cursor_func.vim
@@ -540,9 +540,28 @@ func Test_virtcol2col()
call assert_equal(8, virtcol2col(0, 1, 7))
call assert_equal(8, virtcol2col(0, 1, 8))
+ let w = winwidth(0)
+ call setline(2, repeat('a', w + 2))
+ let win_nosbr = win_getid()
+ split
+ setlocal showbreak=!!
+ let win_sbr = win_getid()
+ call assert_equal(w, virtcol2col(win_nosbr, 2, w))
+ call assert_equal(w + 1, virtcol2col(win_nosbr, 2, w + 1))
+ call assert_equal(w + 2, virtcol2col(win_nosbr, 2, w + 2))
+ call assert_equal(w + 2, virtcol2col(win_nosbr, 2, w + 3))
+ call assert_equal(w, virtcol2col(win_sbr, 2, w))
+ call assert_equal(w + 1, virtcol2col(win_sbr, 2, w + 1))
+ call assert_equal(w + 1, virtcol2col(win_sbr, 2, w + 2))
+ call assert_equal(w + 1, virtcol2col(win_sbr, 2, w + 3))
+ call assert_equal(w + 2, virtcol2col(win_sbr, 2, w + 4))
+ call assert_equal(w + 2, virtcol2col(win_sbr, 2, w + 5))
+ close
+
call assert_fails('echo virtcol2col("0", 1, 20)', 'E1210:')
call assert_fails('echo virtcol2col(0, "1", 20)', 'E1210:')
call assert_fails('echo virtcol2col(0, 1, "1")', 'E1210:')
+
bw!
endfunc
diff --git a/test/old/testdir/test_functions.vim b/test/old/testdir/test_functions.vim
index e286090018..c91e989233 100644
--- a/test/old/testdir/test_functions.vim
+++ b/test/old/testdir/test_functions.vim
@@ -3093,12 +3093,32 @@ endfunc
" Test for virtcol()
func Test_virtcol()
- enew!
+ new
call setline(1, "the\tquick\tbrown\tfox")
norm! 4|
call assert_equal(8, virtcol('.'))
call assert_equal(8, virtcol('.', v:false))
call assert_equal([4, 8], virtcol('.', v:true))
+
+ let w = winwidth(0)
+ call setline(2, repeat('a', w + 2))
+ let win_nosbr = win_getid()
+ split
+ setlocal showbreak=!!
+ let win_sbr = win_getid()
+ call assert_equal([w, w], virtcol([2, w], v:true, win_nosbr))
+ call assert_equal([w + 1, w + 1], virtcol([2, w + 1], v:true, win_nosbr))
+ call assert_equal([w + 2, w + 2], virtcol([2, w + 2], v:true, win_nosbr))
+ call assert_equal([w, w], virtcol([2, w], v:true, win_sbr))
+ call assert_equal([w + 3, w + 3], virtcol([2, w + 1], v:true, win_sbr))
+ call assert_equal([w + 4, w + 4], virtcol([2, w + 2], v:true, win_sbr))
+ close
+
+ call assert_equal(0, virtcol(''))
+ call assert_equal([0, 0], virtcol('', v:true))
+ call assert_equal(0, virtcol('.', v:false, 5001))
+ call assert_equal([0, 0], virtcol('.', v:true, 5001))
+
bwipe!
endfunc