This is a preliminary implementation of matchaddpos() that requires a list
of positions. See changes in matchparen.vim as example of using it. It
works fine with the new matchparen. The implementation does not involve
regexps and redraws only part of screen. Probably i missed something or
something could be done simpler...

The implementation extends struct matchitem_T adding 4 new elements:
positions pos, current position index counter cur_pos and redrawing
boundaries (top and bottom buffer lines which are calculated from pos). If
the idea of the patch is Ok then i will do some cleanup, docs etc.,
implement suggestions and send changes.

(Btw i do not understand difference between NUL and NULL, what should i use
and where?)

Cheers, Alexey.



2014-05-28 18:06 GMT+04:00 Alexey Radkov <alexey.rad...@gmail.com>:

> Thanks, now i understand it. I am making another patch...
>
>
> 2014-05-28 17:36 GMT+04:00 Павлов Николай Александрович <zyx....@gmail.com
> >:
>
> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA512
>>
>>
>>
>> On May 28, 2014 3:11:51 PM GMT+03:00, Alexey Radkov <
>> alexey.rad...@gmail.com> wrote:
>> >If a new function is involved then :3match would have explicitly
>> >different
>> >behaviour than other :match commands whereas currently it is not
>> >prohibited
>> >to use :3match for purposes besides matchparen (though it is not
>> >recommended in docs). It means that backward compatibility will be
>> >broken.
>>
>> :3match is an alias to *VimL* matchadd() function. Bram was suggesting to
>> add *VimL* matchaddpos() function. NOT change :3match behavior, but
>> introduce a new VimL function that is better suited for the purposes of
>> matchparen.
>>
>> >This patch tries to guess if :3match was called by matchparen and do
>> >not
>> >break expected behaviour when :3match was called for other purposes.
>> >But i
>> >agree that regexp heuristics looks ugly and is not so fast. Probably
>> >using
>> >a new dedicated command instead :3match will be the best solution: the
>> >new
>> >command would be implemented by the matchaddpos() function.
>> >
>> >
>> >2014-05-28 14:19 GMT+04:00 Bram Moolenaar <b...@moolenaar.net>:
>> >
>> >>
>> >> Alexey Radkov wrote:
>> >>
>> >> > Hi all.
>> >> >
>> >> > My home computer is
>> >> >
>> >> > Linux 3.14.4-200.fc20.x86_64 x86_64 x86_64 x86_64 GNU/Linux
>> >> >
>> >> > running on
>> >> >
>> >> > AMD Athlon(tm) 64 X2 Dual Core Processor 5200+
>> >> >
>> >> > Relatively old. And matchparen (I use matchparen++ but they do not
>> >> > differ a lot) may perform extremely slow in some cases. I found
>> >that
>> >> > most slow call in the plugin is 3match and tried to increase its
>> >> > performance in the attached patch.
>> >> >
>> >> > The idea of the patch:
>> >> >
>> >> > Functions match_add() and match_delete() redraw whole screen
>> >passing
>> >> > flag SOME_VALID to redraw_later(). However matchparen does not
>> >require
>> >> > that all screen must be redrawn: the positions of matching pairs
>> >are
>> >> > well known and they are passed in the pattern regexp like
>> >> > \(\%24l\%31c\)\|\(\%28l\%36c\), so they can be easily retrieved in
>> >the
>> >> > match_add()/_delete(). Another fact that hints that we are dealing
>> >> > with matchparen is id 3 (:3match is mostly solely used for
>> >matchparen
>> >> > as the vim doc says). Now we can calculate boundaries for redrawing
>> >> > area, set wp->w_buffer->b_mod_set and corresponding top and bottom
>> >> > lines numbers and finally pass VALID to redraw_later() and it
>> >should
>> >> > redraw only between the top and the bottom lines.
>> >> >
>> >> > The patch works best for specific cases:
>> >> >
>> >> > when matching pairs are located on the same line or close lines and
>> >> > terminal area is big enough (this shows best difference due to
>> >small
>> >> > redraw area to the whole terminal area large relation value).
>> >> >
>> >> > I am not sure if this patch is clean (especially when using
>> >> > wp->w_buffer->b_mod... variables).
>> >> >
>> >> > I also attached video that shows how vim compiled with this patch
>> >> > (vim.fast) faster than original vim (vim.slow) (there are two
>> >sessions
>> >> > on the video: the first is slow, the second is fast(er)).
>> >>
>> >> In my opinion this is too tricky.  It depends on the matchparen
>> >plugin
>> >> to set exactly the pattern that the code will recognize.
>> >>
>> >> Instead of this, it would be much better to add a kind of match that
>> >> doesn't work with a pattern but with the line number and column.
>> >> Perhaps also the number of characters.  That's much simpler and also
>> >> more efficient.
>> >>
>> >> Could be done by adding a matchaddpos() function, similar to
>> >matchadd()
>> >> but using a position instead of a pattern.
>> >>
>> >> Whether the match position is adjusted for inserted and deleted lines
>> >> remains to be decided.  Probably needs to be an option.
>> >>
>> >> --
>> >> hundred-and-one symptoms of being an internet addict:
>> >> 215. Your mouse-clicking forearm rivals Popeye's.
>> >>
>> >>  /// Bram Moolenaar -- b...@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
>> >>  ///
>> >>
>> >
>> >--
>> >--
>> >You received this message from the "vim_dev" maillist.
>> >Do not top-post! Type your reply below the text you are replying to.
>> >For more information, visit http://www.vim.org/maillist.php
>> >
>> >---
>> >You received this message because you are subscribed to the Google
>> >Groups "vim_dev" group.
>> >To unsubscribe from this group and stop receiving emails from it, send
>> >an email to vim_dev+unsubscr...@googlegroups.com.
>> >For more options, visit https://groups.google.com/d/optout.
>> -----BEGIN PGP SIGNATURE-----
>> Version: APG v1.1.1
>>
>> iQI1BAEBCgAfBQJTheZrGBxaeVggPHp5eC52aW1AZ21haWwuY29tPgAKCRCf3UKj
>> HhHSvtL4EACDLvhpafQvMMM5BCZn5hoNgeeps3bAf0lK4TxGOhq/dCl6OmSwapy4
>> DDuaYf14rZn1m/QGnqOLRP0cx3sHFYSGgdGFHtuDpBepRV3fVD5M72m/GStzwnfl
>> A7OX9gi2P55UdarZQ8RQhfFbBTtzlKCoXpQFIZqpRjxgSBFKyBHJpDxL1cSIC6MN
>> /kKBuaFtP4VADzTb1/FgMKeN6KUJ+QzWAPWZQDWBNX7gK64jQs9KVAbqN4EXBV03
>> +EDb1GNi5ohXmZ6cTFRqNt0EhzrK7SiwQjh1DqJXvDbyjSIUQlUAVy6qBU9EPZBL
>> yDIVJuKSUhG6AWML2dDVjF4K2e4LhLnpyTW3kjwssR1yDOo9no6Zb5hz3znF2/Qe
>> uDi0rqu53ooWLA7qO5DLZiyns+blDp/Hon140X74Fp4YRatqHXxYcEeWXY3CuKqg
>> /mgL5AJJVw5rB2HH3u/+n7PCnop73XuY0DXi6bnSPpvDaAgqQDZKrMyaVCpnGTmc
>> FEu435+7BC9ctSZwQPSKo16TWS64bYs2DVbw6DRXMuljPHLidwRodDSx+dbeNNb1
>> VY3/u+GGCZiKo9GxGOGT3QSlk8WUpmP41lXGh6oORgkTQGlKZXXtITjUH/gwY2P8
>> PZXIYYX6e+emNP9HqgvEXE6VhrjaDepEeZuf/oeTvfyyUYMLFj2V3Q==
>> =uyaE
>> -----END PGP SIGNATURE-----
>>
>> --
>> --
>> You received this message from the "vim_dev" maillist.
>> Do not top-post! Type your reply below the text you are replying to.
>> For more information, visit http://www.vim.org/maillist.php
>>
>> ---
>> You received this message because you are subscribed to the Google Groups
>> "vim_dev" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to vim_dev+unsubscr...@googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
diff -r bed71c37618c runtime/plugin/matchparen.vim
--- a/runtime/plugin/matchparen.vim	Thu May 29 14:36:29 2014 +0200
+++ b/runtime/plugin/matchparen.vim	Fri May 30 22:21:15 2014 +0400
@@ -152,8 +152,7 @@
 
   " If a match is found setup match highlighting.
   if m_lnum > 0 && m_lnum >= stoplinetop && m_lnum <= stoplinebottom 
