1
0
forked from aniani/vim

patch 8.1.1084: cannot delete a match from another window

Problem:    Cannot delete a match from another window. (Paul Jolly)
Solution:   Add window ID argument to matchdelete(), clearmatches(),
            getmatches() and setmatches(). (Andy Massimino, closes #4178)
This commit is contained in:
Bram Moolenaar
2019-03-30 18:11:49 +01:00
parent 8bb41b3d06
commit aff749145e
4 changed files with 131 additions and 68 deletions

View File

@@ -1,4 +1,4 @@
*eval.txt* For Vim version 8.1. Last change: 2019 Mar 29 *eval.txt* For Vim version 8.1. Last change: 2019 Mar 30
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@@ -625,8 +625,11 @@ Functions that can be used with a Dictionary: >
1.5 Blobs ~ 1.5 Blobs ~
*blob* *Blob* *Blobs* *E978* *blob* *Blob* *Blobs* *E978*
A Blob mostly behaves like a |List| of numbers, where the numbers have an A Blob is a binary object. It can be used to read an image from a file and
8-bit value, from 0 to 255. send it over a channel, for example.
A Blob mostly behaves like a |List| of numbers, where each number has the
value of an 8-bit byte, from 0 to 255.
Blob creation ~ Blob creation ~
@@ -2262,7 +2265,7 @@ ch_status({handle} [, {options}])
changenr() Number current change number changenr() Number current change number
char2nr({expr} [, {utf8}]) Number ASCII/UTF8 value of first char in {expr} char2nr({expr} [, {utf8}]) Number ASCII/UTF8 value of first char in {expr}
cindent({lnum}) Number C indent for line {lnum} cindent({lnum}) Number C indent for line {lnum}
clearmatches() none clear all matches clearmatches([{win}]) none clear all matches
col({expr}) Number column nr of cursor or mark col({expr}) Number column nr of cursor or mark
complete({startcol}, {matches}) none set Insert mode completion complete({startcol}, {matches}) none set Insert mode completion
complete_add({expr}) Number add completion match complete_add({expr}) Number add completion match
@@ -2356,7 +2359,7 @@ getjumplist([{winnr} [, {tabnr}]])
getline({lnum}) String line {lnum} of current buffer getline({lnum}) String line {lnum} of current buffer
getline({lnum}, {end}) List lines {lnum} to {end} of current buffer getline({lnum}, {end}) List lines {lnum} to {end} of current buffer
getloclist({nr} [, {what}]) List list of location list items getloclist({nr} [, {what}]) List list of location list items
getmatches() List list of current matches getmatches([{win}]) List list of current matches
getpid() Number process ID of Vim getpid() Number process ID of Vim
getpos({expr}) List position of cursor, mark, etc. getpos({expr}) List position of cursor, mark, etc.
getqflist([{what}]) List list of quickfix items getqflist([{what}]) List list of quickfix items
@@ -2447,7 +2450,7 @@ matchadd({group}, {pattern} [, {priority} [, {id} [, {dict}]]])
matchaddpos({group}, {pos} [, {priority} [, {id} [, {dict}]]]) matchaddpos({group}, {pos} [, {priority} [, {id} [, {dict}]]])
Number highlight positions with {group} Number highlight positions with {group}
matcharg({nr}) List arguments of |:match| matcharg({nr}) List arguments of |:match|
matchdelete({id}) Number delete match identified by {id} matchdelete({id} [, {win}]) Number delete match identified by {id}
matchend({expr}, {pat} [, {start} [, {count}]]) matchend({expr}, {pat} [, {start} [, {count}]])
Number position where {pat} ends in {expr} Number position where {pat} ends in {expr}
matchlist({expr}, {pat} [, {start} [, {count}]]) matchlist({expr}, {pat} [, {start} [, {count}]])
@@ -2553,7 +2556,7 @@ setfperm({fname}, {mode}) Number set {fname} file permissions to {mode}
setline({lnum}, {line}) Number set line {lnum} to {line} setline({lnum}, {line}) Number set line {lnum} to {line}
setloclist({nr}, {list} [, {action} [, {what}]]) setloclist({nr}, {list} [, {action} [, {what}]])
Number modify location list using {list} Number modify location list using {list}
setmatches({list}) Number restore a list of matches setmatches({list} [, {win}]) Number restore a list of matches
setpos({expr}, {list}) Number set the {expr} position to {list} setpos({expr}, {list}) Number set the {expr} position to {list}
setqflist({list} [, {action} [, {what}]]) setqflist({list} [, {action} [, {what}]])
Number modify quickfix list using {list} Number modify quickfix list using {list}
@@ -3444,6 +3447,10 @@ char2nr({expr} [, {utf8}]) *char2nr()*
< With {utf8} set to 1, always treat as utf-8 characters. < With {utf8} set to 1, always treat as utf-8 characters.
A combining character is a separate character. A combining character is a separate character.
|nr2char()| does the opposite. |nr2char()| does the opposite.
To turn a string into a list of character numbers: >
let str = "ABC"
let list = map(split(str, '\zs'), {_, val -> char2nr(val)})
< Result: [65, 66, 67]
cindent({lnum}) *cindent()* cindent({lnum}) *cindent()*
Get the amount of indent for line {lnum} according the C Get the amount of indent for line {lnum} according the C
@@ -3454,9 +3461,11 @@ cindent({lnum}) *cindent()*
feature, -1 is returned. feature, -1 is returned.
See |C-indenting|. See |C-indenting|.
clearmatches() *clearmatches()* clearmatches([{win}]) *clearmatches()*
Clears all matches previously defined for the current window Clears all matches previously defined for the current window
by |matchadd()| and the |:match| commands. by |matchadd()| and the |:match| commands.
If {win} is specified, use the window with this number or
window ID instead of the current window.
*col()* *col()*
col({expr}) The result is a Number, which is the byte index of the column col({expr}) The result is a Number, which is the byte index of the column
@@ -5029,7 +5038,7 @@ getloclist({nr} [, {what}]) *getloclist()*
|location-list-file-window| for more |location-list-file-window| for more
details. details.
getmatches() *getmatches()* getmatches([{win}]) *getmatches()*
Returns a |List| with all matches previously defined for the Returns a |List| with all matches previously defined for the
current window by |matchadd()| and the |:match| commands. current window by |matchadd()| and the |:match| commands.
|getmatches()| is useful in combination with |setmatches()|, |getmatches()| is useful in combination with |setmatches()|,
@@ -6399,7 +6408,7 @@ matchadd({group}, {pattern} [, {priority} [, {id} [, {dict}]]])
Defines a pattern to be highlighted in the current window (a Defines a pattern to be highlighted in the current window (a
"match"). It will be highlighted with {group}. Returns an "match"). It will be highlighted with {group}. Returns an
identification number (ID), which can be used to delete the identification number (ID), which can be used to delete the
match using |matchdelete()|. match using |matchdelete()|. The ID is bound to the window.
Matching is case sensitive and magic, unless case sensitivity Matching is case sensitive and magic, unless case sensitivity
or magicness are explicitly overridden in {pattern}. The or magicness are explicitly overridden in {pattern}. The
'magic', 'smartcase' and 'ignorecase' options are not used. 'magic', 'smartcase' and 'ignorecase' options are not used.
@@ -6495,11 +6504,13 @@ matcharg({nr}) *matcharg()*
Highlighting matches using the |:match| commands are limited Highlighting matches using the |:match| commands are limited
to three matches. |matchadd()| does not have this limitation. to three matches. |matchadd()| does not have this limitation.
matchdelete({id}) *matchdelete()* *E802* *E803* matchdelete({id} [, {win}) *matchdelete()* *E802* *E803*
Deletes a match with ID {id} previously defined by |matchadd()| Deletes a match with ID {id} previously defined by |matchadd()|
or one of the |:match| commands. Returns 0 if successful, or one of the |:match| commands. Returns 0 if successful,
otherwise -1. See example for |matchadd()|. All matches can otherwise -1. See example for |matchadd()|. All matches can
be deleted in one operation by |clearmatches()|. be deleted in one operation by |clearmatches()|.
If {win} is specified, use the window with this number or
window ID instead of the current window.
matchend({expr}, {pat} [, {start} [, {count}]]) *matchend()* matchend({expr}, {pat} [, {start} [, {count}]]) *matchend()*
Same as |match()|, but return the index of first character Same as |match()|, but return the index of first character
@@ -6688,6 +6699,10 @@ nr2char({expr} [, {utf8}]) *nr2char()*
nr2char(10), because NULs are represented with newline nr2char(10), because NULs are represented with newline
characters. nr2char(0) is a real NUL and terminates the characters. nr2char(0) is a real NUL and terminates the
string, thus results in an empty string. string, thus results in an empty string.
To turn a list of character numbers into a string: >
let list = [65, 66, 67]
let str = join(map(list, {_, val -> nr2char(val)}), '')
< Result: "ABC"
or({expr}, {expr}) *or()* or({expr}, {expr}) *or()*
Bitwise OR on the two arguments. The arguments are converted Bitwise OR on the two arguments. The arguments are converted
@@ -7906,11 +7921,13 @@ setloclist({nr}, {list} [, {action} [, {what}]]) *setloclist()*
only the items listed in {what} are set. Refer to |setqflist()| only the items listed in {what} are set. Refer to |setqflist()|
for the list of supported keys in {what}. for the list of supported keys in {what}.
setmatches({list}) *setmatches()* setmatches({list} [, {win}]) *setmatches()*
Restores a list of matches saved by |getmatches() for the Restores a list of matches saved by |getmatches() for the
current window|. Returns 0 if successful, otherwise -1. All current window|. Returns 0 if successful, otherwise -1. All
current matches are cleared before the list is restored. See current matches are cleared before the list is restored. See
example for |getmatches()|. example for |getmatches()|.
If {win} is specified, use the window with this number or
window ID instead of the current window.
*setpos()* *setpos()*
setpos({expr}, {list}) setpos({expr}, {list})

View File

@@ -31,6 +31,7 @@
static char *e_listarg = N_("E686: Argument of %s must be a List"); static char *e_listarg = N_("E686: Argument of %s must be a List");
static char *e_listblobarg = N_("E899: Argument of %s must be a List or Blob"); static char *e_listblobarg = N_("E899: Argument of %s must be a List or Blob");
static char *e_stringreq = N_("E928: String required"); static char *e_stringreq = N_("E928: String required");
static char *e_invalwindow = N_("E957: Invalid window number");
#ifdef FEAT_FLOAT #ifdef FEAT_FLOAT
static void f_abs(typval_T *argvars, typval_T *rettv); static void f_abs(typval_T *argvars, typval_T *rettv);
@@ -590,7 +591,7 @@ static struct fst
{"changenr", 0, 0, f_changenr}, {"changenr", 0, 0, f_changenr},
{"char2nr", 1, 2, f_char2nr}, {"char2nr", 1, 2, f_char2nr},
{"cindent", 1, 1, f_cindent}, {"cindent", 1, 1, f_cindent},
{"clearmatches", 0, 0, f_clearmatches}, {"clearmatches", 0, 1, f_clearmatches},
{"col", 1, 1, f_col}, {"col", 1, 1, f_col},
#if defined(FEAT_INS_EXPAND) #if defined(FEAT_INS_EXPAND)
{"complete", 2, 2, f_complete}, {"complete", 2, 2, f_complete},
@@ -677,7 +678,7 @@ static struct fst
{"getjumplist", 0, 2, f_getjumplist}, {"getjumplist", 0, 2, f_getjumplist},
{"getline", 1, 2, f_getline}, {"getline", 1, 2, f_getline},
{"getloclist", 1, 2, f_getloclist}, {"getloclist", 1, 2, f_getloclist},
{"getmatches", 0, 0, f_getmatches}, {"getmatches", 0, 1, f_getmatches},
{"getpid", 0, 0, f_getpid}, {"getpid", 0, 0, f_getpid},
{"getpos", 1, 1, f_getpos}, {"getpos", 1, 1, f_getpos},
{"getqflist", 0, 1, f_getqflist}, {"getqflist", 0, 1, f_getqflist},
@@ -761,7 +762,7 @@ static struct fst
{"matchadd", 2, 5, f_matchadd}, {"matchadd", 2, 5, f_matchadd},
{"matchaddpos", 2, 5, f_matchaddpos}, {"matchaddpos", 2, 5, f_matchaddpos},
{"matcharg", 1, 1, f_matcharg}, {"matcharg", 1, 1, f_matcharg},
{"matchdelete", 1, 1, f_matchdelete}, {"matchdelete", 1, 2, f_matchdelete},
{"matchend", 2, 4, f_matchend}, {"matchend", 2, 4, f_matchend},
{"matchlist", 2, 4, f_matchlist}, {"matchlist", 2, 4, f_matchlist},
{"matchstr", 2, 4, f_matchstr}, {"matchstr", 2, 4, f_matchstr},
@@ -859,7 +860,7 @@ static struct fst
{"setfperm", 2, 2, f_setfperm}, {"setfperm", 2, 2, f_setfperm},
{"setline", 2, 2, f_setline}, {"setline", 2, 2, f_setline},
{"setloclist", 2, 4, f_setloclist}, {"setloclist", 2, 4, f_setloclist},
{"setmatches", 1, 1, f_setmatches}, {"setmatches", 1, 2, f_setmatches},
{"setpos", 2, 2, f_setpos}, {"setpos", 2, 2, f_setpos},
{"setqflist", 1, 3, f_setqflist}, {"setqflist", 1, 3, f_setqflist},
{"setreg", 2, 3, f_setreg}, {"setreg", 2, 3, f_setreg},
@@ -2496,6 +2497,23 @@ f_cindent(typval_T *argvars UNUSED, typval_T *rettv)
rettv->vval.v_number = -1; rettv->vval.v_number = -1;
} }
static win_T *
get_optional_window(typval_T *argvars, int idx)
{
win_T *win = curwin;
if (argvars[idx].v_type != VAR_UNKNOWN)
{
win = find_win_by_nr_or_id(&argvars[idx]);
if (win == NULL)
{
emsg(_(e_invalwindow));
return NULL;
}
}
return win;
}
/* /*
* "clearmatches()" function * "clearmatches()" function
*/ */
@@ -2503,7 +2521,10 @@ f_cindent(typval_T *argvars UNUSED, typval_T *rettv)
f_clearmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED) f_clearmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
{ {
#ifdef FEAT_SEARCH_EXTRA #ifdef FEAT_SEARCH_EXTRA
clear_matches(curwin); win_T *win = get_optional_window(argvars, 0);
if (win != NULL)
clear_matches(win);
#endif #endif
} }
@@ -5412,60 +5433,62 @@ f_getmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
{ {
#ifdef FEAT_SEARCH_EXTRA #ifdef FEAT_SEARCH_EXTRA
dict_T *dict; dict_T *dict;
matchitem_T *cur = curwin->w_match_head; matchitem_T *cur;
int i; int i;
win_T *win = get_optional_window(argvars, 0);
if (rettv_list_alloc(rettv) == OK) if (rettv_list_alloc(rettv) == FAIL || win == NULL)
return;
cur = win->w_match_head;
while (cur != NULL)
{ {
while (cur != NULL) dict = dict_alloc();
if (dict == NULL)
return;
if (cur->match.regprog == NULL)
{ {
dict = dict_alloc(); /* match added with matchaddpos() */
if (dict == NULL) for (i = 0; i < MAXPOSMATCH; ++i)
return;
if (cur->match.regprog == NULL)
{ {
/* match added with matchaddpos() */ llpos_T *llpos;
for (i = 0; i < MAXPOSMATCH; ++i) char buf[6];
list_T *l;
llpos = &cur->pos.pos[i];
if (llpos->lnum == 0)
break;
l = list_alloc();
if (l == NULL)
break;
list_append_number(l, (varnumber_T)llpos->lnum);
if (llpos->col > 0)
{ {
llpos_T *llpos; list_append_number(l, (varnumber_T)llpos->col);
char buf[6]; list_append_number(l, (varnumber_T)llpos->len);
list_T *l;
llpos = &cur->pos.pos[i];
if (llpos->lnum == 0)
break;
l = list_alloc();
if (l == NULL)
break;
list_append_number(l, (varnumber_T)llpos->lnum);
if (llpos->col > 0)
{
list_append_number(l, (varnumber_T)llpos->col);
list_append_number(l, (varnumber_T)llpos->len);
}
sprintf(buf, "pos%d", i + 1);
dict_add_list(dict, buf, l);
} }
sprintf(buf, "pos%d", i + 1);
dict_add_list(dict, buf, l);
} }
else
{
dict_add_string(dict, "pattern", cur->pattern);
}
dict_add_string(dict, "group", syn_id2name(cur->hlg_id));
dict_add_number(dict, "priority", (long)cur->priority);
dict_add_number(dict, "id", (long)cur->id);
# if defined(FEAT_CONCEAL)
if (cur->conceal_char)
{
char_u buf[MB_MAXBYTES + 1];
buf[(*mb_char2bytes)((int)cur->conceal_char, buf)] = NUL;
dict_add_string(dict, "conceal", (char_u *)&buf);
}
# endif
list_append_dict(rettv->vval.v_list, dict);
cur = cur->next;
} }
else
{
dict_add_string(dict, "pattern", cur->pattern);
}
dict_add_string(dict, "group", syn_id2name(cur->hlg_id));
dict_add_number(dict, "priority", (long)cur->priority);
dict_add_number(dict, "id", (long)cur->id);
# if defined(FEAT_CONCEAL)
if (cur->conceal_char)
{
char_u buf[MB_MAXBYTES + 1];
buf[(*mb_char2bytes)((int)cur->conceal_char, buf)] = NUL;
dict_add_string(dict, "conceal", (char_u *)&buf);
}
# endif
list_append_dict(rettv->vval.v_list, dict);
cur = cur->next;
} }
#endif #endif
} }
@@ -8245,7 +8268,7 @@ matchadd_dict_arg(typval_T *tv, char_u **conceal_char, win_T **win)
*win = find_win_by_nr_or_id(&di->di_tv); *win = find_win_by_nr_or_id(&di->di_tv);
if (*win == NULL) if (*win == NULL)
{ {
emsg(_("E957: Invalid window number")); emsg(_(e_invalwindow));
return FAIL; return FAIL;
} }
} }
@@ -8393,7 +8416,12 @@ f_matcharg(typval_T *argvars UNUSED, typval_T *rettv)
f_matchdelete(typval_T *argvars UNUSED, typval_T *rettv UNUSED) f_matchdelete(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
{ {
#ifdef FEAT_SEARCH_EXTRA #ifdef FEAT_SEARCH_EXTRA
rettv->vval.v_number = match_delete(curwin, win_T *win = get_optional_window(argvars, 1);
if (win == NULL)
rettv->vval.v_number = -1;
else
rettv->vval.v_number = match_delete(win,
(int)tv_get_number(&argvars[0]), TRUE); (int)tv_get_number(&argvars[0]), TRUE);
#endif #endif
} }
@@ -11206,6 +11234,7 @@ f_setmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
listitem_T *li; listitem_T *li;
dict_T *d; dict_T *d;
list_T *s = NULL; list_T *s = NULL;
win_T *win = get_optional_window(argvars, 1);
rettv->vval.v_number = -1; rettv->vval.v_number = -1;
if (argvars[0].v_type != VAR_LIST) if (argvars[0].v_type != VAR_LIST)
@@ -11213,9 +11242,11 @@ f_setmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
emsg(_(e_listreq)); emsg(_(e_listreq));
return; return;
} }
if (win == NULL)
return;
if ((l = argvars[0].vval.v_list) != NULL) if ((l = argvars[0].vval.v_list) != NULL)
{ {
/* To some extent make sure that we are dealing with a list from /* To some extent make sure that we are dealing with a list from
* "getmatches()". */ * "getmatches()". */
li = l->lv_first; li = l->lv_first;
@@ -11239,7 +11270,7 @@ f_setmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
li = li->li_next; li = li->li_next;
} }
clear_matches(curwin); clear_matches(win);
li = l->lv_first; li = l->lv_first;
while (li != NULL) while (li != NULL)
{ {
@@ -11286,13 +11317,13 @@ f_setmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
: NULL; : NULL;
if (i == 0) if (i == 0)
{ {
match_add(curwin, group, match_add(win, group,
dict_get_string(d, (char_u *)"pattern", FALSE), dict_get_string(d, (char_u *)"pattern", FALSE),
priority, id, NULL, conceal); priority, id, NULL, conceal);
} }
else else
{ {
match_add(curwin, group, NULL, priority, id, s, conceal); match_add(win, group, NULL, priority, id, s, conceal);
list_unref(s); list_unref(s);
s = NULL; s = NULL;
} }

View File

@@ -205,6 +205,19 @@ func Test_matchaddpos_otherwin()
call assert_equal(screenattr(1,2), screenattr(2,2)) call assert_equal(screenattr(1,2), screenattr(2,2))
call assert_notequal(screenattr(1,2), screenattr(1,4)) call assert_notequal(screenattr(1,2), screenattr(1,4))
let savematches = getmatches(winid)
let expect = [
\ {'group': 'Search', 'pattern': '4', 'priority': 10, 'id': 4},
\ {'group': 'Error', 'id': 5, 'priority': 10, 'pos1': [1, 2, 1], 'pos2': [2, 2, 1]},
\]
call assert_equal(expect, savematches)
call clearmatches(winid)
call assert_equal([], getmatches(winid))
call setmatches(savematches, winid)
call assert_equal(expect, savematches)
wincmd w wincmd w
bwipe! bwipe!
call clearmatches() call clearmatches()

View File

@@ -775,6 +775,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1084,
/**/ /**/
1083, 1083,
/**/ /**/