When you get bored looking at the highlighted matches, you can turn it
off with |:nohlsearch|. As soon as you use a search command, the
highlighting comes back.
+ 'redrawtime' specifies the maximum time spend on finding matches.
When the search pattern can match an end-of-line, Vim will try to
highlight all of the matched text. However, this depends on where the
search starts. This will be the first line in the window or the first
original position when no match is found and when pressing <Esc>. You
still need to finish the search command with <Enter> to move the
cursor to the match.
+ When compiled with the |+reltime| feature Vim only searches for about
+ half a second. With a complicated pattern and/or a lot of text the
+ match may not be found. This is to avoid that Vim hangs while you
+ are typing the pattern.
The highlighting can be set with the 'i' flag in 'highlight'.
See also: 'hlsearch'.
CTRL-L can be used to add one character from after the current match
{not in Vi:} When using the ":view" command the 'readonly' option is
set for the newly edited buffer.
+ *'redrawtime'* *'rdt'*
+'redrawtime' 'rdt' number (default 2000)
+ global
+ {not in Vi}
+ {only available when compiled with the |+reltime|
+ feature}
+ The time in milliseconds for redrawing the display. This applies to
+ searching for patterns for 'hlsearch' and |:match| highlighting.
+ When redrawing takes more than this many milliseconds no further
+ matches will be highlighted. This is used to avoid that Vim hangs
+ when using a very complicated pattern.
+
*'remap'* *'noremap'*
'remap' boolean (default on)
global
#endif
); ++lnum)
{
- nmatch = vim_regexec_multi(®match, curwin, curbuf, lnum, (colnr_T)0);
+ nmatch = vim_regexec_multi(®match, curwin, curbuf, lnum,
+ (colnr_T)0, NULL);
if (nmatch)
{
colnr_T copycol;
|| (do_ask && !re_lookbehind(regmatch.regprog))
|| nmatch_tl > 0
|| (nmatch = vim_regexec_multi(®match, curwin,
- curbuf, sub_firstlnum, matchcol)) == 0
+ curbuf, sub_firstlnum,
+ matchcol, NULL)) == 0
|| regmatch.startpos[0].lnum > 0)
{
if (new_start != NULL)
}
if (nmatch == -1 && !lastone)
nmatch = vim_regexec_multi(®match, curwin, curbuf,
- sub_firstlnum, matchcol);
+ sub_firstlnum, matchcol, NULL);
/*
* 5. break if there isn't another match in this line
for (lnum = eap->line1; lnum <= eap->line2 && !got_int; ++lnum)
{
/* a match on this line? */
- match = vim_regexec_multi(®match, curwin, curbuf, lnum, (colnr_T)0);
+ match = vim_regexec_multi(®match, curwin, curbuf, lnum,
+ (colnr_T)0, NULL);
if ((type == 'g' && match) || (type == 'v' && !match))
{
ml_setmarked(lnum);
curwin->w_cursor.col = 0;
searchcmdlen = 0;
if (!do_search(NULL, c, cmd, 1L,
- SEARCH_HIS + SEARCH_MSG + SEARCH_START))
+ SEARCH_HIS + SEARCH_MSG + SEARCH_START,
+ NULL))
{
curwin->w_cursor = pos;
cmd = NULL;
if (p_is && !cmd_silent && (firstc == '/' || firstc == '?'))
{
pos_T end_pos;
+#ifdef FEAT_RELTIME
+ proftime_T tm;
+#endif
/* if there is a character waiting, search and redraw later */
if (char_avail())
cursor_off(); /* so the user knows we're busy */
out_flush();
++emsg_off; /* So it doesn't beep if bad expr */
+#ifdef FEAT_RELTIME
+ /* Set the time limit to half a second. */
+ profile_setlimit(500L, &tm);
+#endif
i = do_search(NULL, firstc, ccline.cmdbuff, count,
- SEARCH_KEEP + SEARCH_OPT + SEARCH_NOOF + SEARCH_PEEK);
+ SEARCH_KEEP + SEARCH_OPT + SEARCH_NOOF + SEARCH_PEEK,
+#ifdef FEAT_RELTIME
+ &tm
+#else
+ NULL
+#endif
+ );
--emsg_off;
/* if interrupted while searching, behave like it failed */
if (got_int)
/* Search for the next match. */
i = msg_scroll;
do_search(NULL, down ? '/' : '?', ga.ga_data, 1L,
- SEARCH_MSG + SEARCH_MARK);
+ SEARCH_MSG + SEARCH_MARK, NULL);
msg_scroll = i; /* don't let an error message set msg_scroll */
}
{
regmatch.rmm_ic = FALSE;
regmatch.rmm_maxcol = 0;
- if (vim_regexec_multi(®match, curwin, curbuf, lnum, (colnr_T)0))
+ if (vim_regexec_multi(®match, curwin, curbuf, lnum,
+ (colnr_T)0, NULL))
{
pos.lnum = regmatch.endpos[0].lnum + lnum;
pos.col = regmatch.endpos[0].col;
curwin->w_set_curswant = TRUE;
i = do_search(cap->oap, dir, pat, cap->count1,
- opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG);
+ opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG, NULL);
if (i == 0)
clearop(cap->oap);
else
{"redraw", NULL, P_BOOL|P_VI_DEF,
(char_u *)NULL, PV_NONE,
{(char_u *)FALSE, (char_u *)0L}},
+ {"redrawtime", "rdt", P_NUM|P_VI_DEF,
+#ifdef FEAT_RELTIME
+ (char_u *)&p_rdt, PV_NONE,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)2000L, (char_u *)0L}},
{"remap", NULL, P_BOOL|P_VI_DEF,
(char_u *)&p_remap, PV_NONE,
{(char_u *)TRUE, (char_u *)0L}},
#ifdef FEAT_SEARCHPATH
EXTERN char_u *p_cdpath; /* 'cdpath' */
#endif
+#ifdef FEAT_RELTIME
+EXTERN long p_rdt; /* 'redrawtime' */
+#endif
EXTERN int p_remap; /* 'remap' */
EXTERN long p_report; /* 'report' */
#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
/* regexp.c */
-void free_regexp_stuff __ARGS((void));
int re_multiline __ARGS((regprog_T *prog));
int re_lookbehind __ARGS((regprog_T *prog));
char_u *skip_regexp __ARGS((char_u *startp, int dirc, int magic, char_u **newp));
regprog_T *vim_regcomp __ARGS((char_u *expr, int re_flags));
int vim_regcomp_had_eol __ARGS((void));
+void free_regexp_stuff __ARGS((void));
int vim_regexec __ARGS((regmatch_T *rmp, char_u *line, colnr_T col));
int vim_regexec_nl __ARGS((regmatch_T *rmp, char_u *line, colnr_T col));
-long vim_regexec_multi __ARGS((regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col));
+long vim_regexec_multi __ARGS((regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col, proftime_T *tm));
reg_extmatch_T *ref_extmatch __ARGS((reg_extmatch_T *em));
void unref_extmatch __ARGS((reg_extmatch_T *em));
char_u *regtilde __ARGS((char_u *source, int magic));
void set_last_search_pat __ARGS((char_u *s, int idx, int magic, int setlast));
void last_pat_prog __ARGS((regmmatch_T *regmatch));
int searchit __ARGS((win_T *win, buf_T *buf, pos_T *pos, int dir, char_u *pat, long count, int options, int pat_use, linenr_T stop_lnum, proftime_T *tm));
-int do_search __ARGS((oparg_T *oap, int dirc, char_u *pat, long count, int options));
+int do_search __ARGS((oparg_T *oap, int dirc, char_u *pat, long count, int options, proftime_T *tm));
int search_for_exact_line __ARGS((buf_T *buf, pos_T *pos, int dir, char_u *pat));
int searchc __ARGS((cmdarg_T *cap, int t_cmd));
pos_T *findmatch __ARGS((oparg_T *oap, int initc));
/* Move the cursor to the first line in the buffer */
save_cursor = curwin->w_cursor;
curwin->w_cursor.lnum = 0;
- if (!do_search(NULL, '/', qf_ptr->qf_pattern, (long)1, SEARCH_KEEP))
+ if (!do_search(NULL, '/', qf_ptr->qf_pattern, (long)1,
+ SEARCH_KEEP, NULL))
curwin->w_cursor = save_cursor;
}
{
col = 0;
while (vim_regexec_multi(®match, curwin, buf, lnum,
- col) > 0)
+ col, NULL) > 0)
{
;
if (qf_add_entry(qi, &prevp,
} save_se_T;
static char_u *reg_getline __ARGS((linenr_T lnum));
-static long vim_regexec_both __ARGS((char_u *line, colnr_T col));
+static long vim_regexec_both __ARGS((char_u *line, colnr_T col, proftime_T *tm));
static long regtry __ARGS((regprog_T *prog, colnr_T col));
static void cleanup_subexpr __ARGS((void));
#ifdef FEAT_SYN_HL
ireg_icombine = FALSE;
#endif
ireg_maxcol = 0;
- return (vim_regexec_both(line, col) != 0);
+ return (vim_regexec_both(line, col, NULL) != 0);
}
#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) \
ireg_icombine = FALSE;
#endif
ireg_maxcol = 0;
- return (vim_regexec_both(line, col) != 0);
+ return (vim_regexec_both(line, col, NULL) != 0);
}
#endif
* match otherwise.
*/
long
-vim_regexec_multi(rmp, win, buf, lnum, col)
+vim_regexec_multi(rmp, win, buf, lnum, col, tm)
regmmatch_T *rmp;
win_T *win; /* window in which to search or NULL */
buf_T *buf; /* buffer in which to search */
linenr_T lnum; /* nr of line to start looking for match */
colnr_T col; /* column to start looking for match */
+ proftime_T *tm; /* timeout limit or NULL */
{
long r;
buf_T *save_curbuf = curbuf;
/* Need to switch to buffer "buf" to make vim_iswordc() work. */
curbuf = buf;
- r = vim_regexec_both(NULL, col);
+ r = vim_regexec_both(NULL, col, tm);
curbuf = save_curbuf;
return r;
* Match a regexp against a string ("line" points to the string) or multiple
* lines ("line" is NULL, use reg_getline()).
*/
+/*ARGSUSED*/
static long
-vim_regexec_both(line, col)
+vim_regexec_both(line, col, tm)
char_u *line;
colnr_T col; /* column to start looking for match */
+ proftime_T *tm; /* timeout limit or NULL */
{
regprog_T *prog;
char_u *s;
}
else
{
+#ifdef FEAT_RELTIME
+ int tm_count = 0;
+#endif
/* Messy cases: unanchored match. */
while (!got_int)
{
else
#endif
++col;
+#ifdef FEAT_RELTIME
+ /* Check for timeout once in a twenty times to avoid overhead. */
+ if (tm != NULL && ++tm_count == 20)
+ {
+ tm_count = 0;
+ if (profile_passed_limit(tm))
+ break;
+ }
+#endif
}
}
cur->hl.buf = buf;
cur->hl.lnum = 0;
cur->hl.first_lnum = 0;
+# ifdef FEAT_RELTIME
+ /* Set the time limit to 'redrawtime'. */
+ profile_setlimit(p_rdt, &(cur->hl.tm));
+# endif
cur = cur->next;
}
search_hl.buf = buf;
search_hl.lnum = 0;
search_hl.first_lnum = 0;
+ /* time limit is set at the toplevel, for all windows */
#endif
#ifdef FEAT_LINEBREAK
{
last_pat_prog(&search_hl.rm);
search_hl.attr = hl_attr(HLF_L);
+# ifdef FEAT_RELTIME
+ /* Set the time limit to 'redrawtime'. */
+ profile_setlimit(p_rdt, &search_hl.tm);
+# endif
}
}
called_emsg = FALSE;
for (;;)
{
+#ifdef FEAT_RELTIME
+ /* Stop searching after passing the time limit. */
+ if (profile_passed_limit(&(shl->tm)))
+ {
+ shl->lnum = 0; /* no match found in time */
+ break;
+ }
+#endif
/* Three situations:
* 1. No useful previous match: search from start of line.
* 2. Not Vi compatible or empty match: continue at next character.
matchcol = shl->rm.endpos[0].col;
shl->lnum = lnum;
- nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol);
+ nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol,
+#ifdef FEAT_RELTIME
+ &(shl->tm)
+#else
+ NULL
+#endif
+ );
if (called_emsg)
{
/* Error while handling regexp: stop using this regexp. */
* Look for a match somewhere in line "lnum".
*/
nmatched = vim_regexec_multi(®match, win, buf,
- lnum, (colnr_T)0);
+ lnum, (colnr_T)0,
+#ifdef FEAT_RELTIME
+ tm
+#else
+ NULL
+#endif
+ );
/* Abort searching on an error (e.g., out of stack). */
if (called_emsg)
break;
/* match may actually be in another line when using \zs */
matchpos = regmatch.startpos[0];
endpos = regmatch.endpos[0];
-# ifdef FEAT_EVAL
+#ifdef FEAT_EVAL
submatch = first_submatch(®match);
-# endif
+#endif
/* Line me be past end of buffer for "\n\zs". */
if (lnum + matchpos.lnum > buf->b_ml.ml_line_count)
ptr = (char_u *)"";
if (ptr[matchcol] == NUL
|| (nmatched = vim_regexec_multi(®match,
win, buf, lnum + matchpos.lnum,
- matchcol)) == 0)
+ matchcol,
+#ifdef FEAT_RELTIME
+ tm
+#else
+ NULL
+#endif
+ )) == 0)
{
match_ok = FALSE;
break;
if (ptr[matchcol] == NUL
|| (nmatched = vim_regexec_multi(®match,
win, buf, lnum + matchpos.lnum,
- matchcol)) == 0)
+ matchcol,
+#ifdef FEAT_RELTIME
+ tm
+#else
+ NULL
+#endif
+ )) == 0)
break;
/* Need to get the line pointer again, a
* return 0 for failure, 1 for found, 2 for found and line offset added
*/
int
-do_search(oap, dirc, pat, count, options)
+do_search(oap, dirc, pat, count, options, tm)
oparg_T *oap; /* can be NULL */
int dirc; /* '/' or '?' */
char_u *pat;
long count;
int options;
+ proftime_T *tm; /* timeout limit or NULL */
{
pos_T pos; /* position of the last match */
char_u *searchstr;
(SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS
+ SEARCH_MSG + SEARCH_START
+ ((pat != NULL && *pat == ';') ? 0 : SEARCH_NOOF))),
- RE_LAST, (linenr_T)0, NULL);
+ RE_LAST, (linenr_T)0, tm);
if (dircp != NULL)
*dircp = dirc; /* restore second '/' or '?' for normal_cmd() */
curwin->w_cursor.lnum = 0;
while (!got_int)
{
- if (do_search(NULL, '/', frompat, 1L, SEARCH_KEEP) == 0
+ if (do_search(NULL, '/', frompat, 1L, SEARCH_KEEP, NULL) == 0
|| u_save_cursor() == FAIL)
break;
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 */
+#ifdef FEAT_RELTIME
+ proftime_T tm; /* for a time limit */
+#endif
} match_T;
/*
colnr_T col;
{
rmp->rmm_maxcol = syn_buf->b_p_smc;
- if (vim_regexec_multi(rmp, syn_win, syn_buf, lnum, col) > 0)
+ if (vim_regexec_multi(rmp, syn_win, syn_buf, lnum, col, NULL) > 0)
{
rmp->startpos[0].lnum += lnum;
rmp->endpos[0].lnum += lnum;
#endif
save_lnum = curwin->w_cursor.lnum;
curwin->w_cursor.lnum = 0; /* start search before first line */
- if (do_search(NULL, pbuf[0], pbuf + 1, (long)1, search_options))
+ if (do_search(NULL, pbuf[0], pbuf + 1, (long)1,
+ search_options, NULL))
retval = OK;
else
{
*/
p_ic = TRUE;
if (!do_search(NULL, pbuf[0], pbuf + 1, (long)1,
- search_options))
+ search_options, NULL))
{
/*
* Failed to find pattern, take a guess: "^func ("
cc = *tagp.tagname_end;
*tagp.tagname_end = NUL;
sprintf((char *)pbuf, "^%s\\s\\*(", tagp.tagname);
- if (!do_search(NULL, '/', pbuf, (long)1, search_options))
+ if (!do_search(NULL, '/', pbuf, (long)1,
+ search_options, NULL))
{
/* Guess again: "^char * \<func (" */
sprintf((char *)pbuf, "^\\[#a-zA-Z_]\\.\\*\\<%s\\s\\*(",
tagp.tagname);
if (!do_search(NULL, '/', pbuf, (long)1,
- search_options))
+ search_options, NULL))
found = 0;
}
*tagp.tagname_end = cc;
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 236,
/**/
235,
/**/
# define MB_MAXBYTES 21
#endif
+#if (defined(FEAT_PROFILE) || defined(FEAT_RELTIME)) && !defined(PROTO)
+# ifdef WIN3264
+typedef LARGE_INTEGER proftime_T;
+# else
+typedef struct timeval proftime_T;
+# endif
+#else
+typedef int proftime_T; /* dummy for function prototypes */
+#endif
+
/* Include option.h before structs.h, because the number of window-local and
* buffer-local options is used there. */
#include "option.h" /* options and default values */
# define stat(a,b) (access(a,0) ? -1 : stat(a,b))
#endif
-#if (defined(FEAT_PROFILE) || defined(FEAT_RELTIME)) && !defined(PROTO)
-# ifdef WIN3264
-typedef LARGE_INTEGER proftime_T;
-# else
-typedef struct timeval proftime_T;
-# endif
-#else
-typedef int proftime_T; /* dummy for function prototypes */
-#endif
-
#include "ex_cmds.h" /* Ex command defines */
#include "proto.h" /* function prototypes */