patch 9.0.1728: missing winid argument for virtcol()

Commit: 
https://github.com/vim/vim/commit/825cf813fa0fddf085fcbd3194781e875320ff63
Author: zeertzjq <[email protected]>
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 <[email protected]>
    Co-authored-by: zeertzjq <[email protected]>

diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 6a5ec1bac..661876b24 100644
--- 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
index ef0414c68..c0710da11 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -1070,7 +1070,6 @@ static argcheck_T arg2_string_dict[] = {arg_string, 
arg_dict_any};
 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[] = {arg_string, 
arg_bool, arg_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 *rettv)
 }
 
 /*
- * "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 *rettv)
     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)))
+                   && (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 *rettv)
        ++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 *rettv)
     }
     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
index 2ae7580a4..b0444d5e6 100644
--- 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
index e5d56ac18..60e99210e 100644
--- 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
index 23a68358c..5e57b90fd 100644
--- 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
index b9e584d20..aa4a089bf 100644
--- a/src/version.c
+++ b/src/version.c
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1728,
 /**/
     1727,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/E1qWk6A-006ZfA-CT%40256bit.org.

Raspunde prin e-mail lui