Skip to content
Permalink
Browse files

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)
  • Loading branch information...
brammool committed Mar 30, 2019
1 parent 8bb41b3 commit aff749145e23c0f20b5158d1d3a942948ed138e3
Showing with 129 additions and 66 deletions.
  1. +29 −12 runtime/doc/eval.txt
  2. +85 −54 src/evalfunc.c
  3. +13 −0 src/testdir/test_match.vim
  4. +2 −0 src/version.c
@@ -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
@@ -625,8 +625,11 @@ Functions that can be used with a Dictionary: >

1.5 Blobs ~
*blob* *Blob* *Blobs* *E978*
A Blob mostly behaves like a |List| of numbers, where the numbers have an
8-bit value, from 0 to 255.
A Blob is a binary object. It can be used to read an image from a file and
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 ~
@@ -2262,7 +2265,7 @@ ch_status({handle} [, {options}])
changenr() Number current change number
char2nr({expr} [, {utf8}]) Number ASCII/UTF8 value of first char in {expr}
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
complete({startcol}, {matches}) none set Insert mode completion
complete_add({expr}) Number add completion match
@@ -2356,7 +2359,7 @@ getjumplist([{winnr} [, {tabnr}]])
getline({lnum}) String line {lnum} of current buffer
getline({lnum}, {end}) List lines {lnum} to {end} of current buffer
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
getpos({expr}) List position of cursor, mark, etc.
getqflist([{what}]) List list of quickfix items
@@ -2447,7 +2450,7 @@ matchadd({group}, {pattern} [, {priority} [, {id} [, {dict}]]])
matchaddpos({group}, {pos} [, {priority} [, {id} [, {dict}]]])
Number highlight positions with {group}
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}]])
Number position where {pat} ends in {expr}
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}
setloclist({nr}, {list} [, {action} [, {what}]])
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}
setqflist({list} [, {action} [, {what}]])
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.
A combining character is a separate character.
|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()*
Get the amount of indent for line {lnum} according the C
@@ -3454,9 +3461,11 @@ cindent({lnum}) *cindent()*
feature, -1 is returned.
See |C-indenting|.