-    exe '3match MatchParen /\(\%' . c_lnum . 'l\%' . (c_col - before) .
-	  \ 'c\)\|\(\%' . m_lnum . 'l\%' . m_col . 'c\)/'
+    call matchaddpos('MatchParen', [[c_lnum, c_col - before], [m_lnum, m_col]], 10, 3)
     let w:paren_hl_on = 1
   endif
 endfunction
diff -r bed71c37618c src/eval.c
--- a/src/eval.c	Thu May 29 14:36:29 2014 +0200
+++ b/src/eval.c	Fri May 30 22:21:15 2014 +0400
@@ -619,6 +619,7 @@
 static void f_mapcheck __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_match __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_matchadd __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_matchaddpos __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_matcharg __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_matchdelete __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_matchend __ARGS((typval_T *argvars, typval_T *rettv));
@@ -8039,6 +8040,7 @@
     {"mapcheck",	1, 3, f_mapcheck},
     {"match",		2, 4, f_match},
     {"matchadd",	2, 4, f_matchadd},
+    {"matchaddpos",	2, 4, f_matchaddpos},
     {"matcharg",	1, 1, f_matcharg},
     {"matchdelete",	1, 1, f_matchdelete},
     {"matchend",	2, 4, f_matchend},
@@ -14298,7 +14300,66 @@
 	return;
     }
 
