To: vim_dev@googlegroups.com Subject: Patch 7.4.1685 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4.1685 Problem: There is no easy way to get all the information about a match. Solution: Add matchstrpos(). (Ozaki Kiichi) Files: runtime/doc/eval.txt, runtime/doc/usr_41.txt, src/eval.c, src/testdir/test_alot.vim, src/testdir/test_matchstrpos.vim *** ../vim-7.4.1684/runtime/doc/eval.txt 2016-03-27 15:13:06.962231587 +0200 --- runtime/doc/eval.txt 2016-03-29 23:03:41.642496981 +0200 *************** *** 2003,2008 **** --- 2020,2027 ---- List match and submatches of {pat} in {expr} matchstr( {expr}, {pat}[, {start}[, {count}]]) String {count}'th match of {pat} in {expr} + matchstrpos( {expr}, {pat}[, {start}[, {count}]]) + List {count}'th match of {pat} in {expr} max( {list}) Number maximum value of items in {list} min( {list}) Number minimum value of items in {list} mkdir( {name} [, {path} [, {prot}]]) *************** *** 5121,5126 **** --- 5208,5231 ---- When {expr} is a |List| then the matching item is returned. The type isn't changed, it's not necessarily a String. + matchstrpos({expr}, {pat}[, {start}[, {count}]]) *matchstrpos()* + Same as |matchstr()|, but return the matched string, the start + position and the end position of the match. Example: > + :echo matchstrpos("testing", "ing") + < results in ["ing", 4, 7]. + When there is no match ["", -1, -1] is returned. + The {start}, if given, has the same meaning as for |match()|. > + :echo matchstrpos("testing", "ing", 2) + < results in ["ing", 4, 7]. > + :echo matchstrpos("testing", "ing", 5) + < result is ["", -1, -1]. + When {expr} is a |List| then the matching item, the index + of first item where {pat} matches, the start position and the + end position of the match are returned. > + :echo matchstrpos([1, '__x'], '\a') + < result is ["x", 1, 2, 3]. + The type isn't changed, it's not necessarily a String. + *max()* max({list}) Return the maximum value of all items in {list}. If {list} is not a list or one of the items in {list} cannot *** ../vim-7.4.1684/runtime/doc/usr_41.txt 2016-01-17 21:15:17.839322597 +0100 --- runtime/doc/usr_41.txt 2016-03-29 22:43:02.095293197 +0200 *************** *** 592,597 **** --- 592,598 ---- match() position where a pattern matches in a string matchend() position where a pattern match ends in a string matchstr() match of a pattern in a string + matchstrpos() match and postions of a pattern in a string matchlist() like matchstr() and also return submatches stridx() first index of a short string in a long string strridx() last index of a short string in a long string *** ../vim-7.4.1684/src/eval.c 2016-03-28 22:48:26.000724752 +0200 --- src/eval.c 2016-03-29 22:59:56.020825613 +0200 *************** *** 673,678 **** --- 673,679 ---- static void f_matchend(typval_T *argvars, typval_T *rettv); static void f_matchlist(typval_T *argvars, typval_T *rettv); static void f_matchstr(typval_T *argvars, typval_T *rettv); + static void f_matchstrpos(typval_T *argvars, typval_T *rettv); static void f_max(typval_T *argvars, typval_T *rettv); static void f_min(typval_T *argvars, typval_T *rettv); #ifdef vim_mkdir *************** *** 8383,8388 **** --- 8384,8390 ---- {"matchend", 2, 4, f_matchend}, {"matchlist", 2, 4, f_matchlist}, {"matchstr", 2, 4, f_matchstr}, + {"matchstrpos", 2, 4, f_matchstrpos}, {"max", 1, 1, f_max}, {"min", 1, 1, f_min}, #ifdef vim_mkdir *************** *** 15302,15312 **** p_cpo = (char_u *)""; rettv->vval.v_number = -1; ! if (type == 3) { ! /* return empty list when there are no matches */ if (rettv_list_alloc(rettv) == FAIL) goto theend; } else if (type == 2) { --- 15304,15329 ---- p_cpo = (char_u *)""; rettv->vval.v_number = -1; ! if (type == 3 || type == 4) { ! /* type 3: return empty list when there are no matches. ! * type 4: return ["", -1, -1, -1] */ if (rettv_list_alloc(rettv) == FAIL) goto theend; + if (type == 4 + && (list_append_string(rettv->vval.v_list, + (char_u *)"", 0) == FAIL + || list_append_number(rettv->vval.v_list, + (varnumber_T)-1) == FAIL + || list_append_number(rettv->vval.v_list, + (varnumber_T)-1) == FAIL + || list_append_number(rettv->vval.v_list, + (varnumber_T)-1) == FAIL)) + { + list_free(rettv->vval.v_list, TRUE); + rettv->vval.v_list = NULL; + goto theend; + } } else if (type == 2) { *************** *** 15383,15389 **** break; } vim_free(tofree); ! str = echo_string(&li->li_tv, &tofree, strbuf, 0); if (str == NULL) break; } --- 15400,15406 ---- break; } vim_free(tofree); ! expr = str = echo_string(&li->li_tv, &tofree, strbuf, 0); if (str == NULL) break; } *************** *** 15420,15426 **** if (match) { ! if (type == 3) { int i; --- 15437,15459 ---- if (match) { ! if (type == 4) ! { ! listitem_T *li1 = rettv->vval.v_list->lv_first; ! listitem_T *li2 = li1->li_next; ! listitem_T *li3 = li2->li_next; ! listitem_T *li4 = li3->li_next; ! ! li1->li_tv.vval.v_string = vim_strnsave(regmatch.startp[0], ! (int)(regmatch.endp[0] - regmatch.startp[0])); ! li3->li_tv.vval.v_number = ! (varnumber_T)(regmatch.startp[0] - expr); ! li4->li_tv.vval.v_number = ! (varnumber_T)(regmatch.endp[0] - expr); ! if (l != NULL) ! li2->li_tv.vval.v_number = (varnumber_T)idx; ! } ! else if (type == 3) { int i; *************** *** 15465,15470 **** --- 15498,15508 ---- vim_regfree(regmatch.regprog); } + if (type == 4 && l == NULL) + /* matchstrpos() without a list: drop the second item. */ + listitem_remove(rettv->vval.v_list, + rettv->vval.v_list->lv_first->li_next); + theend: vim_free(tofree); p_cpo = save_cpo; *************** *** 15665,15670 **** --- 15703,15717 ---- find_some_match(argvars, rettv, 2); } + /* + * "matchstrpos()" function + */ + static void + f_matchstrpos(typval_T *argvars, typval_T *rettv) + { + find_some_match(argvars, rettv, 4); + } + static void max_min(typval_T *argvars, typval_T *rettv, int domax); static void *** ../vim-7.4.1684/src/testdir/test_alot.vim 2016-03-26 20:59:48.111431615 +0100 --- src/testdir/test_alot.vim 2016-03-29 22:43:02.103293115 +0200 *************** *** 15,20 **** --- 15,21 ---- source test_help_tagjump.vim source test_join.vim source test_lispwords.vim + source test_matchstrpos.vim source test_menu.vim source test_partial.vim source test_reltime.vim *** ../vim-7.4.1684/src/testdir/test_matchstrpos.vim 2016-03-29 23:07:53.175901290 +0200 --- src/testdir/test_matchstrpos.vim 2016-03-29 22:44:24.658440733 +0200 *************** *** 0 **** --- 1,13 ---- + " Test matchstrpos + + func Test_matchstrpos() + call assert_equal(['ing', 4, 7], matchstrpos('testing', 'ing')) + + call assert_equal(['ing', 4, 7], matchstrpos('testing', 'ing', 2)) + + call assert_equal(['', -1, -1], matchstrpos('testing', 'ing', 5)) + + call assert_equal(['ing', 1, 4, 7], matchstrpos(['vim', 'testing', 'execute'], 'ing')) + + call assert_equal(['', -1, -1, -1], matchstrpos(['vim', 'testing', 'execute'], 'img')) + endfunc *** ../vim-7.4.1684/src/version.c 2016-03-29 22:26:24.617615161 +0200 --- src/version.c 2016-03-29 22:42:47.263446342 +0200 *************** *** 750,751 **** --- 750,753 ---- { /* Add new patch number below this line */ + /**/ + 1685, /**/ -- "Hit any key to continue" is very confusing when you have two keyboards. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///