@@ -673,6 +673,7 @@ static void f_matchdelete(typval_T *argvars, typval_T *rettv);
673673static void f_matchend(typval_T *argvars, typval_T *rettv);
674674static void f_matchlist(typval_T *argvars, typval_T *rettv);
675675static void f_matchstr(typval_T *argvars, typval_T *rettv);
676+ static void f_matchstrpos(typval_T *argvars, typval_T *rettv);
676677static void f_max(typval_T *argvars, typval_T *rettv);
677678static void f_min(typval_T *argvars, typval_T *rettv);
678679#ifdef vim_mkdir
@@ -8383,6 +8384,7 @@ static struct fst
83838384 {"matchend", 2, 4, f_matchend},
83848385 {"matchlist", 2, 4, f_matchlist},
83858386 {"matchstr", 2, 4, f_matchstr},
8387+ {"matchstrpos", 2, 4, f_matchstrpos},
83868388 {"max", 1, 1, f_max},
83878389 {"min", 1, 1, f_min},
83888390#ifdef vim_mkdir
@@ -15302,11 +15304,26 @@ find_some_match(typval_T *argvars, typval_T *rettv, int type)
1530215304 p_cpo = (char_u *)"";
1530315305
1530415306 rettv->vval.v_number = -1;
15305- if (type == 3)
15307+ if (type == 3 || type == 4 )
1530615308 {
15307- /* return empty list when there are no matches */
15309+ /* type 3: return empty list when there are no matches.
15310+ * type 4: return ["", -1, -1, -1] */
1530815311 if (rettv_list_alloc(rettv) == FAIL)
1530915312 goto theend;
15313+ if (type == 4
15314+ && (list_append_string(rettv->vval.v_list,
15315+ (char_u *)"", 0) == FAIL
15316+ || list_append_number(rettv->vval.v_list,
15317+ (varnumber_T)-1) == FAIL
15318+ || list_append_number(rettv->vval.v_list,
15319+ (varnumber_T)-1) == FAIL
15320+ || list_append_number(rettv->vval.v_list,
15321+ (varnumber_T)-1) == FAIL))
15322+ {
15323+ list_free(rettv->vval.v_list, TRUE);
15324+ rettv->vval.v_list = NULL;
15325+ goto theend;
15326+ }
1531015327 }
1531115328 else if (type == 2)
1531215329 {
@@ -15383,7 +15400,7 @@ find_some_match(typval_T *argvars, typval_T *rettv, int type)
1538315400 break;
1538415401 }
1538515402 vim_free(tofree);
15386- str = echo_string(&li->li_tv, &tofree, strbuf, 0);
15403+ expr = str = echo_string(&li->li_tv, &tofree, strbuf, 0);
1538715404 if (str == NULL)
1538815405 break;
1538915406 }
@@ -15420,7 +15437,23 @@ find_some_match(typval_T *argvars, typval_T *rettv, int type)
1542015437
1542115438 if (match)
1542215439 {
15423- if (type == 3)
15440+ if (type == 4)
15441+ {
15442+ listitem_T *li1 = rettv->vval.v_list->lv_first;
15443+ listitem_T *li2 = li1->li_next;
15444+ listitem_T *li3 = li2->li_next;
15445+ listitem_T *li4 = li3->li_next;
15446+
15447+ li1->li_tv.vval.v_string = vim_strnsave(regmatch.startp[0],
15448+ (int)(regmatch.endp[0] - regmatch.startp[0]));
15449+ li3->li_tv.vval.v_number =
15450+ (varnumber_T)(regmatch.startp[0] - expr);
15451+ li4->li_tv.vval.v_number =
15452+ (varnumber_T)(regmatch.endp[0] - expr);
15453+ if (l != NULL)
15454+ li2->li_tv.vval.v_number = (varnumber_T)idx;
15455+ }
15456+ else if (type == 3)
1542415457 {
1542515458 int i;
1542615459
@@ -15465,6 +15498,11 @@ find_some_match(typval_T *argvars, typval_T *rettv, int type)
1546515498 vim_regfree(regmatch.regprog);
1546615499 }
1546715500
15501+ if (type == 4 && l == NULL)
15502+ /* matchstrpos() without a list: drop the second item. */
15503+ listitem_remove(rettv->vval.v_list,
15504+ rettv->vval.v_list->lv_first->li_next);
15505+
1546815506theend:
1546915507 vim_free(tofree);
1547015508 p_cpo = save_cpo;
@@ -15665,6 +15703,15 @@ f_matchstr(typval_T *argvars, typval_T *rettv)
1566515703 find_some_match(argvars, rettv, 2);
1566615704}
1566715705
15706+ /*
15707+ * "matchstrpos()" function
15708+ */
15709+ static void
15710+ f_matchstrpos(typval_T *argvars, typval_T *rettv)
15711+ {
15712+ find_some_match(argvars, rettv, 4);
15713+ }
15714+
1566815715static void max_min(typval_T *argvars, typval_T *rettv, int domax);
1566915716
1567015717 static void
0 commit comments