-    rettv->vval.v_number = match_add(curwin, grp, pat, prio, id);
+    rettv->vval.v_number = match_add(curwin, grp, pat, prio, id, NULL);
+#endif
+}
+
+/*
+ * "matchaddpos()" function
+ */
+    static void
+f_matchaddpos(argvars, rettv)
+    typval_T	*argvars UNUSED;
+    typval_T	*rettv UNUSED;
+{
+#ifdef FEAT_SEARCH_EXTRA
+    char_u	buf[NUMBUFLEN];
+    char_u	*grp = get_tv_string_buf_chk(&argvars[0], buf);	/* group */
+    char_u	*pat = NULL;	/* pattern */
+    int		prio = 10;	/* default priority */
+    int		id = -1;
+    int		error = FALSE;
+    list_T	*l;
+    listitem_T	*li;
+
+    rettv->vval.v_number = -1;
+
+    if (grp == NULL)
+	return;
+
+    if (argvars[1].v_type != VAR_LIST)
+    {
+	EMSG2(_(e_listarg), "matchaddpos()");
+	return;
+    }
+    l = argvars[1].vval.v_list;
+    if (l == NULL)
+	return;
+
+    for (li = l->lv_first; li != NULL; li = li->li_next)
+    {
+	if (li->li_tv.v_type != VAR_LIST)
+	{
+	    EMSG(_(e_listreq));
+	    return;
+	}
+    }
+
+    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;
+    if (id >= 1 && id <= 2)
+    {
+	EMSGN("E798: ID is reserved for \":match\": %ld", id);
+	return;
+    }
+
+    rettv->vval.v_number = match_add(curwin, grp, NULL, prio, id, l);
 #endif
 }
 
@@ -16801,7 +16862,7 @@
 	    match_add(curwin, get_dict_string(d, (char_u *)"group", FALSE),
 		    get_dict_string(d, (char_u *)"pattern", FALSE),
 		    (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;
 	}
 	rettv->vval.v_number = 0;
diff -r bed71c37618c src/ex_docmd.c
--- a/src/ex_docmd.c	Thu May 29 14:36:29 2014 +0200
+++ b/src/ex_docmd.c	Fri May 30 22:21:15 2014 +0400
@@ -11489,7 +11489,7 @@
 
 	    c = *end;
 	    *end = NUL;
-	    match_add(curwin, g, p + 1, 10, id);
+	    match_add(curwin, g, p + 1, 10, id, NULL);
 	    vim_free(g);
 	    *end = c;
 	}
diff -r bed71c37618c src/proto/window.pro
--- a/src/proto/window.pro	Thu May 29 14:36:29 2014 +0200
+++ b/src/proto/window.pro	Fri May 30 22:21:15 2014 +0400
@@ -75,7 +75,7 @@
 void switch_buffer __ARGS((buf_T **save_curbuf, buf_T *buf));
 void restore_buffer __ARGS((buf_T *save_curbuf));
 int win_hasvertsplit __ARGS((void));
-int match_add __ARGS((win_T *wp, char_u *grp, char_u *pat, int prio, int id));
+int match_add __ARGS((win_T *wp, char_u *grp, char_u *pat, int prio, int id, list_T *pos));
 int match_delete __ARGS((win_T *wp, int id, int perr));
 void clear_matches __ARGS((win_T *wp));
 matchitem_T *get_match __ARGS((win_T *wp, int id));
diff -r bed71c37618c src/screen.c
--- a/src/screen.c	Thu May 29 14:36:29 2014 +0200
+++ b/src/screen.c	Fri May 30 22:21:15 2014 +0400
@@ -145,6 +145,7 @@
 static void init_search_hl __ARGS((win_T *wp));
 static void prepare_search_hl __ARGS((win_T *wp, linenr_T lnum));
 static void next_search_hl __ARGS((win_T *win, match_T *shl, linenr_T lnum, colnr_T mincol));
