mirror of
https://github.com/neovim/neovim.git
synced 2025-09-12 06:18:16 +00:00
vim-patch: 7.4.330
Problem: Using a regexp pattern to highlight a specific position can be slow. Solution: Add matchaddpos() to highlight specific positions efficiently. (Alexey Radkov.) https://code.google.com/p/vim/source/detail?r=f9fa2e506b9f07549cd91074835c5c553db7b3a7
This commit is contained in:
@@ -880,6 +880,28 @@ typedef struct {
|
|||||||
proftime_T tm; /* for a time limit */
|
proftime_T tm; /* for a time limit */
|
||||||
} match_T;
|
} match_T;
|
||||||
|
|
||||||
|
/// number of positions supported by matchaddpos()
|
||||||
|
#define MAXPOSMATCH 8
|
||||||
|
|
||||||
|
/// Same as lpos_T, but with additional field len.
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
linenr_T lnum; ///< line number
|
||||||
|
colnr_T col; ///< column number
|
||||||
|
int len; ///< length: 0 - to the end of line
|
||||||
|
} llpos_T;
|
||||||
|
|
||||||
|
/// posmatch_T provides an array for storing match items for matchaddpos()
|
||||||
|
/// function.
|
||||||
|
typedef struct posmatch posmatch_T;
|
||||||
|
struct posmatch
|
||||||
|
{
|
||||||
|
llpos_T pos[MAXPOSMATCH]; ///< array of positions
|
||||||
|
int cur; ///< internal position counter
|
||||||
|
linenr_T toplnum; ///< top buffer line
|
||||||
|
linenr_T botlnum; ///< bottom buffer line
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* matchitem_T provides a linked list for storing match items for ":match" and
|
* matchitem_T provides a linked list for storing match items for ":match" and
|
||||||
* the match functions.
|
* the match functions.
|
||||||
@@ -892,6 +914,7 @@ struct matchitem {
|
|||||||
char_u *pattern; /* pattern to highlight */
|
char_u *pattern; /* pattern to highlight */
|
||||||
int hlg_id; /* highlight group ID */
|
int hlg_id; /* highlight group ID */
|
||||||
regmmatch_T match; /* regexp program for pattern */
|
regmmatch_T match; /* regexp program for pattern */
|
||||||
|
posmatch_T pos; // position matches
|
||||||
match_T hl; /* struct for doing the actual highlighting */
|
match_T hl; /* struct for doing the actual highlighting */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -6456,6 +6456,7 @@ static struct fst {
|
|||||||
{"mapcheck", 1, 3, f_mapcheck},
|
{"mapcheck", 1, 3, f_mapcheck},
|
||||||
{"match", 2, 4, f_match},
|
{"match", 2, 4, f_match},
|
||||||
{"matchadd", 2, 4, f_matchadd},
|
{"matchadd", 2, 4, f_matchadd},
|
||||||
|
{"matchaddpos", 2, 4, f_matchaddpos},
|
||||||
{"matcharg", 1, 1, f_matcharg},
|
{"matcharg", 1, 1, f_matcharg},
|
||||||
{"matchdelete", 1, 1, f_matchdelete},
|
{"matchdelete", 1, 1, f_matchdelete},
|
||||||
{"matchend", 2, 4, f_matchend},
|
{"matchend", 2, 4, f_matchend},
|
||||||
@@ -9300,12 +9301,34 @@ static void f_getline(typval_T *argvars, typval_T *rettv)
|
|||||||
static void f_getmatches(typval_T *argvars, typval_T *rettv)
|
static void f_getmatches(typval_T *argvars, typval_T *rettv)
|
||||||
{
|
{
|
||||||
matchitem_T *cur = curwin->w_match_head;
|
matchitem_T *cur = curwin->w_match_head;
|
||||||
|
int i;
|
||||||
|
|
||||||
rettv_list_alloc(rettv);
|
rettv_list_alloc(rettv);
|
||||||
while (cur != NULL) {
|
while (cur != NULL) {
|
||||||
dict_T *dict = dict_alloc();
|
dict_T *dict = dict_alloc();
|
||||||
dict_add_nr_str(dict, "group", 0L, syn_id2name(cur->hlg_id));
|
if (cur->match.regprog == NULL) {
|
||||||
|
// match added with matchaddpos()
|
||||||
|
for (i = 0; i < MAXPOSMATCH; ++i) {
|
||||||
|
llpos_T *llpos;
|
||||||
|
char buf[6];
|
||||||
|
|
||||||
|
llpos = &cur->pos.pos[i];
|
||||||
|
if (llpos->lnum == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
list_T *l = list_alloc();
|
||||||
|
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_nr_str(dict, "pattern", 0L, cur->pattern);
|
dict_add_nr_str(dict, "pattern", 0L, cur->pattern);
|
||||||
|
}
|
||||||
|
dict_add_nr_str(dict, "group", 0L, syn_id2name(cur->hlg_id));
|
||||||
dict_add_nr_str(dict, "priority", (long)cur->priority, NULL);
|
dict_add_nr_str(dict, "priority", (long)cur->priority, NULL);
|
||||||
dict_add_nr_str(dict, "id", (long)cur->id, NULL);
|
dict_add_nr_str(dict, "id", (long)cur->id, NULL);
|
||||||
list_append_dict(rettv->vval.v_list, dict);
|
list_append_dict(rettv->vval.v_list, dict);
|
||||||
@@ -11104,7 +11127,52 @@ static void f_matchadd(typval_T *argvars, typval_T *rettv)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rettv->vval.v_number = match_add(curwin, grp, pat, prio, id);
|
rettv->vval.v_number = match_add(curwin, grp, pat, prio, id, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void f_matchaddpos(typval_T *argvars, typval_T *rettv) FUNC_ATTR_NONNULL_ALL
|
||||||
|
{
|
||||||
|
rettv->vval.v_number = -1;
|
||||||
|
|
||||||
|
char_u buf[NUMBUFLEN];
|
||||||
|
char_u *group;
|
||||||
|
group = get_tv_string_buf_chk(&argvars[0], buf);
|
||||||
|
if (group == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argvars[1].v_type != VAR_LIST) {
|
||||||
|
EMSG2(_(e_listarg), "matchaddpos()");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_T *l;
|
||||||
|
l = argvars[1].vval.v_list;
|
||||||
|
if (l == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int error = false;
|
||||||
|
int prio = 10;
|
||||||
|
int id = -1;
|
||||||
|
|
||||||
|
if (argvars[2].v_type != VAR_UNKNOWN) {
|
||||||
|
prio = get_tv_number_chk(&argvars[2], &error);
|
||||||
|
if (argvars[3].v_type != VAR_UNKNOWN) {
|
||||||
|
id = get_tv_number_chk(&argvars[3], &error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (error == true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// id == 3 is ok because matchaddpos() is supposed to substitute :3match
|
||||||
|
if (id == 1 || id == 2) {
|
||||||
|
EMSGN("E798: ID is reserved for \"match\": %" PRId64, id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rettv->vval.v_number = match_add(curwin, group, NULL, prio, id, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -12914,7 +12982,7 @@ static void f_setmatches(typval_T *argvars, typval_T *rettv)
|
|||||||
match_add(curwin, get_dict_string(d, (char_u *)"group", FALSE),
|
match_add(curwin, get_dict_string(d, (char_u *)"group", FALSE),
|
||||||
get_dict_string(d, (char_u *)"pattern", FALSE),
|
get_dict_string(d, (char_u *)"pattern", FALSE),
|
||||||
(int)get_dict_number(d, (char_u *)"priority"),
|
(int)get_dict_number(d, (char_u *)"priority"),
|
||||||
(int)get_dict_number(d, (char_u *)"id"));
|
(int)get_dict_number(d, (char_u *)"id"), NULL);
|
||||||
li = li->li_next;
|
li = li->li_next;
|
||||||
}
|
}
|
||||||
rettv->vval.v_number = 0;
|
rettv->vval.v_number = 0;
|
||||||
|
@@ -8859,7 +8859,7 @@ static void ex_match(exarg_T *eap)
|
|||||||
|
|
||||||
c = *end;
|
c = *end;
|
||||||
*end = NUL;
|
*end = NUL;
|
||||||
match_add(curwin, g, p + 1, 10, id);
|
match_add(curwin, g, p + 1, 10, id, NULL);
|
||||||
free(g);
|
free(g);
|
||||||
*end = c;
|
*end = c;
|
||||||
}
|
}
|
||||||
|
@@ -2658,38 +2658,42 @@ win_line (
|
|||||||
shl->startcol = MAXCOL;
|
shl->startcol = MAXCOL;
|
||||||
shl->endcol = MAXCOL;
|
shl->endcol = MAXCOL;
|
||||||
shl->attr_cur = 0;
|
shl->attr_cur = 0;
|
||||||
if (shl->rm.regprog != NULL) {
|
|
||||||
v = (long)(ptr - line);
|
v = (long)(ptr - line);
|
||||||
next_search_hl(wp, shl, lnum, (colnr_T)v);
|
if (cur != NULL) {
|
||||||
|
cur->pos.cur = 0;
|
||||||
|
}
|
||||||
|
next_search_hl(wp, shl, lnum, (colnr_T)v, cur);
|
||||||
|
|
||||||
/* Need to get the line again, a multi-line regexp may have made it
|
// Need to get the line again, a multi-line regexp may have made it
|
||||||
* invalid. */
|
// invalid.
|
||||||
line = ml_get_buf(wp->w_buffer, lnum, FALSE);
|
line = ml_get_buf(wp->w_buffer, lnum, false);
|
||||||
ptr = line + v;
|
ptr = line + v;
|
||||||
|
|
||||||
if (shl->lnum != 0 && shl->lnum <= lnum) {
|
if (shl->lnum != 0 && shl->lnum <= lnum) {
|
||||||
if (shl->lnum == lnum)
|
if (shl->lnum == lnum) {
|
||||||
shl->startcol = shl->rm.startpos[0].col;
|
shl->startcol = shl->rm.startpos[0].col;
|
||||||
else
|
} else {
|
||||||
shl->startcol = 0;
|
shl->startcol = 0;
|
||||||
|
}
|
||||||
if (lnum == shl->lnum + shl->rm.endpos[0].lnum
|
if (lnum == shl->lnum + shl->rm.endpos[0].lnum
|
||||||
- shl->rm.startpos[0].lnum)
|
- shl->rm.startpos[0].lnum) {
|
||||||
shl->endcol = shl->rm.endpos[0].col;
|
shl->endcol = shl->rm.endpos[0].col;
|
||||||
else
|
} else {
|
||||||
shl->endcol = MAXCOL;
|
shl->endcol = MAXCOL;
|
||||||
/* Highlight one character for an empty match. */
|
}
|
||||||
|
// Highlight one character for an empty match.
|
||||||
if (shl->startcol == shl->endcol) {
|
if (shl->startcol == shl->endcol) {
|
||||||
if (has_mbyte && line[shl->endcol] != NUL)
|
if (has_mbyte && line[shl->endcol] != NUL) {
|
||||||
shl->endcol += (*mb_ptr2len)(line + shl->endcol);
|
shl->endcol += (*mb_ptr2len)(line + shl->endcol);
|
||||||
else
|
} else {
|
||||||
++shl->endcol;
|
++shl->endcol;
|
||||||
}
|
}
|
||||||
if ((long)shl->startcol < v) { /* match at leftcol */
|
}
|
||||||
|
if ((long)shl->startcol < v) { // match at leftcol
|
||||||
shl->attr_cur = shl->attr;
|
shl->attr_cur = shl->attr;
|
||||||
search_attr = shl->attr;
|
search_attr = shl->attr;
|
||||||
}
|
}
|
||||||
area_highlighting = TRUE;
|
area_highlighting = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (shl != &search_hl && cur != NULL)
|
if (shl != &search_hl && cur != NULL)
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
@@ -2701,7 +2705,7 @@ win_line (
|
|||||||
if (wp->w_p_cul && lnum == wp->w_cursor.lnum
|
if (wp->w_p_cul && lnum == wp->w_cursor.lnum
|
||||||
&& !(wp == curwin && VIsual_active)) {
|
&& !(wp == curwin && VIsual_active)) {
|
||||||
line_attr = hl_attr(HLF_CUL);
|
line_attr = hl_attr(HLF_CUL);
|
||||||
area_highlighting = TRUE;
|
area_highlighting = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
off = (unsigned)(current_ScreenLine - ScreenLines);
|
off = (unsigned)(current_ScreenLine - ScreenLines);
|
||||||
@@ -2942,7 +2946,13 @@ win_line (
|
|||||||
shl_flag = TRUE;
|
shl_flag = TRUE;
|
||||||
} else
|
} else
|
||||||
shl = &cur->hl;
|
shl = &cur->hl;
|
||||||
while (shl->rm.regprog != NULL) {
|
if (cur != NULL) {
|
||||||
|
cur->pos.cur = 0;
|
||||||
|
}
|
||||||
|
bool pos_inprogress = true; // mark that a position match search is
|
||||||
|
// in progress
|
||||||
|
while (shl->rm.regprog != NULL
|
||||||
|
|| (cur != NULL && pos_inprogress)) {
|
||||||
if (shl->startcol != MAXCOL
|
if (shl->startcol != MAXCOL
|
||||||
&& v >= (long)shl->startcol
|
&& v >= (long)shl->startcol
|
||||||
&& v < (long)shl->endcol) {
|
&& v < (long)shl->endcol) {
|
||||||
@@ -2950,7 +2960,8 @@ win_line (
|
|||||||
} else if (v == (long)shl->endcol) {
|
} else if (v == (long)shl->endcol) {
|
||||||
shl->attr_cur = 0;
|
shl->attr_cur = 0;
|
||||||
|
|
||||||
next_search_hl(wp, shl, lnum, (colnr_T)v);
|
next_search_hl(wp, shl, lnum, (colnr_T)v, cur);
|
||||||
|
pos_inprogress = !(cur == NULL || cur->pos.cur == 0);
|
||||||
|
|
||||||
/* Need to get the line again, a multi-line regexp
|
/* Need to get the line again, a multi-line regexp
|
||||||
* may have made it invalid. */
|
* may have made it invalid. */
|
||||||
@@ -5602,9 +5613,16 @@ static void prepare_search_hl(win_T *wp, linenr_T lnum)
|
|||||||
NULL, NULL, TRUE, NULL))
|
NULL, NULL, TRUE, NULL))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (cur != NULL) {
|
||||||
|
cur->pos.cur = 0;
|
||||||
|
}
|
||||||
|
bool pos_inprogress = true; // mark that a position match search is
|
||||||
|
// in progress
|
||||||
n = 0;
|
n = 0;
|
||||||
while (shl->first_lnum < lnum && shl->rm.regprog != NULL) {
|
while (shl->first_lnum < lnum && (shl->rm.regprog != NULL
|
||||||
next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n);
|
|| (cur != NULL && pos_inprogress))) {
|
||||||
|
next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n, cur);
|
||||||
|
pos_inprogress = !(cur == NULL || cur->pos.cur == 0);
|
||||||
if (shl->lnum != 0) {
|
if (shl->lnum != 0) {
|
||||||
shl->first_lnum = shl->lnum
|
shl->first_lnum = shl->lnum
|
||||||
+ shl->rm.endpos[0].lnum
|
+ shl->rm.endpos[0].lnum
|
||||||
@@ -5634,12 +5652,13 @@ next_search_hl (
|
|||||||
win_T *win,
|
win_T *win,
|
||||||
match_T *shl, /* points to search_hl or a match */
|
match_T *shl, /* points to search_hl or a match */
|
||||||
linenr_T lnum,
|
linenr_T lnum,
|
||||||
colnr_T mincol /* minimal column for a match */
|
colnr_T mincol, /* minimal column for a match */
|
||||||
|
matchitem_T *cur /* to retrieve match positions if any */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
linenr_T l;
|
linenr_T l;
|
||||||
colnr_T matchcol;
|
colnr_T matchcol;
|
||||||
long nmatched;
|
long nmatched = 0;
|
||||||
|
|
||||||
if (shl->lnum != 0) {
|
if (shl->lnum != 0) {
|
||||||
/* Check for three situations:
|
/* Check for three situations:
|
||||||
@@ -5693,21 +5712,24 @@ next_search_hl (
|
|||||||
matchcol = shl->rm.endpos[0].col;
|
matchcol = shl->rm.endpos[0].col;
|
||||||
|
|
||||||
shl->lnum = lnum;
|
shl->lnum = lnum;
|
||||||
nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol,
|
if (shl->rm.regprog != NULL) {
|
||||||
&(shl->tm)
|
nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol, &(shl->tm));
|
||||||
);
|
|
||||||
if (called_emsg || got_int) {
|
if (called_emsg || got_int) {
|
||||||
/* Error while handling regexp: stop using this regexp. */
|
// Error while handling regexp: stop using this regexp.
|
||||||
if (shl == &search_hl) {
|
if (shl == &search_hl) {
|
||||||
/* don't free regprog in the match list, it's a copy */
|
// don't free regprog in the match list, it's a copy
|
||||||
vim_regfree(shl->rm.regprog);
|
vim_regfree(shl->rm.regprog);
|
||||||
SET_NO_HLSEARCH(TRUE);
|
SET_NO_HLSEARCH(TRUE);
|
||||||
}
|
}
|
||||||
shl->rm.regprog = NULL;
|
shl->rm.regprog = NULL;
|
||||||
shl->lnum = 0;
|
shl->lnum = 0;
|
||||||
got_int = FALSE; /* avoid the "Type :quit to exit Vim" message */
|
got_int = FALSE; /* avoid the "Type :quit to exit Vim"
|
||||||
|
message */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if (cur != NULL) {
|
||||||
|
nmatched = next_search_hl_pos(shl, lnum, &(cur->pos), matchcol);
|
||||||
|
}
|
||||||
if (nmatched == 0) {
|
if (nmatched == 0) {
|
||||||
shl->lnum = 0; /* no match found */
|
shl->lnum = 0; /* no match found */
|
||||||
break;
|
break;
|
||||||
@@ -5722,6 +5744,59 @@ next_search_hl (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
next_search_hl_pos(
|
||||||
|
match_T *shl, // points to a match
|
||||||
|
linenr_T lnum,
|
||||||
|
posmatch_T *posmatch, // match positions
|
||||||
|
colnr_T mincol // minimal column for a match
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int bot = -1;
|
||||||
|
|
||||||
|
shl->lnum = 0;
|
||||||
|
for (i = posmatch->cur; i < MAXPOSMATCH; i++) {
|
||||||
|
if (posmatch->pos[i].lnum == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (posmatch->pos[i].col < mincol) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (posmatch->pos[i].lnum == lnum) {
|
||||||
|
if (shl->lnum == lnum) {
|
||||||
|
// 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];
|
||||||
|
|
||||||
|
posmatch->pos[i] = posmatch->pos[bot];
|
||||||
|
posmatch->pos[bot] = tmp;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bot = i;
|
||||||
|
shl->lnum = lnum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
posmatch->cur = 0;
|
||||||
|
if (shl->lnum == lnum) {
|
||||||
|
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;
|
||||||
|
|
||||||
|
shl->rm.startpos[0].lnum = 0;
|
||||||
|
shl->rm.startpos[0].col = start;
|
||||||
|
shl->rm.endpos[0].lnum = 0;
|
||||||
|
shl->rm.endpos[0].col = end;
|
||||||
|
posmatch->cur = bot + 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void screen_start_highlight(int attr)
|
static void screen_start_highlight(int attr)
|
||||||
{
|
{
|
||||||
attrentry_T *aep = NULL;
|
attrentry_T *aep = NULL;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
Test for ":match", ":2match", ":3match", "clearmatches()", "getmatches()",
|
Test for ":match", ":2match", ":3match", "clearmatches()", "getmatches()",
|
||||||
"matchadd()", "matcharg()", "matchdelete()", and "setmatches()".
|
"matchadd()", "matchaddpos()", "matcharg()", "matchdelete()", and "setmatches()".
|
||||||
|
|
||||||
STARTTEST
|
STARTTEST
|
||||||
:so small.vim
|
:so small.vim
|
||||||
@@ -147,9 +147,26 @@ STARTTEST
|
|||||||
:unlet rf1
|
:unlet rf1
|
||||||
:unlet rf2
|
:unlet rf2
|
||||||
:unlet rf3
|
:unlet rf3
|
||||||
:highlight clear MyGroup1
|
:" --- Check that "matchaddpos()" positions matches correctly
|
||||||
:highlight clear MyGroup2
|
:let @r .= "*** Test 11:\n"
|
||||||
:highlight clear MyGroup3
|
:set nolazyredraw
|
||||||
|
: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)
|
||||||
|
:let @r .= string(getmatches())."\n"
|
||||||
|
:if v1 != v5 && v6 == v1 && v8 == v5 && v10 == v5 && v11 == v1
|
||||||
|
: let @r .= "OK\n"
|
||||||
|
:else
|
||||||
|
: let @r .= "FAILED\n"
|
||||||
|
:endif
|
||||||
|
:call clearmatches()
|
||||||
G"rp
|
G"rp
|
||||||
:/^Results/,$wq! test.out
|
:/^Results/,$wq! test.out
|
||||||
ENDTEST
|
ENDTEST
|
||||||
|
@@ -9,3 +9,6 @@ Results of test63:
|
|||||||
*** Test 8: OK
|
*** Test 8: OK
|
||||||
*** Test 9: OK
|
*** Test 9: OK
|
||||||
*** Test 10: OK
|
*** Test 10: OK
|
||||||
|
*** Test 11:
|
||||||
|
[{'group': 'MyGroup1', 'id': 3, 'priority': 10, 'pos1': [1, 5, 1], 'pos2': [1, 8, 3]}]
|
||||||
|
OK
|
||||||
|
@@ -265,7 +265,7 @@ static int included_patches[] = {
|
|||||||
//333 NA
|
//333 NA
|
||||||
//332 NA
|
//332 NA
|
||||||
331,
|
331,
|
||||||
//330,
|
330,
|
||||||
329,
|
329,
|
||||||
328,
|
328,
|
||||||
327,
|
327,
|
||||||
|
@@ -5190,16 +5190,18 @@ void restore_buffer(buf_T *save_curbuf)
|
|||||||
* If no particular ID is desired, -1 must be specified for 'id'.
|
* If no particular ID is desired, -1 must be specified for 'id'.
|
||||||
* Return ID of added match, -1 on failure.
|
* Return ID of added match, -1 on failure.
|
||||||
*/
|
*/
|
||||||
int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id)
|
int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id, list_T *pos_list)
|
||||||
{
|
{
|
||||||
matchitem_T *cur;
|
matchitem_T *cur;
|
||||||
matchitem_T *prev;
|
matchitem_T *prev;
|
||||||
matchitem_T *m;
|
matchitem_T *m;
|
||||||
int hlg_id;
|
int hlg_id;
|
||||||
regprog_T *regprog;
|
regprog_T *regprog = NULL;
|
||||||
|
int rtype = SOME_VALID;
|
||||||
|
|
||||||
if (*grp == NUL || *pat == NUL)
|
if (*grp == NUL || (pat != NULL && *pat == NUL)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
if (id < -1 || id == 0) {
|
if (id < -1 || id == 0) {
|
||||||
EMSGN("E799: Invalid ID: %" PRId64
|
EMSGN("E799: Invalid ID: %" PRId64
|
||||||
" (must be greater than or equal to 1)",
|
" (must be greater than or equal to 1)",
|
||||||
@@ -5220,7 +5222,7 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id)
|
|||||||
EMSG2(_(e_nogroup), grp);
|
EMSG2(_(e_nogroup), grp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ((regprog = vim_regcomp(pat, RE_MAGIC)) == NULL) {
|
if (pat != NULL && (regprog = vim_regcomp(pat, RE_MAGIC)) == NULL) {
|
||||||
EMSG2(_(e_invarg2), pat);
|
EMSG2(_(e_invarg2), pat);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -5236,15 +5238,108 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Build new match. */
|
/* Build new match. */
|
||||||
m = xmalloc(sizeof(matchitem_T));
|
m = xcalloc(1, sizeof(matchitem_T));
|
||||||
m->id = id;
|
m->id = id;
|
||||||
m->priority = prio;
|
m->priority = prio;
|
||||||
m->pattern = vim_strsave(pat);
|
m->pattern = pat == NULL ? NULL: vim_strsave(pat);
|
||||||
|
m->pos.cur = 0;
|
||||||
m->hlg_id = hlg_id;
|
m->hlg_id = hlg_id;
|
||||||
m->match.regprog = regprog;
|
m->match.regprog = regprog;
|
||||||
m->match.rmm_ic = FALSE;
|
m->match.rmm_ic = FALSE;
|
||||||
m->match.rmm_maxcol = 0;
|
m->match.rmm_maxcol = 0;
|
||||||
|
|
||||||
|
// Set up position matches
|
||||||
|
if (pos_list != NULL)
|
||||||
|
{
|
||||||
|
linenr_T toplnum = 0;
|
||||||
|
linenr_T botlnum = 0;
|
||||||
|
listitem_T *li;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0, li = pos_list->lv_first; i < MAXPOSMATCH;
|
||||||
|
i++, li = li->li_next) {
|
||||||
|
linenr_T lnum = 0;
|
||||||
|
colnr_T col = 0;
|
||||||
|
int len = 1;
|
||||||
|
list_T *subl;
|
||||||
|
listitem_T *subli;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if (li == NULL) {
|
||||||
|
m->pos.pos[i].lnum = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (li->li_tv.v_type == VAR_LIST) {
|
||||||
|
subl = li->li_tv.vval.v_list;
|
||||||
|
if (subl == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
subli = subl->lv_first;
|
||||||
|
if (subli == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
lnum = get_tv_number_chk(&subli->li_tv, &error);
|
||||||
|
if (error == TRUE) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
m->pos.pos[i].lnum = lnum;
|
||||||
|
if (lnum == 0) {
|
||||||
|
--i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
subli = subli->li_next;
|
||||||
|
if (subli != NULL) {
|
||||||
|
col = get_tv_number_chk(&subli->li_tv, &error);
|
||||||
|
if (error == TRUE)
|
||||||
|
goto fail;
|
||||||
|
subli = subli->li_next;
|
||||||
|
if (subli != NULL) {
|
||||||
|
len = get_tv_number_chk(&subli->li_tv, &error);
|
||||||
|
if (error == true) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m->pos.pos[i].col = col;
|
||||||
|
m->pos.pos[i].len = len;
|
||||||
|
} else if (li->li_tv.v_type == VAR_NUMBER) {
|
||||||
|
if (li->li_tv.vval.v_number == 0)
|
||||||
|
continue;
|
||||||
|
m->pos.pos[i].lnum = li->li_tv.vval.v_number;
|
||||||
|
m->pos.pos[i].col = 0;
|
||||||
|
m->pos.pos[i].len = 0;
|
||||||
|
} else {
|
||||||
|
EMSG(_("List or number required"));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (toplnum == 0 || lnum < toplnum) {
|
||||||
|
toplnum = lnum;
|
||||||
|
}
|
||||||
|
if (botlnum == 0 || lnum > botlnum) {
|
||||||
|
botlnum = lnum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate top and bottom lines for redrawing area
|
||||||
|
if (toplnum != 0){
|
||||||
|
if (wp->w_buffer->b_mod_set) {
|
||||||
|
if (wp->w_buffer->b_mod_top > toplnum) {
|
||||||
|
wp->w_buffer->b_mod_top = toplnum;
|
||||||
|
}
|
||||||
|
if (wp->w_buffer->b_mod_bot < botlnum) {
|
||||||
|
wp->w_buffer->b_mod_bot = botlnum;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wp->w_buffer->b_mod_top = toplnum;
|
||||||
|
wp->w_buffer->b_mod_bot = botlnum;
|
||||||
|
}
|
||||||
|
m->pos.toplnum = toplnum;
|
||||||
|
m->pos.botlnum = botlnum;
|
||||||
|
wp->w_buffer->b_mod_set = TRUE;
|
||||||
|
rtype = VALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Insert new match. The match list is in ascending order with regard to
|
/* Insert new match. The match list is in ascending order with regard to
|
||||||
* the match priorities. */
|
* the match priorities. */
|
||||||
cur = wp->w_match_head;
|
cur = wp->w_match_head;
|
||||||
@@ -5259,8 +5354,12 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id)
|
|||||||
prev->next = m;
|
prev->next = m;
|
||||||
m->next = cur;
|
m->next = cur;
|
||||||
|
|
||||||
redraw_later(SOME_VALID);
|
redraw_later(rtype);
|
||||||
return id;
|
return id;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
free(m);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -5271,6 +5370,7 @@ int match_delete(win_T *wp, int id, int perr)
|
|||||||
{
|
{
|
||||||
matchitem_T *cur = wp->w_match_head;
|
matchitem_T *cur = wp->w_match_head;
|
||||||
matchitem_T *prev = cur;
|
matchitem_T *prev = cur;
|
||||||
|
int rtype = SOME_VALID;
|
||||||
|
|
||||||
if (id < 1) {
|
if (id < 1) {
|
||||||
if (perr == TRUE)
|
if (perr == TRUE)
|
||||||
@@ -5294,8 +5394,23 @@ int match_delete(win_T *wp, int id, int perr)
|
|||||||
prev->next = cur->next;
|
prev->next = cur->next;
|
||||||
vim_regfree(cur->match.regprog);
|
vim_regfree(cur->match.regprog);
|
||||||
free(cur->pattern);
|
free(cur->pattern);
|
||||||
|
if (cur->pos.toplnum != 0) {
|
||||||
|
if (wp->w_buffer->b_mod_set) {
|
||||||
|
if (wp->w_buffer->b_mod_top > cur->pos.toplnum) {
|
||||||
|
wp->w_buffer->b_mod_top = cur->pos.toplnum;
|
||||||
|
}
|
||||||
|
if (wp->w_buffer->b_mod_bot < cur->pos.botlnum) {
|
||||||
|
wp->w_buffer->b_mod_bot = cur->pos.botlnum;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wp->w_buffer->b_mod_top = cur->pos.toplnum;
|
||||||
|
wp->w_buffer->b_mod_bot = cur->pos.botlnum;
|
||||||
|
}
|
||||||
|
wp->w_buffer->b_mod_set = TRUE;
|
||||||
|
rtype = VALID;
|
||||||
|
}
|
||||||
free(cur);
|
free(cur);
|
||||||
redraw_later(SOME_VALID);
|
redraw_later(rtype);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user