diff src/evalfunc.c @ 28994:644b0f0541de v8.2.5019

patch 8.2.5019: cannot get the first screen column of a character Commit: https://github.com/vim/vim/commit/0f7a3e1de6f71e8e1423fe594890d6aa7f94e132 Author: LemonBoy <thatlemon@gmail.com> Date: Thu May 26 12:10:37 2022 +0100 patch 8.2.5019: cannot get the first screen column of a character Problem: Cannot get the first screen column of a character. Solution: Let virtcol() optionally return a list. (closes https://github.com/vim/vim/issues/10482, closes #7964)
author Bram Moolenaar <Bram@vim.org>
date Thu, 26 May 2022 13:15:04 +0200
parents 6cdf55afaae9
children 9f25e0ed831d
line wrap: on
line diff
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -994,6 +994,7 @@ 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_string_or_number[] = {arg_string, arg_string_or_nr};
 static argcheck_T arg3_any_list_dict[] = {NULL, arg_list_any, arg_dict_any};
 static argcheck_T arg3_buffer_lnum_lnum[] = {arg_buffer, arg_lnum, arg_lnum};
@@ -1458,6 +1459,20 @@ ret_getreg(int argcount,
 }
 
     static type_T *
+ret_virtcol(int argcount,
+	type2_T *argtypes UNUSED,
+	type_T	**decl_type)
+{
+    // Assume that if the second argument is passed it's non-zero
+    if (argcount == 2)
+    {
+	*decl_type = &t_list_any;
+	return &t_list_number;
+    }
+    return &t_number;
+}
+
+    static type_T *
 ret_maparg(int argcount,
 	type2_T *argtypes UNUSED,
 	type_T	**decl_type UNUSED)
@@ -2665,8 +2680,8 @@ static funcentry_T global_functions[] =
 			ret_first_arg,	    f_uniq},
     {"values",		1, 1, FEARG_1,	    arg1_dict_any,
 			ret_list_any,	    f_values},
-    {"virtcol",		1, 1, FEARG_1,	    arg1_string_or_list_any,
-			ret_number,	    f_virtcol},
+    {"virtcol",		1, 2, FEARG_1,	    arg2_string_or_list_bool,
+			ret_virtcol,	    f_virtcol},
     {"visualmode",	0, 1, 0,	    arg1_bool,
 			ret_string,	    f_visualmode},
     {"wildmenumode",	0, 0, 0,	    NULL,
@@ -10380,23 +10395,26 @@ f_type(typval_T *argvars, typval_T *rett
 }
 
 /*
- * "virtcol(string)" function
+ * "virtcol(string, bool)" function
  */
     static void
 f_virtcol(typval_T *argvars, typval_T *rettv)
 {
-    colnr_T	vcol = 0;
+    colnr_T	vcol_start = 0;
+    colnr_T	vcol_end = 0;
     pos_T	*fp;
     int		fnum = curbuf->b_fnum;
     int		len;
 
     if (in_vim9script()
-	    && check_for_string_or_list_arg(argvars, 0) == FAIL)
+	    && (check_for_string_or_list_arg(argvars, 0) == FAIL
+		|| (argvars[1].v_type != VAR_UNKNOWN
+		    && check_for_bool_arg(argvars, 1) == FAIL)))
 	return;
 
     fp = var2fpos(&argvars[0], FALSE, &fnum, FALSE);
     if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count
-						    && fnum == curbuf->b_fnum)
+	    && fnum == curbuf->b_fnum)
     {
 	// Limit the column to a valid value, getvvcol() doesn't check.
 	if (fp->col < 0)
@@ -10407,11 +10425,23 @@ f_virtcol(typval_T *argvars, typval_T *r
 	    if (fp->col > len)
 		fp->col = len;
 	}
-	getvvcol(curwin, fp, NULL, NULL, &vcol);
-	++vcol;
-    }
-
-    rettv->vval.v_number = vcol;
+	getvvcol(curwin, fp, &vcol_start, NULL, &vcol_end);
+	++vcol_start;
+	++vcol_end;
+    }
+
+    if (argvars[1].v_type != VAR_UNKNOWN && tv_get_bool(&argvars[1]))
+    {
+	if (rettv_list_alloc(rettv) == OK)
+	{
+	    list_append_number(rettv->vval.v_list, vcol_start);
+	    list_append_number(rettv->vval.v_list, vcol_end);
+	}
+	else
+	    rettv->vval.v_number = 0;
+    }
+    else
+	rettv->vval.v_number = vcol_end;
 }
 
 /*