patch 8.0.0643: when a pattern search is slow Vim becomes unusable
Problem: When 'hlsearch' is set and matching with the last search pattern
is very slow, Vim becomes unusable. Cannot quit search by
pressing CTRL-C.
Solution: When the search times out set a flag and don't try again. Check
for timeout and CTRL-C in NFA loop that adds states.
diff --git a/src/search.c b/src/search.c
index 9470073..ac11927 100644
--- a/src/search.c
+++ b/src/search.c
@@ -593,7 +593,8 @@
int options,
int pat_use, /* which pattern to use when "pat" is empty */
linenr_T stop_lnum, /* stop after this line number when != 0 */
- proftime_T *tm UNUSED) /* timeout limit or NULL */
+ proftime_T *tm UNUSED, /* timeout limit or NULL */
+ int *timed_out UNUSED) /* set when timed out or NULL */
{
int found;
linenr_T lnum; /* no init to shut up Apollo cc */
@@ -715,13 +716,17 @@
nmatched = vim_regexec_multi(®match, win, buf,
lnum, col,
#ifdef FEAT_RELTIME
- tm
+ tm, timed_out
#else
- NULL
+ NULL, NULL
#endif
);
/* Abort searching on an error (e.g., out of stack). */
- if (called_emsg)
+ if (called_emsg
+#ifdef FEAT_RELTIME
+ || (timed_out != NULL && *timed_out)
+#endif
+ )
break;
if (nmatched > 0)
{
@@ -810,9 +815,9 @@
win, buf, lnum + matchpos.lnum,
matchcol,
#ifdef FEAT_RELTIME
- tm
+ tm, timed_out
#else
- NULL
+ NULL, NULL
#endif
)) == 0)
{
@@ -922,9 +927,9 @@
win, buf, lnum + matchpos.lnum,
matchcol,
#ifdef FEAT_RELTIME
- tm
+ tm, timed_out
#else
- NULL
+ NULL, NULL
#endif
)) == 0)
break;
@@ -1019,10 +1024,13 @@
* twice.
*/
if (!p_ws || stop_lnum != 0 || got_int || called_emsg
-#ifdef FEAT_SEARCH_EXTRA
- || break_loop
+#ifdef FEAT_RELTIME
+ || (timed_out != NULL && *timed_out)
#endif
- || found || loop)
+#ifdef FEAT_SEARCH_EXTRA
+ || break_loop
+#endif
+ || found || loop)
break;
/*
@@ -1041,6 +1049,9 @@
? top_bot_msg : bot_top_msg), TRUE);
}
if (got_int || called_emsg
+#ifdef FEAT_RELTIME
+ || (timed_out != NULL && *timed_out)
+#endif
#ifdef FEAT_SEARCH_EXTRA
|| break_loop
#endif
@@ -1147,7 +1158,8 @@
char_u *pat,
long count,
int options,
- proftime_T *tm) /* timeout limit or NULL */
+ proftime_T *tm, /* timeout limit or NULL */
+ int *timed_out) /* flag set on timeout or NULL */
{
pos_T pos; /* position of the last match */
char_u *searchstr;
@@ -1433,7 +1445,7 @@
(SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS
+ SEARCH_MSG + SEARCH_START
+ ((pat != NULL && *pat == ';') ? 0 : SEARCH_NOOF))),
- RE_LAST, (linenr_T)0, tm);
+ RE_LAST, (linenr_T)0, tm, timed_out);
if (dircp != NULL)
*dircp = dirc; /* restore second '/' or '?' for normal_cmd() */
@@ -4672,7 +4684,7 @@
result = searchit(curwin, curbuf, &pos, (dir ? FORWARD : BACKWARD),
spats[last_idx].pat, (long) (i ? count : 1),
- SEARCH_KEEP | flags, RE_SEARCH, 0, NULL);
+ SEARCH_KEEP | flags, RE_SEARCH, 0, NULL, NULL);
/* First search may fail, but then start searching from the
* beginning of the file (cursor might be on the search match)
@@ -4719,7 +4731,8 @@
* already on the next match */
if (!one_char)
result = searchit(curwin, curbuf, &pos, (forward ? FORWARD : BACKWARD),
- spats[last_idx].pat, 0L, flags | SEARCH_KEEP, RE_SEARCH, 0, NULL);
+ spats[last_idx].pat, 0L, flags | SEARCH_KEEP, RE_SEARCH, 0,
+ NULL, NULL);
if (!VIsual_active)
VIsual = start_pos;
@@ -4800,7 +4813,7 @@
}
if (searchit(curwin, curbuf, &pos, FORWARD, pattern, 1,
- SEARCH_KEEP + flag, RE_SEARCH, 0, NULL) != FAIL)
+ SEARCH_KEEP + flag, RE_SEARCH, 0, NULL, NULL) != FAIL)
{
/* Zero-width pattern should match somewhere, then we can check if
* start and end are in the same position. */
@@ -4809,7 +4822,7 @@
{
regmatch.startpos[0].col++;
nmatched = vim_regexec_multi(®match, curwin, curbuf,
- pos.lnum, regmatch.startpos[0].col, NULL);
+ pos.lnum, regmatch.startpos[0].col, NULL, NULL);
if (!nmatched)
break;
} while (regmatch.startpos[0].col < pos.col);