From 6fea2dfd26cb902d7b2f52f53ccca9befef2b442 Mon Sep 17 00:00:00 2001 From: Michael Ennen Date: Thu, 24 Nov 2016 23:13:30 -0700 Subject: vim-patch:7.4.1685 Problem: There is no easy way to get all the information about a match. Solution: Add matchstrpos(). (Ozaki Kiichi) https://github.com/vim/vim/commit/7fed5c18f8577b75404b80d8b9a9907b1bbd27e4 --- runtime/doc/eval.txt | 20 +++++++++++++++++++ runtime/doc/usr_41.txt | 1 + src/nvim/eval.c | 37 +++++++++++++++++++++++++++++++---- src/nvim/eval.lua | 1 + src/nvim/testdir/test_alot.vim | 1 + src/nvim/testdir/test_matchstrpos.vim | 13 ++++++++++++ src/nvim/version.c | 2 +- 7 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 src/nvim/testdir/test_matchstrpos.vim diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index cca53db531..53f14c7d47 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2032,6 +2032,8 @@ matchlist({expr}, {pat}[, {start}[, {count}]]) 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}]]) @@ -5017,6 +5019,24 @@ matchstr({expr}, {pat}[, {start}[, {count}]]) *matchstr()* :echo matchstr("testing", "ing", 5) < result is "". 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()* diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 4d3ad49f1f..2896611274 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -592,6 +592,7 @@ String manipulation: *string-functions* 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 diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 8e8d36b442..ba5864fe3b 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -12211,9 +12211,16 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type) p_cpo = (char_u *)""; rettv->vval.v_number = -1; - if (type == 3) { - /* return empty list when there are no matches */ + if (type == 3 || type == 4) { + // type 3: return empty list when there are no matches. + // type 4: return ["", -1, -1, -1] rettv_list_alloc(rettv); + if (type == 4) { + list_append_string(rettv->vval.v_list, (char_u *)"", 0); + list_append_number(rettv->vval.v_list, (varnumber_T)-1); + list_append_number(rettv->vval.v_list, (varnumber_T)-1); + list_append_number(rettv->vval.v_list, (varnumber_T)-1); + } } else if (type == 2) { rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; @@ -12276,7 +12283,7 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type) break; } xfree(tofree); - tofree = str = (char_u *) encode_tv2echo(&li->li_tv, NULL); + tofree = expr = str = (char_u *)encode_tv2echo(&li->li_tv, NULL); if (str == NULL) { break; } @@ -12304,7 +12311,19 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type) } if (match) { - if (type == 3) { + 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; + int rd = (int)(regmatch.endp[0] - regmatch.startp[0]); + li1->li_tv.vval.v_string = vim_strnsave(regmatch.startp[0], rd); + 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; /* return list with matched string and submatches */ @@ -12339,6 +12358,11 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type) 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: xfree(tofree); p_cpo = save_cpo; @@ -12511,6 +12535,11 @@ static void f_matchstr(typval_T *argvars, typval_T *rettv, FunPtr fptr) find_some_match(argvars, rettv, 2); } +/// "matchstrpos()" function +static void f_matchstrpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + find_some_match(argvars, rettv, 4); +} static void max_min(typval_T *argvars, typval_T *rettv, int domax) { diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index bea25b36f3..61a5438d8c 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -198,6 +198,7 @@ return { matchend={args={2, 4}}, matchlist={args={2, 4}}, matchstr={args={2, 4}}, + matchstrpos={args={2,4}}, max={args=1}, min={args=1}, mkdir={args={1, 3}}, diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim index c9d7b332e4..58ed57499f 100644 --- a/src/nvim/testdir/test_alot.vim +++ b/src/nvim/testdir/test_alot.vim @@ -9,6 +9,7 @@ source test_expr.vim source test_expr_utf8.vim source test_feedkeys.vim source test_goto.vim +source test_matchstrpos.vim source test_menu.vim source test_messages.vim source test_options.vim diff --git a/src/nvim/testdir/test_matchstrpos.vim b/src/nvim/testdir/test_matchstrpos.vim new file mode 100644 index 0000000000..e14765b26b --- /dev/null +++ b/src/nvim/testdir/test_matchstrpos.vim @@ -0,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 diff --git a/src/nvim/version.c b/src/nvim/version.c index aea5143bb8..ea2646d23e 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -759,7 +759,7 @@ static int included_patches[] = { // 1688 NA // 1687 NA 1686, - // 1685, + 1685, // 1684 NA // 1683 NA 1682, -- cgit From 629e788b3689698f8cd96a71b0d5421d7456e770 Mon Sep 17 00:00:00 2001 From: Michael Ennen Date: Tue, 6 Dec 2016 16:54:59 -0700 Subject: vim-patch:7.4.2163 Problem: match() and related functions tested with old style test. Solution: Convert to new style test. (Hirohito Higashi) https://github.com/vim/vim/commit/d76a0c15f8bdbc901015879177fd5076d34c7a06 --- src/nvim/testdir/Makefile | 3 +- src/nvim/testdir/test_alot.vim | 4 +- src/nvim/testdir/test_match.vim | 165 ++++++++++++++++++++++++++++++++++ src/nvim/testdir/test_matchstrpos.vim | 13 --- src/nvim/version.c | 2 +- 5 files changed, 170 insertions(+), 17 deletions(-) create mode 100644 src/nvim/testdir/test_match.vim delete mode 100644 src/nvim/testdir/test_matchstrpos.vim diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index b2a512013b..dba8a8a877 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -37,13 +37,14 @@ NEW_TESTS = \ test_help_tagjump.res \ test_history.res \ test_langmap.res \ + test_match.res \ + test_matchadd_conceal.res \ test_syntax.res \ test_usercommands.res \ test_timers.res \ test_viml.res \ test_visual.res \ test_window_id.res \ - test_matchadd_conceal.res \ test_alot.res SCRIPTS_GUI := test16.out diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim index 58ed57499f..b8b79632d7 100644 --- a/src/nvim/testdir/test_alot.vim +++ b/src/nvim/testdir/test_alot.vim @@ -9,7 +9,8 @@ source test_expr.vim source test_expr_utf8.vim source test_feedkeys.vim source test_goto.vim -source test_matchstrpos.vim +source test_match.vim +source test_matchadd_conceal_utf8.vim source test_menu.vim source test_messages.vim source test_options.vim @@ -20,4 +21,3 @@ source test_syn_attr.vim source test_tabline.vim source test_tabpage.vim source test_unlet.vim -source test_matchadd_conceal_utf8.vim diff --git a/src/nvim/testdir/test_match.vim b/src/nvim/testdir/test_match.vim new file mode 100644 index 0000000000..57dde19bab --- /dev/null +++ b/src/nvim/testdir/test_match.vim @@ -0,0 +1,165 @@ +" Test for :match, :2match, :3match, clearmatches(), getmatches(), matchadd(), +" matchaddpos(), matcharg(), matchdelete(), matchstrpos() and setmatches(). + +function Test_matcharg() + highlight MyGroup1 term=bold ctermbg=red guibg=red + highlight MyGroup2 term=italic ctermbg=green guibg=green + highlight MyGroup3 term=underline ctermbg=blue guibg=blue + + " --- Check that "matcharg()" returns the correct group and pattern if a match + " --- is defined. + match MyGroup1 /TODO/ + 2match MyGroup2 /FIXME/ + 3match MyGroup3 /XXX/ + call assert_equal(['MyGroup1', 'TODO'], matcharg(1)) + call assert_equal(['MyGroup2', 'FIXME'], matcharg(2)) + call assert_equal(['MyGroup3', 'XXX'], matcharg(3)) + + " --- Check that "matcharg()" returns an empty list if the argument is not 1, + " --- 2 or 3 (only 0 and 4 are tested). + call assert_equal([], matcharg(0)) + call assert_equal([], matcharg(4)) + + " --- Check that "matcharg()" returns ['', ''] if a match is not defined. + match + 2match + 3match + call assert_equal(['', ''], matcharg(1)) + call assert_equal(['', ''], matcharg(2)) + call assert_equal(['', ''], matcharg(3)) + + " --- Check that "matchadd()" and "getmatches()" agree on added matches and + " --- that default values apply. + let m1 = matchadd("MyGroup1", "TODO") + let m2 = matchadd("MyGroup2", "FIXME", 42) + let m3 = matchadd("MyGroup3", "XXX", 60, 17) + let ans = [{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 4}, + \ {'group': 'MyGroup2', 'pattern': 'FIXME', 'priority': 42, 'id': 5}, + \ {'group': 'MyGroup3', 'pattern': 'XXX', 'priority': 60, 'id': 17}] + call assert_equal(ans, getmatches()) + + " --- Check that "matchdelete()" deletes the matches defined in the previous + " --- test correctly. + call matchdelete(m1) + call matchdelete(m2) + call matchdelete(m3) + call assert_equal([], getmatches()) + + " --- Check that "matchdelete()" returns 0 if successful and otherwise -1. + let m = matchadd("MyGroup1", "TODO") + call assert_equal(0, matchdelete(m)) + call assert_fails('call matchdelete(42)', 'E803:') + + " --- Check that "clearmatches()" clears all matches defined by ":match" and + " --- "matchadd()". + let m1 = matchadd("MyGroup1", "TODO") + let m2 = matchadd("MyGroup2", "FIXME", 42) + let m3 = matchadd("MyGroup3", "XXX", 60, 17) + match MyGroup1 /COFFEE/ + 2match MyGroup2 /HUMPPA/ + 3match MyGroup3 /VIM/ + call clearmatches() + call assert_equal([], getmatches()) + + " --- Check that "setmatches()" restores a list of matches saved by + " --- "getmatches()" without changes. (Matches with equal priority must also + " --- remain in the same order.) + let m1 = matchadd("MyGroup1", "TODO") + let m2 = matchadd("MyGroup2", "FIXME", 42) + let m3 = matchadd("MyGroup3", "XXX", 60, 17) + match MyGroup1 /COFFEE/ + 2match MyGroup2 /HUMPPA/ + 3match MyGroup3 /VIM/ + let ml = getmatches() + call clearmatches() + call setmatches(ml) + call assert_equal(ml, getmatches()) + call clearmatches() + + " --- Check that "setmatches()" will not add two matches with the same ID. The + " --- expected behaviour (for now) is to add the first match but not the + " --- second and to return 0 (even though it is a matter of debate whether + " --- this can be considered successful behaviour). + let data = [{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}, + \ {'group': 'MyGroup2', 'pattern': 'FIXME', 'priority': 10, 'id': 1}] + call assert_fails('call setmatches(data)', 'E801:') + call assert_equal([data[0]], getmatches()) + call clearmatches() + + " --- Check that "setmatches()" returns 0 if successful and otherwise -1. + " --- (A range of valid and invalid input values are tried out to generate the + " --- return values.) + call assert_equal(0, setmatches([])) + call assert_equal(0, setmatches([{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}])) + call clearmatches() + call assert_fails('call setmatches(0)', 'E714:') + call assert_fails('call setmatches([0])', 'E474:') + call assert_fails("call setmatches([{'wrong key': 'wrong value'}])", 'E474:') + + call setline(1, 'abcdefghijklmnopq') + call matchaddpos("MyGroup1", [[1, 5], [1, 8, 3]], 10, 3) + 1 + redraw! + let v1 = screenattr(1, 1) + let v5 = screenattr(1, 5) + let v6 = screenattr(1, 6) + let v8 = screenattr(1, 8) + let v10 = screenattr(1, 10) + let v11 = screenattr(1, 11) + call assert_notequal(v1, v5) + call assert_equal(v6, v1) + call assert_equal(v8, v5) + call assert_equal(v10, v5) + call assert_equal(v11, v1) + call assert_equal([{'group': 'MyGroup1', 'id': 3, 'priority': 10, 'pos1': [1, 5, 1], 'pos2': [1, 8, 3]}], getmatches()) + call clearmatches() + + " + if has('multi_byte') + call setline(1, 'abcdΣabcdef') + call matchaddpos("MyGroup1", [[1, 4, 2], [1, 9, 2]]) + 1 + redraw! + let v1 = screenattr(1, 1) + let v4 = screenattr(1, 4) + let v5 = screenattr(1, 5) + let v6 = screenattr(1, 6) + let v7 = screenattr(1, 7) + let v8 = screenattr(1, 8) + let v9 = screenattr(1, 9) + let v10 = screenattr(1, 10) + call assert_equal([{'group': 'MyGroup1', 'id': 11, 'priority': 10, 'pos1': [1, 4, 2], 'pos2': [1, 9, 2]}], getmatches()) + call assert_notequal(v1, v4) + call assert_equal(v5, v4) + call assert_equal(v6, v1) + call assert_equal(v7, v1) + call assert_equal(v8, v4) + call assert_equal(v9, v4) + call assert_equal(v10, v1) + + " Check, that setmatches() can correctly restore the matches from matchaddpos() + call matchadd('MyGroup1', '\%2lmatchadd') + let m=getmatches() + call clearmatches() + call setmatches(m) + call assert_equal([{'group': 'MyGroup1', 'id': 11, 'priority': 10, 'pos1': [1, 4, 2], 'pos2': [1,9, 2]}, {'group': 'MyGroup1', 'pattern': '\%2lmatchadd', 'priority': 10, 'id': 12}], getmatches()) + endif + + highlight MyGroup1 NONE + highlight MyGroup2 NONE + highlight MyGroup3 NONE +endfunc + +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: et ts=2 sw=2 diff --git a/src/nvim/testdir/test_matchstrpos.vim b/src/nvim/testdir/test_matchstrpos.vim deleted file mode 100644 index e14765b26b..0000000000 --- a/src/nvim/testdir/test_matchstrpos.vim +++ /dev/null @@ -1,13 +0,0 @@ -" 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 diff --git a/src/nvim/version.c b/src/nvim/version.c index ea2646d23e..0f97ad3262 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -279,7 +279,7 @@ static int included_patches[] = { // 2166 NA // 2165, // 2164, - // 2163, + 2163, 2162, // 2161, // 2160, -- cgit From 0064e9738aec725b9cf4b29f425b0da7ecc8fd46 Mon Sep 17 00:00:00 2001 From: Michael Ennen Date: Tue, 6 Dec 2016 17:12:08 -0700 Subject: vim-patch:7.4.2217 Problem: When using matchaddpos() a character after the end of the line can be highlighted. Solution: Only highlight existing characters. (Hirohito Higashi) https://github.com/vim/vim/commit/4f416e41243ca151b95d39d81ce23d00b1484755 --- src/nvim/buffer_defs.h | 5 +++-- src/nvim/screen.c | 29 +++++++++++++++++------------ src/nvim/testdir/test_match.vim | 26 +++++++++++++++++++++++++- src/nvim/version.c | 2 +- 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 4f0de1451a..65ce07a172 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -885,8 +885,9 @@ typedef struct { int attr_cur; /* attributes currently active in win_line() */ linenr_T first_lnum; /* first lnum to search for multi-line pat */ colnr_T startcol; /* in win_line() points to char where HL starts */ - colnr_T endcol; /* in win_line() points to char where HL ends */ - proftime_T tm; /* for a time limit */ + colnr_T endcol; // in win_line() points to char where HL ends + bool is_addpos; // position specified directly by matchaddpos() + proftime_T tm; // for a time limit } match_T; /// number of positions supported by matchaddpos() diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 9075f94a20..c5fe5e8b05 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -2592,6 +2592,7 @@ win_line ( shl->startcol = MAXCOL; shl->endcol = MAXCOL; shl->attr_cur = 0; + shl->is_addpos = false; v = (long)(ptr - line); if (cur != NULL) { cur->pos.cur = 0; @@ -3760,18 +3761,18 @@ win_line ( if ((long)(wp->w_p_wrap ? wp->w_skipcol : wp->w_leftcol) > prevcol) ++prevcol; - /* Invert at least one char, used for Visual and empty line or - * highlight match at end of line. If it's beyond the last - * char on the screen, just overwrite that one (tricky!) Not - * needed when a '$' was displayed for 'list'. */ - prevcol_hl_flag = FALSE; - if (prevcol == (long)search_hl.startcol) - prevcol_hl_flag = TRUE; - else { + // Invert at least one char, used for Visual and empty line or + // highlight match at end of line. If it's beyond the last + // char on the screen, just overwrite that one (tricky!) Not + // needed when a '$' was displayed for 'list'. + prevcol_hl_flag = false; + if (!search_hl.is_addpos && prevcol == (long)search_hl.startcol) { + prevcol_hl_flag = true; + } else { cur = wp->w_match_head; while (cur != NULL) { - if (prevcol == (long)cur->hl.startcol) { - prevcol_hl_flag = TRUE; + if (!cur->hl.is_addpos && prevcol == (long)cur->hl.startcol) { + prevcol_hl_flag = true; break; } cur = cur->next; @@ -3821,10 +3822,13 @@ win_line ( shl_flag = TRUE; } else shl = &cur->hl; - if ((ptr - line) - 1 == (long)shl->startcol) + if ((ptr - line) - 1 == (long)shl->startcol + && (shl == &search_hl || !shl->is_addpos)) { char_attr = shl->attr; - if (shl != &search_hl && cur != NULL) + } + if (shl != &search_hl && cur != NULL) { cur = cur->next; + } } } ScreenAttrs[off] = char_attr; @@ -5737,6 +5741,7 @@ next_search_hl_pos( shl->rm.startpos[0].col = start; shl->rm.endpos[0].lnum = 0; shl->rm.endpos[0].col = end; + shl->is_addpos = true; posmatch->cur = bot + 1; return true; } diff --git a/src/nvim/testdir/test_match.vim b/src/nvim/testdir/test_match.vim index 57dde19bab..67f3ea7373 100644 --- a/src/nvim/testdir/test_match.vim +++ b/src/nvim/testdir/test_match.vim @@ -1,7 +1,7 @@ " Test for :match, :2match, :3match, clearmatches(), getmatches(), matchadd(), " matchaddpos(), matcharg(), matchdelete(), matchstrpos() and setmatches(). -function Test_matcharg() +function Test_match() highlight MyGroup1 term=bold ctermbg=red guibg=red highlight MyGroup2 term=italic ctermbg=green guibg=green highlight MyGroup3 term=underline ctermbg=blue guibg=blue @@ -162,4 +162,28 @@ func Test_matchstrpos() call assert_equal(['', -1, -1, -1], matchstrpos(['vim', 'testing', 'execute'], 'img')) endfunc +func Test_matchaddpos() + syntax on + set hlsearch + + call setline(1, ['12345', 'NP']) + call matchaddpos('Error', [[1,2], [1,6], [2,2]]) + redraw! + call assert_notequal(screenattr(2,2), 0) + call assert_equal(screenattr(2,2), screenattr(1,2)) + call assert_notequal(screenattr(2,2), screenattr(1,6)) + 1 + call matchadd('Search', 'N\|\n') + redraw! + call assert_notequal(screenattr(2,1), 0) + call assert_equal(screenattr(2,1), screenattr(1,6)) + exec "norm! i0\" + redraw! + call assert_equal(screenattr(2,2), screenattr(1,6)) + + nohl + syntax off + set hlsearch& +endfunc + " vim: et ts=2 sw=2 diff --git a/src/nvim/version.c b/src/nvim/version.c index 0f97ad3262..a314817399 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -225,7 +225,7 @@ static int included_patches[] = { // 2220, 2219, // 2218 NA - // 2217, + 2217, // 2216 NA // 2215, // 2214 NA -- cgit From c5d2e442a34e090ed3e9294c4d1d51b3c23d8d24 Mon Sep 17 00:00:00 2001 From: Michael Ennen Date: Tue, 6 Dec 2016 17:15:49 -0700 Subject: vim-patch:7.4.2269 Problem: Using 'hlsearch' highlighting instead of matchpos if there is no search match. Solution: Pass NULL as last item to next_search_hl() when searching for 'hlsearch' match. (Shane Harper, closes vim/vim#1013) https://github.com/vim/vim/commit/e17bdffff78ebd6a4e3cff26754cc667557ea810 --- src/nvim/screen.c | 9 ++++++--- src/nvim/testdir/test_match.vim | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/nvim/screen.c b/src/nvim/screen.c index c5fe5e8b05..2b6005b484 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -2597,7 +2597,8 @@ win_line ( if (cur != NULL) { cur->pos.cur = 0; } - next_search_hl(wp, shl, lnum, (colnr_T)v, cur); + next_search_hl(wp, shl, lnum, (colnr_T)v, + shl == &search_hl ? NULL : cur); // Need to get the line again, a multi-line regexp may have made it // invalid. @@ -2926,7 +2927,8 @@ win_line ( shl->attr_cur = 0; prev_syntax_id = 0; - next_search_hl(wp, shl, lnum, (colnr_T)v, cur); + next_search_hl(wp, shl, lnum, (colnr_T)v, + shl == &search_hl ? NULL : cur); pos_inprogress = !(cur == NULL || cur->pos.cur == 0); /* Need to get the line again, a multi-line regexp @@ -5562,7 +5564,8 @@ static void prepare_search_hl(win_T *wp, linenr_T lnum) n = 0; while (shl->first_lnum < lnum && (shl->rm.regprog != NULL || (cur != NULL && pos_inprogress))) { - next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n, cur); + next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n, + shl == &search_hl ? NULL : cur); pos_inprogress = !(cur == NULL || cur->pos.cur == 0); if (shl->lnum != 0) { shl->first_lnum = shl->lnum diff --git a/src/nvim/testdir/test_match.vim b/src/nvim/testdir/test_match.vim index 67f3ea7373..ce06143bad 100644 --- a/src/nvim/testdir/test_match.vim +++ b/src/nvim/testdir/test_match.vim @@ -186,4 +186,31 @@ func Test_matchaddpos() set hlsearch& endfunc +func Test_matchaddpos_using_negative_priority() + set hlsearch + + call clearmatches() + + call setline(1, 'x') + let @/='x' + redraw! + let search_attr = screenattr(1,1) + + let @/='' + call matchaddpos('Error', [1], 10) + redraw! + let error_attr = screenattr(1,1) + + call setline(2, '-1 match priority') + call matchaddpos('Error', [2], -1) + redraw! + let negative_match_priority_attr = screenattr(2,1) + + call assert_notequal(negative_match_priority_attr, search_attr, "Match with negative priority is incorrectly highlighted with Search highlight.") + call assert_equal(negative_match_priority_attr, error_attr) + + nohl + set hlsearch& +endfunc + " vim: et ts=2 sw=2 -- cgit From 0e99d291699dc5548f891340a4abb1541041b854 Mon Sep 17 00:00:00 2001 From: Michael Ennen Date: Tue, 6 Dec 2016 17:21:12 -0700 Subject: vim-patch:8.0.0033 Problem: Cannot use overlapping positions with matchaddpos(). Solution: Check end of match. (Ozaki Kiichi) Add a test (Hirohito Higashi) https://github.com/vim/vim/commit/a6c27ee6db2c328e0ab0e6d143e2a295a0bb9c9a --- src/nvim/buffer_defs.h | 2 +- src/nvim/screen.c | 16 +++++++++------- src/nvim/testdir/test_match.vim | 10 ++++++++++ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 65ce07a172..1de74e089e 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -884,7 +884,7 @@ typedef struct { int attr; /* attributes to be used for a match */ int attr_cur; /* attributes currently active in win_line() */ linenr_T first_lnum; /* first lnum to search for multi-line pat */ - colnr_T startcol; /* in win_line() points to char where HL starts */ + colnr_T startcol; // in win_line() points to char where HL starts colnr_T endcol; // in win_line() points to char where HL ends bool is_addpos; // position specified directly by matchaddpos() proftime_T tm; // for a time limit diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 2b6005b484..ac8d14efb1 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -5563,7 +5563,7 @@ static void prepare_search_hl(win_T *wp, linenr_T lnum) // in progress n = 0; while (shl->first_lnum < lnum && (shl->rm.regprog != NULL - || (cur != NULL && pos_inprogress))) { + || (cur != NULL && pos_inprogress))) { next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n, shl == &search_hl ? NULL : cur); pos_inprogress = !(cur == NULL || cur->pos.cur == 0); @@ -5711,20 +5711,22 @@ next_search_hl_pos( shl->lnum = 0; for (i = posmatch->cur; i < MAXPOSMATCH; i++) { - if (posmatch->pos[i].lnum == 0) { + llpos_T *pos = &posmatch->pos[i]; + + if (pos->lnum == 0) { break; } - if (posmatch->pos[i].col < mincol) { + if (pos->col + pos->len - 1 <= mincol) { continue; } - if (posmatch->pos[i].lnum == lnum) { + if (pos->lnum == lnum) { if (bot != -1) { // partially sort positions by column numbers // on the same line - if (posmatch->pos[i].col < posmatch->pos[bot].col) { - llpos_T tmp = posmatch->pos[i]; + if (pos->col < posmatch->pos[bot].col) { + llpos_T tmp = *pos; - posmatch->pos[i] = posmatch->pos[bot]; + *pos = posmatch->pos[bot]; posmatch->pos[bot] = tmp; } } else { diff --git a/src/nvim/testdir/test_match.vim b/src/nvim/testdir/test_match.vim index ce06143bad..d176bf9a87 100644 --- a/src/nvim/testdir/test_match.vim +++ b/src/nvim/testdir/test_match.vim @@ -181,6 +181,16 @@ func Test_matchaddpos() redraw! call assert_equal(screenattr(2,2), screenattr(1,6)) + " Check overlapping pos + call clearmatches() + call setline(1, ['1234567890', 'NH']) + call matchaddpos('Error', [[1,1,5], [1,3,5], [2,2]]) + redraw! + call assert_notequal(screenattr(2,2), 0) + call assert_equal(screenattr(2,2), screenattr(1,5)) + call assert_equal(screenattr(2,2), screenattr(1,7)) + call assert_notequal(screenattr(2,2), screenattr(1,8)) + nohl syntax off set hlsearch& -- cgit From 63c46c11062f5c720644d9bb419f42b0a6d837c8 Mon Sep 17 00:00:00 2001 From: Michael Ennen Date: Tue, 6 Dec 2016 22:56:14 -0700 Subject: vim-patch:8.0.0040 Problem: Whole line highlighting with matchaddpos() does not work. Solution: Check for zero length. (Hirohito Higashi) https://github.com/vim/vim/commit/8507747600bddfd6a68aed057840856bf5548e61 --- src/nvim/buffer_defs.h | 14 +++++++------- src/nvim/screen.c | 38 ++++++++++++++++++++------------------ src/nvim/testdir/test_match.vim | 8 ++++++++ 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 1de74e089e..2f0e8ad974 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -877,13 +877,13 @@ struct frame_S { * match functions there is a different pattern for each window. */ typedef struct { - regmmatch_T rm; /* points to the regexp program; contains last found - match (may continue in next line) */ - buf_T *buf; /* the buffer to search for a match */ - linenr_T lnum; /* the line to search for a match */ - int attr; /* attributes to be used for a match */ - int attr_cur; /* attributes currently active in win_line() */ - linenr_T first_lnum; /* first lnum to search for multi-line pat */ + regmmatch_T rm; // points to the regexp program; contains last found + // match (may continue in next line) + buf_T *buf; // the buffer to search for a match + linenr_T lnum; // the line to search for a match + int attr; // attributes to be used for a match + int attr_cur; // attributes currently active in win_line() + linenr_T first_lnum; // first lnum to search for multi-line pat colnr_T startcol; // in win_line() points to char where HL starts colnr_T endcol; // in win_line() points to char where HL ends bool is_addpos; // position specified directly by matchaddpos() diff --git a/src/nvim/screen.c b/src/nvim/screen.c index ac8d14efb1..50517d2829 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -5698,6 +5698,8 @@ next_search_hl ( } } +/// If there is a match fill "shl" and return one. +/// Return zero otherwise. static int next_search_hl_pos( match_T *shl, // points to a match @@ -5707,7 +5709,7 @@ next_search_hl_pos( ) { int i; - int bot = -1; + int found = -1; shl->lnum = 0; for (i = posmatch->cur; i < MAXPOSMATCH; i++) { @@ -5716,41 +5718,41 @@ next_search_hl_pos( if (pos->lnum == 0) { break; } - if (pos->col + pos->len - 1 <= mincol) { + if (pos->len == 0 && pos->col < mincol) { continue; } if (pos->lnum == lnum) { - if (bot != -1) { - // partially sort positions by column numbers - // on the same line - if (pos->col < posmatch->pos[bot].col) { + if (found >= 0) { + // if this match comes before the one at "found" then swap + // them + if (pos->col < posmatch->pos[found].col) { llpos_T tmp = *pos; - *pos = posmatch->pos[bot]; - posmatch->pos[bot] = tmp; + *pos = posmatch->pos[found]; + posmatch->pos[found] = tmp; } } else { - bot = i; - shl->lnum = lnum; + found = i; } } } posmatch->cur = 0; - if (bot != -1) { - colnr_T start = posmatch->pos[bot].col == 0 - ? 0: posmatch->pos[bot].col - 1; - colnr_T end = posmatch->pos[bot].col == 0 - ? MAXCOL : start + posmatch->pos[bot].len; + if (found >= 0) { + colnr_T start = posmatch->pos[found].col == 0 + ? 0: posmatch->pos[found].col - 1; + colnr_T end = posmatch->pos[found].col == 0 + ? MAXCOL : start + posmatch->pos[found].len; + shl->lnum = lnum; shl->rm.startpos[0].lnum = 0; shl->rm.startpos[0].col = start; shl->rm.endpos[0].lnum = 0; shl->rm.endpos[0].col = end; shl->is_addpos = true; - posmatch->cur = bot + 1; - return true; + posmatch->cur = found + 1; + return 1; } - return false; + return 0; } static void screen_start_highlight(int attr) diff --git a/src/nvim/testdir/test_match.vim b/src/nvim/testdir/test_match.vim index d176bf9a87..7748dee87f 100644 --- a/src/nvim/testdir/test_match.vim +++ b/src/nvim/testdir/test_match.vim @@ -191,7 +191,15 @@ func Test_matchaddpos() call assert_equal(screenattr(2,2), screenattr(1,7)) call assert_notequal(screenattr(2,2), screenattr(1,8)) + call clearmatches() + call matchaddpos('Error', [[1], [2,2]]) + redraw! + call assert_equal(screenattr(2,2), screenattr(1,1)) + call assert_equal(screenattr(2,2), screenattr(1,10)) + call assert_notequal(screenattr(2,2), screenattr(1,11)) + nohl + call clearmatches() syntax off set hlsearch& endfunc -- cgit