# HG changeset patch # User Christian Brabandt # Date 1692306006 -7200 # Node ID 6e53cf9745f4160a5885df88cc98026805f06a42 # Parent 80e4411ad2e08a57ce0ed468fb00d953ff805fa8 patch 9.0.1728: missing winid argument for virtcol() Commit: https://github.com/vim/vim/commit/825cf813fa0fddf085fcbd3194781e875320ff63 Author: zeertzjq Date: Thu Aug 17 22:55:25 2023 +0200 patch 9.0.1728: missing winid argument for virtcol() 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: #12633 Signed-off-by: Christian Brabandt Co-authored-by: zeertzjq diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -713,7 +713,8 @@ uniq({list} [, {func} [, {dict}]]) utf16idx({string}, {idx} [, {countcc} [, {charidx}]]) Number UTF-16 index of byte {idx} in {string} values({dict}) List values in {dict} -virtcol({expr} [, {list}]) Number or List +virtcol({expr} [, {list} [, {winid}]) + Number or List screen column of cursor or mark virtcol2col({winid}, {lnum}, {col}) Number byte index of a character on screen @@ -10283,7 +10284,7 @@ values({dict}) *values()* Can also be used as a |method|: > mydict->values() -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 @@ -10315,10 +10316,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: > " With text "foo^Lbar" and cursor on the "^L": @@ -10330,7 +10334,7 @@ virtcol({expr} [, {list}]) *virtcol() " With text " there", with 't at 'h': virtcol("'t") " returns 6 -< The 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 more advanced example that echoes the maximum length of all lines: > echo max(map(range(1, line('$')), "virtcol([v:val, '$'])")) diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -1070,7 +1070,6 @@ static argcheck_T arg2_string_dict[] = { static argcheck_T arg2_string_list_number[] = {arg_string, arg_list_number}; static argcheck_T arg2_string_number[] = {arg_string, arg_number}; static argcheck_T arg2_string_or_list_dict[] = {arg_string_or_list_any, arg_dict_any}; -static argcheck_T arg2_string_or_list_bool[] = {arg_string_or_list_any, arg_bool}; static argcheck_T arg2_string_or_list_number[] = {arg_string_or_list_any, arg_number}; static argcheck_T arg2_string_string_or_number[] = {arg_string, arg_string_or_nr}; static argcheck_T arg3_any_list_dict[] = {NULL, arg_list_any, arg_dict_any}; @@ -1094,6 +1093,7 @@ static argcheck_T arg3_string_bool_bool[ static argcheck_T arg3_string_number_bool[] = {arg_string, arg_number, arg_bool}; static argcheck_T arg3_string_number_number[] = {arg_string, arg_number, arg_number}; static argcheck_T arg3_string_or_dict_bool_dict[] = {arg_string_or_dict_any, arg_bool, arg_dict_any}; +static argcheck_T arg3_string_or_list_bool_number[] = {arg_string_or_list_any, arg_bool, arg_number}; static argcheck_T arg3_string_string_bool[] = {arg_string, arg_string, arg_bool}; static argcheck_T arg3_string_string_dict[] = {arg_string, arg_string, arg_dict_any}; static argcheck_T arg3_string_string_number[] = {arg_string, arg_string, arg_number}; @@ -1569,7 +1569,7 @@ ret_virtcol(int argcount, type_T **decl_type) { // Assume that if the second argument is passed it's non-zero - if (argcount == 2) + if (argcount > 1) { *decl_type = &t_list_any; return &t_list_number; @@ -2806,7 +2806,7 @@ static funcentry_T global_functions[] = ret_number, f_utf16idx}, {"values", 1, 1, FEARG_1, arg1_dict_any, ret_list_member, f_values}, - {"virtcol", 1, 2, FEARG_1, arg2_string_or_list_bool, + {"virtcol", 1, 3, FEARG_1, arg3_string_or_list_bool_number, ret_virtcol, f_virtcol}, {"virtcol2col", 3, 3, FEARG_1, arg3_number, ret_number, f_virtcol2col}, @@ -10737,7 +10737,7 @@ f_type(typval_T *argvars, typval_T *rett } /* - * "virtcol(string, bool)" function + * "virtcol({expr}, [, {list} [, {winid}]])" function */ static void f_virtcol(typval_T *argvars, typval_T *rettv) @@ -10745,15 +10745,35 @@ f_virtcol(typval_T *argvars, typval_T *r colnr_T vcol_start = 0; colnr_T vcol_end = 0; pos_T *fp; - int fnum = curbuf->b_fnum; + switchwin_T switchwin; + int winchanged = FALSE; int len; if (in_vim9script() && (check_for_string_or_list_arg(argvars, 0) == FAIL || (argvars[1].v_type != VAR_UNKNOWN - && check_for_bool_arg(argvars, 1) == FAIL))) - return; - + && (check_for_bool_arg(argvars, 1) == FAIL + || check_for_opt_number_arg(argvars, 2) == FAIL)))) + return; + + if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) + { + tabpage_T *tp; + win_T *wp; + + // use the window specified in the third argument + 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; fp = var2fpos(&argvars[0], FALSE, &fnum, FALSE); if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count && fnum == curbuf->b_fnum) @@ -10772,6 +10792,7 @@ f_virtcol(typval_T *argvars, typval_T *r ++vcol_end; } +theend: if (argvars[1].v_type != VAR_UNKNOWN && tv_get_bool(&argvars[1])) { if (rettv_list_alloc(rettv) == OK) @@ -10784,6 +10805,9 @@ f_virtcol(typval_T *argvars, typval_T *r } else rettv->vval.v_number = vcol_end; + + if (winchanged) + restore_win_noblock(&switchwin, TRUE); } /* diff --git a/src/testdir/test_cursor_func.vim b/src/testdir/test_cursor_func.vim --- a/src/testdir/test_cursor_func.vim +++ b/src/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/src/testdir/test_functions.vim b/src/testdir/test_functions.vim --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -3514,12 +3514,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 diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -4811,6 +4811,9 @@ def Test_virtcol() v9.CheckDefAndScriptFailure(['virtcol(".", "a")'], [ 'E1013: Argument 2: type mismatch, expected bool but got string', 'E1212: Bool required for argument 2']) + v9.CheckDefAndScriptFailure(['virtcol(".", v:true, [])'], [ + 'E1013: Argument 3: type mismatch, expected number but got list', + 'E1210: Number required for argument 3']) v9.CheckDefExecAndScriptFailure(['virtcol("")'], 'E1209: Invalid value for a line number') new diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -696,6 +696,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1728, +/**/ 1727, /**/ 1726,