clearmatches() *clearmatches()*
clearmatches([{win}]) *clearmatches()*
Clears all matches previously defined for the current window
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({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
details.

getmatches() *getmatches()*
getmatches([{win}]) *getmatches()*
Returns a |List| with all matches previously defined for the
current window by |matchadd()| and the |:match| commands.
|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
"match"). It will be highlighted with {group}. Returns an
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
or magicness are explicitly overridden in {pattern}. The
'magic', 'smartcase' and 'ignorecase' options are not used.
@@ -6495,11 +6504,13 @@ matcharg({nr}) *matcharg()*
Highlighting matches using the |:match| commands are limited
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()|
or one of the |:match| commands. Returns 0 if successful,
otherwise -1. See example for |matchadd()|. All matches can
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()*
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
characters. nr2char(0) is a real NUL and terminates the
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()*
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()|
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
current window|. Returns 0 if successful, otherwise -1. All
current matches are cleared before the list is restored. See
example for |getmatches()|.
If {win} is specified, use the window with this number or
window ID instead of the current window.

*setpos()*
setpos({expr}, {list})
@@ -31,6 +31,7 @@
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_stringreq = N_("E928: String required");
static char *e_invalwindow = N_("E957: Invalid window number");

#ifdef FEAT_FLOAT
static void f_abs(typval_T *argvars, typval_T *rettv);
@@ -590,7 +591,7 @@ static struct fst
{"changenr", 0, 0, f_changenr},
{"char2nr", 1, 2, f_char2nr},
{"cindent", 1, 1, f_cindent},
{"clearmatches", 0, 0, f_clearmatches},
{"clearmatches", 0, 1, f_clearmatches},
{"col", 1, 1, f_col},
#if defined(FEAT_INS_EXPAND)
{"complete", 2, 2, f_complete},
@@ -677,7 +678,7 @@ static struct fst
{"getjumplist", 0, 2, f_getjumplist},
{"getline", 1, 2, f_getline},
{"getloclist", 1, 2, f_getloclist},
{"getmatches", 0, 0, f_getmatches},
{"getmatches", 0, 1, f_getmatches},
{"getpid", 0, 0, f_getpid},
{"getpos", 1, 1, f_getpos},
{"getqflist", 0, 1, f_getqflist},
@@ -761,7 +762,7 @@ static struct fst
{"matchadd", 2, 5, f_matchadd},
{"matchaddpos", 2, 5, f_matchaddpos},
{"matcharg", 1, 1, f_matcharg},
{"matchdelete", 1, 1, f_matchdelete},
{"matchdelete", 1, 2, f_matchdelete},
{"matchend", 2, 4, f_matchend},
{"matchlist", 2, 4, f_matchlist},
{"matchstr", 2, 4, f_matchstr},
@@ -859,7 +860,7 @@ static struct fst
{"setfperm", 2, 2, f_setfperm},
{"setline", 2, 2, f_setline},
{"setloclist", 2, 4, f_setloclist},
{"setmatches", 1, 1, f_setmatches},
{"setmatches", 1, 2, f_setmatches},
{"setpos", 2, 2, f_setpos},
{"setqflist", 1, 3, f_setqflist},
{"setreg", 2, 3, f_setreg},
@@ -2496,14 +2497,34 @@ f_cindent(typval_T *argvars UNUSED, typval_T *rettv)
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
*/
static void
f_clearmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
{
#ifdef FEAT_SEARCH_EXTRA
clear_matches(curwin);
win_T *win = get_optional_window(argvars, 0);

if (win != NULL)
clear_matches(win);
#endif
}

@@ -5412,60 +5433,62 @@ f_getmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
{
#ifdef FEAT_SEARCH_EXTRA
dict_T *dict;
matchitem_T *cur = curwin->w_match_head;
matchitem_T *cur;
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();
if (dict == NULL)
return;
if (cur->match.regprog == NULL)
/* match added with matchaddpos() */
for (i = 0; i < MAXPOSMATCH; ++i)
{
/* match added with matchaddpos() */
for (i = 0; i < MAXPOSMATCH; ++i)
{
llpos_T *llpos;
char buf[6];
list_T *l;
llpos_T *llpos;
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)
{
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);
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);
}
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);
}
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];
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;
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
}
@@ -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);
if (*win == NULL)
{
emsg(_("E957: Invalid window number"));
emsg(_(e_invalwindow));
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)
{
#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);
#endif
}
@@ -11206,16 +11234,19 @@ f_setmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
listitem_T *li;
dict_T *d;
list_T *s = NULL;
win_T *win = get_optional_window(argvars, 1);

rettv->vval.v_number = -1;
if (argvars[0].v_type != VAR_LIST)
{
emsg(_(e_listreq));
return;
}
if (win == NULL)
return;

if ((l = argvars[0].vval.v_list) != NULL)
{

/* To some extent make sure that we are dealing with a list from
* "getmatches()". */
li = l->lv_first;
@@ -11239,7 +11270,7 @@ f_setmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
li = li->li_next;
}

clear_matches(curwin);
clear_matches(win);
li = l->lv_first;
while (li != NULL)
{
@@ -11286,13 +11317,13 @@ f_setmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
: NULL;
if (i == 0)
{
match_add(curwin, group,
match_add(win, group,
dict_get_string(d, (char_u *)"pattern", FALSE),
priority, id, NULL, conceal);
}
else
{
match_add(curwin, group, NULL, priority, id, s, conceal);
match_add(win, group, NULL, priority, id, s, conceal);
list_unref(s);
s = NULL;
}

0 comments on commit aff7491

Please sign in to comment.
You can’t perform that action at this time.