Mercurial > vim
diff src/search.c @ 11521:578df034735d v8.0.0643
patch 8.0.0643: when a pattern search is slow Vim becomes unusable
commit https://github.com/vim/vim/commit/fbd0b0af6800f6ff89857863d6a07ea03f09ff6c
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Jun 17 18:44:21 2017 +0200
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.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sat, 17 Jun 2017 18:45:04 +0200 |
parents | 9473793c7bb5 |
children | 5e36b2f825cb |
line wrap: on
line diff
--- a/src/search.c +++ b/src/search.c @@ -593,7 +593,8 @@ searchit( 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 @@ searchit( 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 @@ searchit( win, buf, lnum + matchpos.lnum, matchcol, #ifdef FEAT_RELTIME - tm + tm, timed_out #else - NULL + NULL, NULL #endif )) == 0) { @@ -922,9 +927,9 @@ searchit( win, buf, lnum + matchpos.lnum, matchcol, #ifdef FEAT_RELTIME - tm + tm, timed_out #else - NULL + NULL, NULL #endif )) == 0) break; @@ -1019,10 +1024,13 @@ searchit( * twice. */ if (!p_ws || stop_lnum != 0 || got_int || called_emsg +#ifdef FEAT_RELTIME + || (timed_out != NULL && *timed_out) +#endif #ifdef FEAT_SEARCH_EXTRA - || break_loop + || break_loop #endif - || found || loop) + || found || loop) break; /* @@ -1041,6 +1049,9 @@ searchit( ? 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 @@ do_search( 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 @@ do_search( (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 @@ current_search( 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 @@ current_search( * 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 @@ is_one_char(char_u *pattern, int move, p } 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 @@ is_one_char(char_u *pattern, int move, p { 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);