aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/options.txt7
-rw-r--r--src/nvim/ex_cmds.c27
-rw-r--r--src/nvim/ex_getln.c46
-rw-r--r--src/nvim/getchar.c44
-rw-r--r--src/nvim/option.h12
5 files changed, 78 insertions, 58 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index d13a245d87..1789f73aa9 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -3418,6 +3418,9 @@ A jump table for the options with a short description can be found at |Q_op|.
Works for |:substitute|, |:smagic|, |:snomagic|. |hl-Substitute|
+ If the preview is too slow (exceeds 'redrawtime') then 'inccommand' is
+ automatically disabled until |Command-line-mode| is done.
+
*'include'* *'inc'*
'include' 'inc' string (default "^\s*#\s*include")
global or local to buffer |global-local|
@@ -4733,8 +4736,8 @@ A jump table for the options with a short description can be found at |Q_op|.
global
{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.
+ Time in milliseconds for redrawing the display. Applies to
+ 'hlsearch', 'inccommand' 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.
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 66b6aa2f46..a747ead6b9 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -3100,8 +3100,6 @@ static char_u *sub_parse_flags(char_u *cmd, subflags_T *subflags,
return cmd;
}
-/// do_sub()
-///
/// Perform a substitution from line eap->line1 to line eap->line2 using the
/// command pointed to by eap->arg which should be of the form:
///
@@ -3110,7 +3108,7 @@ static char_u *sub_parse_flags(char_u *cmd, subflags_T *subflags,
/// The usual escapes are supported as described in the regexp docs.
///
/// @return buffer used for 'inccommand' preview
-buf_T *do_sub(exarg_T *eap)
+static buf_T *do_sub(exarg_T *eap)
{
long i = 0;
regmmatch_T regmatch;
@@ -3139,6 +3137,7 @@ buf_T *do_sub(exarg_T *eap)
bool endcolumn = false; // cursor in last column when done
MatchedLineVec matched_lines = KV_INITIAL_VALUE;
pos_T old_cursor = curwin->w_cursor;
+ proftime_T timeout = eap->is_live ? profile_setlimit(p_rdt) : profile_zero();
int start_nsubs;
int save_ma = 0;
int save_b_changed = curbuf->b_changed;
@@ -3581,7 +3580,7 @@ buf_T *do_sub(exarg_T *eap)
|| typed == intr_char
#endif
) {
- got_quit = TRUE;
+ got_quit = true;
break;
}
if (typed == 'n')
@@ -3882,6 +3881,10 @@ skip:
}
line_breakcheck();
+
+ if (profile_passed_limit(timeout)) {
+ got_quit = true;
+ }
}
if (first_line != 0) {
@@ -3949,9 +3952,14 @@ skip:
// Show 'inccommand' preview if there are matched lines.
buf_T *preview_buf = NULL;
- if (eap->is_live && *p_icm != NUL && matched_lines.size != 0 && pat != NULL) {
- curbuf->b_changed = save_b_changed; // preserve 'modified' during preview
- preview_buf = show_sub(eap, old_cursor, pat, sub, &matched_lines);
+ if (eap->is_live && !aborting()) {
+ if (got_quit) { // Substitution is too slow, disable 'inccommand'.
+ set_string_option_direct((char_u *)"icm", -1, (char_u *)"", OPT_FREE,
+ SID_NONE);
+ } else if (*p_icm != NUL && matched_lines.size != 0 && pat != NULL) {
+ curbuf->b_changed = save_b_changed; // preserve 'modified' during preview
+ preview_buf = show_sub(eap, old_cursor, pat, sub, &matched_lines);
+ }
}
for (MatchedLine m; kv_size(matched_lines);) {
@@ -6017,7 +6025,8 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, char_u *pat, char_u *sub,
cmdmod.tab = 0; // disable :tab modifier
cmdmod.noswapfile = true; // disable swap for preview buffer
// disable file info message
- set_option_value((char_u *)"shm", 0L, (char_u *)"F", 0);
+ set_string_option_direct((char_u *)"shm", -1, (char_u *)"F", OPT_FREE,
+ SID_NONE);
bool outside_curline = (eap->line1 != old_cusr.lnum
|| eap->line2 != old_cusr.lnum);
@@ -6096,7 +6105,7 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, char_u *pat, char_u *sub,
win_size_restore(&save_winsizes);
ga_clear(&save_winsizes);
- set_option_value((char_u *)"shm", 0L, save_shm_p, 0);
+ set_string_option_direct((char_u *)"shm", -1, save_shm_p, OPT_FREE, SID_NONE);
xfree(save_shm_p);
// Update screen now. Must do this _before_ close_windows().
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index c4169f03f0..3093caebaf 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -95,19 +95,21 @@ typedef struct command_line_state {
char_u *lookfor; // string to match
int hiscnt; // current history line in use
int histype; // history type to be used
- pos_T old_cursor;
- colnr_T old_curswant;
- colnr_T old_leftcol;
- linenr_T old_topline;
- int old_topfill;
- linenr_T old_botline;
+ pos_T old_cursor;
+ colnr_T old_curswant;
+ colnr_T old_leftcol;
+ linenr_T old_topline;
+ int old_topfill;
+ linenr_T old_botline;
int did_incsearch;
int incsearch_postponed;
+ bool live; // performing 'inccommand' preview
int did_wild_list; // did wild_list() recently
int wim_index; // index in wim_flags[]
int res;
- int save_msg_scroll;
- int save_State; // remember State when called
+ int save_msg_scroll;
+ int save_State; // remember State when called
+ char_u *save_p_icm;
int some_key_typed; // one of the keys was typed
// mouse drag and release events are ignored, unless they are
// preceded with a mouse down event
@@ -159,6 +161,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
s->indent = indent;
s->save_msg_scroll = msg_scroll;
s->save_State = State;
+ s->save_p_icm = vim_strsave(p_icm);
s->ignore_drag_release = true;
if (s->firstc == -1) {
@@ -323,9 +326,12 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
need_wait_return = false;
}
+ set_string_option_direct((char_u *)"icm", -1, s->save_p_icm, OPT_FREE,
+ SID_NONE);
State = s->save_State;
setmouse();
ui_cursor_shape(); // may show different cursor shape
+ xfree(s->save_p_icm);
{
char_u *p = ccline.cmdbuff;
@@ -394,7 +400,8 @@ static int command_line_execute(VimState *state, int key)
if ((s->c == Ctrl_C)
&& s->firstc != '@'
&& !s->break_ctrl_c
- && !global_busy) {
+ && !global_busy
+ && !cmd_is_live(ccline.cmdbuff)) {
got_int = false;
}
@@ -981,7 +988,6 @@ static int command_line_handle_key(CommandLineState *s)
status_redraw_curbuf();
return command_line_not_changed(s);
- // case '@': only in very old vi
case Ctrl_U:
// delete all characters left of the cursor
s->j = ccline.cmdpos;
@@ -996,7 +1002,6 @@ static int command_line_handle_key(CommandLineState *s)
redrawcmd();
return command_line_changed(s);
-
case ESC: // get here if p_wc != ESC or when ESC typed twice
case Ctrl_C:
// In exmode it doesn't make sense to return. Except when
@@ -1489,11 +1494,11 @@ static int command_line_handle_key(CommandLineState *s)
static int command_line_not_changed(CommandLineState *s)
{
- // This part implements incremental searches for "/" and "?" Jump to
- // cmdline_not_changed when a character has been read but the command line
- // did not change. Then we only search and redraw if something changed in
- // the past. Jump to cmdline_changed when the command line did change.
- // (Sorry for the goto's, I know it is ugly).
+ // Incremental searches for "/" and "?":
+ // Enter command_line_not_changed() when a character has been read but the
+ // command line did not change. Then we only search and redraw if something
+ // changed in the past.
+ // Enter command_line_changed() when the command line did change.
if (!s->incsearch_postponed) {
return 1;
}
@@ -1592,11 +1597,13 @@ static int command_line_changed(CommandLineState *s)
redrawcmdline();
s->did_incsearch = true;
} else if (s->firstc == ':'
- && KeyTyped // only if interactive
+ && current_SID == 0 // only if interactive
&& *p_icm != NUL // 'inccommand' is set
&& curbuf->b_p_ma // buffer is modifiable
&& cmdline_star == 0 // not typing a password
- && cmd_is_live(ccline.cmdbuff)) {
+ && cmd_is_live(ccline.cmdbuff)
+ && !vpeekc_any()) {
+ s->live = true;
// process a "live" command ('inccommand')
do_cmdline(ccline.cmdbuff, NULL, NULL, DOCMD_KEEPLINE|DOCMD_LIVE);
@@ -1610,6 +1617,9 @@ static int command_line_changed(CommandLineState *s)
update_topline();
redrawcmdline();
+ } else if (s->live) {
+ s->live = false;
+ update_screen(SOME_VALID); // Clear 'inccommand' preview.
}
if (cmdmsg_rl || (p_arshape && !p_tbidi && enc_utf8)) {
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index dad0ac33cd..ab52ee0372 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -1583,29 +1583,27 @@ vungetc ( /* unget one character (can only be done once!) */
old_mouse_col = mouse_col;
}
-/*
- * get a character:
- * 1. from the stuffbuffer
- * This is used for abbreviated commands like "D" -> "d$".
- * Also used to redo a command for ".".
- * 2. from the typeahead buffer
- * Stores text obtained previously but not used yet.
- * Also stores the result of mappings.
- * Also used for the ":normal" command.
- * 3. from the user
- * This may do a blocking wait if "advance" is TRUE.
- *
- * if "advance" is TRUE (vgetc()):
- * really get the character.
- * KeyTyped is set to TRUE in the case the user typed the key.
- * KeyStuffed is TRUE if the character comes from the stuff buffer.
- * if "advance" is FALSE (vpeekc()):
- * just look whether there is a character available.
- *
- * When "no_mapping" is zero, checks for mappings in the current mode.
- * Only returns one byte (of a multi-byte character).
- * K_SPECIAL and CSI may be escaped, need to get two more bytes then.
- */
+/// get a character:
+/// 1. from the stuffbuffer
+/// This is used for abbreviated commands like "D" -> "d$".
+/// Also used to redo a command for ".".
+/// 2. from the typeahead buffer
+/// Stores text obtained previously but not used yet.
+/// Also stores the result of mappings.
+/// Also used for the ":normal" command.
+/// 3. from the user
+/// This may do a blocking wait if "advance" is TRUE.
+///
+/// if "advance" is TRUE (vgetc()):
+/// really get the character.
+/// KeyTyped is set to TRUE in the case the user typed the key.
+/// KeyStuffed is TRUE if the character comes from the stuff buffer.
+/// if "advance" is FALSE (vpeekc()):
+/// just look whether there is a character available.
+///
+/// When "no_mapping" is zero, checks for mappings in the current mode.
+/// Only returns one byte (of a multi-byte character).
+/// K_SPECIAL and CSI may be escaped, need to get two more bytes then.
static int vgetorpeek(int advance)
{
int c, c1;
diff --git a/src/nvim/option.h b/src/nvim/option.h
index cf167cdd2c..60f14dea44 100644
--- a/src/nvim/option.h
+++ b/src/nvim/option.h
@@ -13,12 +13,12 @@
/// When OPT_GLOBAL and OPT_LOCAL are both missing, set both local and global
/// values, get local value.
typedef enum {
- OPT_FREE = 1, ///< Free old value if it was allocated.
- OPT_GLOBAL = 2, ///< Use global value.
- OPT_LOCAL = 4, ///< Use local value.
- OPT_MODELINE = 8, ///< Option in modeline.
- OPT_WINONLY = 16, ///< Only set window-local options.
- OPT_NOWIN = 32, ///< Don’t set window-local options.
+ OPT_FREE = 1, ///< Free old value if it was allocated.
+ OPT_GLOBAL = 2, ///< Use global value.
+ OPT_LOCAL = 4, ///< Use local value.
+ OPT_MODELINE = 8, ///< Option in modeline.
+ OPT_WINONLY = 16, ///< Only set window-local options.
+ OPT_NOWIN = 32, ///< Don’t set window-local options.
} OptionFlags;
#ifdef INCLUDE_GENERATED_DECLARATIONS