+static int next_search_hl_pos __ARGS((match_T *shl, linenr_T lnum, matchitem_T *cur));
 #endif
 static void screen_start_highlight __ARGS((int attr));
 static void screen_char __ARGS((unsigned off, int row, int col));
@@ -3439,10 +3440,11 @@
 	shl->startcol = MAXCOL;
 	shl->endcol = MAXCOL;
 	shl->attr_cur = 0;
-	if (shl->rm.regprog != NULL)
+	if (shl->rm.regprog != NULL || next_search_hl_pos(shl, lnum, cur))
 	{
 	    v = (long)(ptr - line);
-	    next_search_hl(wp, shl, lnum, (colnr_T)v);
+	    if (shl->rm.regprog != NULL)
+		next_search_hl(wp, shl, lnum, (colnr_T)v);
 
 	    /* Need to get the line again, a multi-line regexp may have made it
 	     * invalid. */
@@ -3792,7 +3794,7 @@
 		    }
 		    else
 			shl = &cur->hl;
-		    while (shl->rm.regprog != NULL)
+		    while (shl->rm.regprog != NULL || cur->cur_pos > 0)
 		    {
 			if (shl->startcol != MAXCOL
 				&& v >= (long)shl->startcol
@@ -3804,7 +3806,10 @@
 			{
 			    shl->attr_cur = 0;
 
-			    next_search_hl(wp, shl, lnum, (colnr_T)v);
+			    if (shl->rm.regprog != NULL)
+				next_search_hl(wp, shl, lnum, (colnr_T)v);
+			    else if (cur->cur_pos > 0)
+				next_search_hl_pos(shl, lnum, cur);
 
 			    /* Need to get the line again, a multi-line regexp
 			     * may have made it invalid. */
@@ -7453,6 +7458,57 @@
 }
 #endif
 
+    static int
+next_search_hl_pos(shl, lnum, cur)
+    match_T	    *shl;		/* points to search_hl or a match */
+    linenr_T	    lnum;
+    matchitem_T	    *cur;
+{
+    int	    i;
+    int     bot = -1;
+
+    shl->lnum = 0;
+    if (cur == NULL)
+	return FALSE;
+    if (cur->pos[0].col == 0)
+	goto fail;
+    for (i = cur->cur_pos; i < MAXMATCHPOS; i++)
+    {
+	if (cur->pos[i].lnum == lnum)
+	{
+	    if (shl->lnum == lnum)
+	    {
+		/* partially sort column numbers in same line */
+		if (cur->pos[i].col < cur->pos[bot].col)
+		{
+		    colnr_T	tmp = cur->pos[i].col;
+
+		    cur->pos[bot].col = cur->pos[i].col;
+		    cur->pos[i].col = tmp;
+		}
+	    }
+	    else
+	    {
+		bot = i;
+		shl->lnum = lnum;
+	    }
+	}
+    }
+    if (shl->lnum == lnum)
+    {
+	shl->rm.startpos[0].lnum = 0;
+	shl->rm.startpos[0].col = cur->pos[bot].col - 1;
+	shl->rm.endpos[0].lnum = 0;
+	shl->rm.endpos[0].col = cur->pos[bot].col;
+	cur->cur_pos = bot + 1;
+	return TRUE;
+    }
+
+fail:
+    cur->cur_pos = 0;
+    return FALSE;
+}
+
       static void
 screen_start_highlight(attr)
       int	attr;
diff -r bed71c37618c src/structs.h
--- a/src/structs.h	Thu May 29 14:36:29 2014 +0200
+++ b/src/structs.h	Fri May 30 22:21:15 2014 +0400
@@ -1927,6 +1927,7 @@
 #endif
 } match_T;
 
+#define MAXMATCHPOS 2
 /*
  * matchitem_T provides a linked list for storing match items for ":match" and
  * the match functions.
@@ -1941,6 +1942,10 @@
     int		hlg_id;	    /* highlight group ID */
     regmmatch_T	match;	    /* regexp program for pattern */
     match_T	hl;	    /* struct for doing the actual highlighting */
+    lpos_T	pos[MAXMATCHPOS];
+    int		cur_pos;
+    int		topl;
+    int		botl;
 };
 
 /*
diff -r bed71c37618c src/window.c
--- a/src/window.c	Thu May 29 14:36:29 2014 +0200
+++ b/src/window.c	Fri May 30 22:21:15 2014 +0400
@@ -6729,20 +6729,21 @@
  * Return ID of added match, -1 on failure.
  */
     int
