vim-patch:9.0.1728: missing winid argument for virtcol() (#24770)

Problem: missing winid argument for virtcol()
Solution: Add a {winid} argument to virtcol()

Other functions col(), charcol() and virtcol2col() support a {winid}
argument, so it makes sense for virtcol() to also support than.

Also add test for virtcol2col() with 'showbreak' and {winid}.

closes: vim/vim#12633

825cf813fa
This commit is contained in:
zeertzjq
2023-08-18 08:42:45 +08:00
committed by GitHub
parent 46163ddf5d
commit f8afa8023e
6 changed files with 92 additions and 20 deletions

View File

@@ -8399,7 +8399,7 @@ values({dict}) *values()*
in arbitrary order. Also see |items()| and |keys()|. in arbitrary order. Also see |items()| and |keys()|.
Returns zero if {dict} is not a |Dict|. 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 The result is a Number, which is the screen column of the file
position given with {expr}. That is, the last screen position position given with {expr}. That is, the last screen position
occupied by the character at that position, when the screen 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 returns the cursor position. Differs from |'<| in
that it's updated right away. that it's updated right away.
If {list} is present and non-zero then virtcol() returns a List If {list} is present and non-zero then virtcol() returns a
with the first and last screen position occupied by the List with the first and last screen position occupied by the
character. 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. Note that only marks in the current file can be used.
Examples: >vim Examples: >vim
" With text "foo^Lbar" and cursor on the "^L": " With text "foo^Lbar" and cursor on the "^L":
@@ -8446,8 +8449,8 @@ virtcol({expr} [, {list}]) *virtcol()*
" With text " there", with 't at 'h': " With text " there", with 't at 'h':
echo virtcol("'t") " returns 6 echo virtcol("'t") " returns 6
< Techo he first column is 1. 0 is returned for an error. < The first column is 1. 0 or [0, 0] is returned for an error.
A echo more advanced example that echoes the maximum length of A more advanced example that echoes the maximum length of
all lines: >vim all lines: >vim
echo max(map(range(1, line('$')), "virtcol([v:val, '$'])")) echo max(map(range(1, line('$')), "virtcol([v:val, '$'])"))

View File

@@ -10013,10 +10013,13 @@ function vim.fn.values(dict) end
--- returns the cursor position. Differs from |'<| in --- returns the cursor position. Differs from |'<| in
--- that it's updated right away. --- that it's updated right away.
--- ---
--- If {list} is present and non-zero then virtcol() returns a List --- If {list} is present and non-zero then virtcol() returns a
--- with the first and last screen position occupied by the --- List with the first and last screen position occupied by the
--- character. --- 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. --- Note that only marks in the current file can be used.
--- Examples: >vim --- Examples: >vim
--- " With text "foo^Lbar" and cursor on the "^L": --- " 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': --- " With text " there", with 't at 'h':
--- ---
--- echo virtcol("'t") " returns 6 --- echo virtcol("'t") " returns 6
--- <Techo he first column is 1. 0 is returned for an error. --- <The first column is 1. 0 or [0, 0] is returned for an error.
--- A echo more advanced example that echoes the maximum length of --- A more advanced example that echoes the maximum length of
--- all lines: >vim --- all lines: >vim
--- echo max(map(range(1, line('$')), "virtcol([v:val, '$'])")) --- echo max(map(range(1, line('$')), "virtcol([v:val, '$'])"))
--- ---
--- @param expr any --- @param expr any
--- @param list? any --- @param list? any
--- @param winid? integer
--- @return any --- @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 --- The result is a Number, which is the byte index of the
--- character in window {winid} at buffer line {lnum} and virtual --- character in window {winid} at buffer line {lnum} and virtual

View File

@@ -11893,7 +11893,7 @@ M.funcs = {
signature = 'values({dict})', signature = 'values({dict})',
}, },
virtcol = { virtcol = {
args = { 1, 2 }, args = { 1, 3 },
base = 1, base = 1,
desc = [=[ desc = [=[
The result is a Number, which is the screen column of the file 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 returns the cursor position. Differs from |'<| in
that it's updated right away. that it's updated right away.
If {list} is present and non-zero then virtcol() returns a List If {list} is present and non-zero then virtcol() returns a
with the first and last screen position occupied by the List with the first and last screen position occupied by the
character. 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. Note that only marks in the current file can be used.
Examples: >vim Examples: >vim
" With text "foo^Lbar" and cursor on the "^L": " With text "foo^Lbar" and cursor on the "^L":
@@ -11942,15 +11945,15 @@ M.funcs = {
" With text " there", with 't at 'h': " With text " there", with 't at 'h':
echo virtcol("'t") " returns 6 echo virtcol("'t") " returns 6
<Techo he first column is 1. 0 is returned for an error. <The first column is 1. 0 or [0, 0] is returned for an error.
A echo more advanced example that echoes the maximum length of A more advanced example that echoes the maximum length of
all lines: >vim all lines: >vim
echo max(map(range(1, line('$')), "virtcol([v:val, '$'])")) echo max(map(range(1, line('$')), "virtcol([v:val, '$'])"))
]=], ]=],
name = 'virtcol', name = 'virtcol',
params = { { 'expr', 'any' }, { 'list', 'any' } }, params = { { 'expr', 'any' }, { 'list', 'any' }, { 'winid', 'integer' } },
signature = 'virtcol({expr} [, {list}])', signature = 'virtcol({expr} [, {list} [, {winid}]])',
}, },
virtcol2col = { virtcol2col = {
args = 3, args = 3,

View File

@@ -8748,13 +8748,31 @@ static void f_type(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->vval.v_number = n; 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) static void f_virtcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{ {
colnr_T vcol_start = 0; colnr_T vcol_start = 0;
colnr_T vcol_end = 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); pos_T *fp = var2fpos(&argvars[0], false, &fnum, false);
if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count
&& fnum == curbuf->b_fnum) { && fnum == curbuf->b_fnum) {
@@ -8772,6 +8790,7 @@ static void f_virtcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
vcol_end++; vcol_end++;
} }
theend:
if (argvars[1].v_type != VAR_UNKNOWN && tv_get_bool(&argvars[1])) { if (argvars[1].v_type != VAR_UNKNOWN && tv_get_bool(&argvars[1])) {
tv_list_alloc_ret(rettv, 2); tv_list_alloc_ret(rettv, 2);
tv_list_append_number(rettv->vval.v_list, vcol_start); 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 { } else {
rettv->vval.v_number = vcol_end; rettv->vval.v_number = vcol_end;
} }
if (winchanged) {
restore_win_noblock(&switchwin, true);
}
} }
/// "visualmode()" function /// "visualmode()" function

View File

@@ -540,9 +540,28 @@ func Test_virtcol2col()
call assert_equal(8, virtcol2col(0, 1, 7)) call assert_equal(8, virtcol2col(0, 1, 7))
call assert_equal(8, virtcol2col(0, 1, 8)) 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", 20)', 'E1210:') call assert_fails('echo virtcol2col(0, "1", 20)', 'E1210:')
call assert_fails('echo virtcol2col(0, 1, "1")', 'E1210:') call assert_fails('echo virtcol2col(0, 1, "1")', 'E1210:')
bw! bw!
endfunc endfunc

View File

@@ -3093,12 +3093,32 @@ endfunc
" Test for virtcol() " Test for virtcol()
func Test_virtcol() func Test_virtcol()
enew! new
call setline(1, "the\tquick\tbrown\tfox") call setline(1, "the\tquick\tbrown\tfox")
norm! 4| norm! 4|
call assert_equal(8, virtcol('.')) call assert_equal(8, virtcol('.'))
call assert_equal(8, virtcol('.', v:false)) call assert_equal(8, virtcol('.', v:false))
call assert_equal([4, 8], virtcol('.', v:true)) 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! bwipe!
endfunc endfunc