-match_add(wp, grp, pat, prio, id)
+match_add(wp, grp, pat, prio, id, pos)
     win_T	*wp;
     char_u	*grp;
     char_u	*pat;
     int		prio;
     int		id;
+    list_T	*pos;
 {
     matchitem_T *cur;
     matchitem_T *prev;
     matchitem_T *m;
     int		hlg_id;
-    regprog_T	*regprog;
-
-    if (*grp == NUL || *pat == NUL)
+    regprog_T	*regprog = NULL;
+
+    if (*grp == NUL || (pat != NULL && *pat == NUL))
 	return -1;
     if (id < -1 || id == 0)
     {
@@ -6767,7 +6768,7 @@
 	EMSG2(_(e_nogroup), grp);
 	return -1;
     }
-    if ((regprog = vim_regcomp(pat, RE_MAGIC)) == NULL)
+    if (pat != NULL && (regprog = vim_regcomp(pat, RE_MAGIC)) == NULL)
     {
 	EMSG2(_(e_invarg2), pat);
 	return -1;
@@ -6788,7 +6789,9 @@
     m = (matchitem_T *)alloc(sizeof(matchitem_T));
     m->id = id;
     m->priority = prio;
-    m->pattern = vim_strsave(pat);
+    m->pattern = pat == NULL ? NULL : vim_strsave(pat);
+    m->pos[0].lnum = 0;
+    m->cur_pos = 0;
     m->hlg_id = hlg_id;
     m->match.regprog = regprog;
     m->match.rmm_ic = FALSE;
@@ -6809,8 +6812,71 @@
 	prev->next = m;
     m->next = cur;
 
-    redraw_later(SOME_VALID);
+    if (pos == NULL)
+	redraw_later(SOME_VALID);
+    else
+    {
+	int	    topl = 0;
+	int	    botl = 0;
+	listitem_T  *li = pos->lv_first;
+	int	    i;
+
+	for (i = 0; i < MAXMATCHPOS; i++)
+	{
+	    linenr_T	lnum;
+	    colnr_T	col;
+	    list_T	*subl;
+	    listitem_T	*subli;
+	    int		error;
+
+	    if (li == NULL)
+		goto fail;
+	    if (li->li_tv.v_type != VAR_LIST)
+		goto fail;
+	    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;
+	    if (topl == 0 || lnum < topl)
+		topl = lnum;
+	    if (botl == 0 || lnum > botl)
+		botl = lnum;
+	    subli = subli->li_next;
+	    col = get_tv_number_chk(&subli->li_tv, &error);
+	    if (error == TRUE)
+		goto fail;
+	    m->pos[i].lnum = lnum;
+	    m->pos[i].col = col;
+	    li = li->li_next;
+	}
+
+	if (wp->w_buffer->b_mod_set)
+	{
+	    if (wp->w_buffer->b_mod_top > topl)
+		wp->w_buffer->b_mod_top = topl;
+	    if (wp->w_buffer->b_mod_bot < botl)
+		wp->w_buffer->b_mod_bot = botl;
+	}
+	else
+	{
+	    wp->w_buffer->b_mod_top = topl;
+	    wp->w_buffer->b_mod_bot = botl;
+	}
+	m->topl = topl;
+	m->botl = botl;
+	wp->w_buffer->b_mod_set = TRUE;
+	redraw_later(VALID);
+    }
     return id;
+
+fail:
+    vim_free(m);
+    return -1;
 }
 
 /*
@@ -6848,10 +6914,30 @@
 	wp->w_match_head = cur->next;
     else
 	prev->next = cur->next;
-    vim_regfree(cur->match.regprog);
-    vim_free(cur->pattern);
+    if (cur->match.regprog)
+	vim_regfree(cur->match.regprog);
+    if (cur->pattern)
+	vim_free(cur->pattern);
+    if (cur->topl == 0)
+	redraw_later(SOME_VALID);
+    else
+    {
+	if (wp->w_buffer->b_mod_set)
+	{
+	    if (wp->w_buffer->b_mod_top > cur->topl)
+		wp->w_buffer->b_mod_top = cur->topl;
+	    if (wp->w_buffer->b_mod_bot < cur->botl)
+		wp->w_buffer->b_mod_bot = cur->botl;
+	}
+	else
+	{
+	    wp->w_buffer->b_mod_top = cur->topl;
+	    wp->w_buffer->b_mod_bot = cur->botl;
+	}
+	wp->w_buffer->b_mod_set = TRUE;
+	redraw_later(VALID);
+    }
     vim_free(cur);
-    redraw_later(SOME_VALID);
     return 0;
 }
 

Raspunde prin e-mail lui