Merge #5607 from justinmk/icm

'inccommand': auto-disable if too slow; fix other behaviors
This commit is contained in:
Justin M. Keyes 2016-11-15 09:12:47 +01:00 committed by GitHub
commit 01ef6fc3d2
12 changed files with 30836 additions and 132 deletions

View File

@ -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| 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'*
'include' 'inc' string (default "^\s*#\s*include") 'include' 'inc' string (default "^\s*#\s*include")
global or local to buffer |global-local| 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 global
{only available when compiled with the |+reltime| {only available when compiled with the |+reltime|
feature} feature}
The time in milliseconds for redrawing the display. This applies to Time in milliseconds for redrawing the display. Applies to
searching for patterns for 'hlsearch' and |:match| highlighting. 'hlsearch', 'inccommand' and |:match| highlighting.
When redrawing takes more than this many milliseconds no further When redrawing takes more than this many milliseconds no further
matches will be highlighted. This is used to avoid that Vim hangs matches will be highlighted. This is used to avoid that Vim hangs
when using a very complicated pattern. when using a very complicated pattern.

View File

@ -2952,10 +2952,11 @@ void sub_set_replacement(SubReplacementString sub)
/// @param[in] pat Search pattern /// @param[in] pat Search pattern
/// @param[in] sub Replacement string /// @param[in] sub Replacement string
/// @param[in] cmd Command from :s_flags /// @param[in] cmd Command from :s_flags
/// @param[in] save Save pattern to options, history
/// ///
/// @returns true if :substitute can be replaced with a join command /// @returns true if :substitute can be replaced with a join command
static bool sub_joining_lines(exarg_T *eap, char_u *pat, static bool sub_joining_lines(exarg_T *eap, char_u *pat, char_u *sub,
char_u *sub, char_u *cmd) char_u *cmd, bool save)
FUNC_ATTR_NONNULL_ARG(1, 3, 4) FUNC_ATTR_NONNULL_ARG(1, 3, 4)
{ {
// TODO(vim): find a generic solution to make line-joining operations more // TODO(vim): find a generic solution to make line-joining operations more
@ -2989,7 +2990,7 @@ static bool sub_joining_lines(exarg_T *eap, char_u *pat,
ex_may_print(eap); ex_may_print(eap);
} }
if (!eap->is_live) { if (save) {
if (!cmdmod.keeppatterns) { if (!cmdmod.keeppatterns) {
save_re_pat(RE_SUBST, pat, p_magic); save_re_pat(RE_SUBST, pat, p_magic);
} }
@ -3100,8 +3101,6 @@ static char_u *sub_parse_flags(char_u *cmd, subflags_T *subflags,
return cmd; return cmd;
} }
/// do_sub()
///
/// Perform a substitution from line eap->line1 to line eap->line2 using the /// 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: /// command pointed to by eap->arg which should be of the form:
/// ///
@ -3110,7 +3109,7 @@ static char_u *sub_parse_flags(char_u *cmd, subflags_T *subflags,
/// The usual escapes are supported as described in the regexp docs. /// The usual escapes are supported as described in the regexp docs.
/// ///
/// @return buffer used for 'inccommand' preview /// @return buffer used for 'inccommand' preview
buf_T *do_sub(exarg_T *eap) static buf_T *do_sub(exarg_T *eap, proftime_T timeout)
{ {
long i = 0; long i = 0;
regmmatch_T regmatch; regmmatch_T regmatch;
@ -3142,6 +3141,7 @@ buf_T *do_sub(exarg_T *eap)
int start_nsubs; int start_nsubs;
int save_ma = 0; int save_ma = 0;
int save_b_changed = curbuf->b_changed; int save_b_changed = curbuf->b_changed;
bool preview = (State & CMDPREVIEW);
if (!global_busy) { if (!global_busy) {
sub_nsubs = 0; sub_nsubs = 0;
@ -3209,7 +3209,7 @@ buf_T *do_sub(exarg_T *eap)
mb_ptr_adv(cmd); mb_ptr_adv(cmd);
} }
if (!eap->skip && !eap->is_live) { if (!eap->skip && !preview) {
sub_set_replacement((SubReplacementString) { sub_set_replacement((SubReplacementString) {
.sub = xstrdup((char *) sub), .sub = xstrdup((char *) sub),
.timestamp = os_time(), .timestamp = os_time(),
@ -3229,7 +3229,7 @@ buf_T *do_sub(exarg_T *eap)
endcolumn = (curwin->w_curswant == MAXCOL); endcolumn = (curwin->w_curswant == MAXCOL);
} }
if (sub_joining_lines(eap, pat, sub, cmd)) { if (sub_joining_lines(eap, pat, sub, cmd, !preview)) {
return NULL; return NULL;
} }
@ -3274,7 +3274,7 @@ buf_T *do_sub(exarg_T *eap)
return NULL; return NULL;
} }
if (search_regcomp(pat, RE_SUBST, which_pat, (eap->is_live ? 0 : SEARCH_HIS), if (search_regcomp(pat, RE_SUBST, which_pat, (preview ? 0 : SEARCH_HIS),
&regmatch) == FAIL) { &regmatch) == FAIL) {
if (subflags.do_error) { if (subflags.do_error) {
EMSG(_(e_invcmd)); EMSG(_(e_invcmd));
@ -3404,7 +3404,7 @@ buf_T *do_sub(exarg_T *eap)
curwin->w_cursor.lnum = lnum; curwin->w_cursor.lnum = lnum;
do_again = FALSE; do_again = FALSE;
if (eap->is_live) { if (preview) {
// Increment the in-line match count and store the column. // Increment the in-line match count and store the column.
matched_line.nmatch++; matched_line.nmatch++;
kv_push(matched_line.cols, regmatch.startpos[0].col); kv_push(matched_line.cols, regmatch.startpos[0].col);
@ -3457,7 +3457,7 @@ buf_T *do_sub(exarg_T *eap)
goto skip; goto skip;
} }
if (subflags.do_ask && !eap->is_live) { if (subflags.do_ask && !preview) {
int typed = 0; int typed = 0;
/* change State to CONFIRM, so that the mouse works /* change State to CONFIRM, so that the mouse works
@ -3581,7 +3581,7 @@ buf_T *do_sub(exarg_T *eap)
|| typed == intr_char || typed == intr_char
#endif #endif
) { ) {
got_quit = TRUE; got_quit = true;
break; break;
} }
if (typed == 'n') if (typed == 'n')
@ -3628,9 +3628,9 @@ buf_T *do_sub(exarg_T *eap)
* use "\=col("."). */ * use "\=col("."). */
curwin->w_cursor.col = regmatch.startpos[0].col; curwin->w_cursor.col = regmatch.startpos[0].col;
// 3. Substitute the string. During 'inccommand' only do this if there // 3. Substitute the string. During 'inccommand' preview only do this if
// is a replace pattern. // there is a replace pattern.
if (!eap->is_live || has_second_delim) { if (!preview || has_second_delim) {
if (subflags.do_count) { if (subflags.do_count) {
// prevent accidentally changing the buffer by a function // prevent accidentally changing the buffer by a function
save_ma = curbuf->b_p_ma; save_ma = curbuf->b_p_ma;
@ -3874,7 +3874,7 @@ skip:
xfree(sub_firstline); /* free the copy of the original line */ xfree(sub_firstline); /* free the copy of the original line */
sub_firstline = NULL; sub_firstline = NULL;
if (eap->is_live) { if (preview) {
matched_line.lnum = lnum; matched_line.lnum = lnum;
matched_line.line = vim_strsave(ml_get(lnum)); matched_line.line = vim_strsave(ml_get(lnum));
kv_push(matched_lines, matched_line); kv_push(matched_lines, matched_line);
@ -3882,6 +3882,10 @@ skip:
} }
line_breakcheck(); line_breakcheck();
if (profile_passed_limit(timeout)) {
got_quit = true;
}
} }
if (first_line != 0) { if (first_line != 0) {
@ -3914,7 +3918,7 @@ skip:
beginline(BL_WHITE | BL_FIX); beginline(BL_WHITE | BL_FIX);
} }
} }
if (!eap->is_live && !do_sub_msg(subflags.do_count) && subflags.do_ask) { if (!preview && !do_sub_msg(subflags.do_count) && subflags.do_ask) {
MSG(""); MSG("");
} }
} else { } else {
@ -3949,9 +3953,14 @@ skip:
// Show 'inccommand' preview if there are matched lines. // Show 'inccommand' preview if there are matched lines.
buf_T *preview_buf = NULL; buf_T *preview_buf = NULL;
if (eap->is_live && *p_icm != NUL && matched_lines.size != 0 && pat != NULL) { if (preview && !aborting()) {
curbuf->b_changed = save_b_changed; // preserve 'modified' during preview if (got_quit) { // Substitution is too slow, disable 'inccommand'.
preview_buf = show_sub(eap, old_cursor, pat, sub, &matched_lines); 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);) { for (MatchedLine m; kv_size(matched_lines);) {
@ -6004,7 +6013,6 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, char_u *pat, char_u *sub,
{ {
static handle_T bufnr = 0; // special buffer, re-used on each visit static handle_T bufnr = 0; // special buffer, re-used on each visit
garray_T save_winsizes;
win_T *save_curwin = curwin; win_T *save_curwin = curwin;
cmdmod_T save_cmdmod = cmdmod; cmdmod_T save_cmdmod = cmdmod;
char_u *save_shm_p = vim_strsave(p_shm); char_u *save_shm_p = vim_strsave(p_shm);
@ -6013,11 +6021,11 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, char_u *pat, char_u *sub,
// We keep a special-purpose buffer around, but don't assume it exists. // We keep a special-purpose buffer around, but don't assume it exists.
buf_T *preview_buf = bufnr ? buflist_findnr(bufnr) : 0; buf_T *preview_buf = bufnr ? buflist_findnr(bufnr) : 0;
win_size_save(&save_winsizes); // Save current window sizes.
cmdmod.tab = 0; // disable :tab modifier cmdmod.tab = 0; // disable :tab modifier
cmdmod.noswapfile = true; // disable swap for preview buffer cmdmod.noswapfile = true; // disable swap for preview buffer
// disable file info message // 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 bool outside_curline = (eap->line1 != old_cusr.lnum
|| eap->line2 != old_cusr.lnum); || eap->line2 != old_cusr.lnum);
@ -6091,20 +6099,18 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, char_u *pat, char_u *sub,
} }
redraw_later(SOME_VALID); redraw_later(SOME_VALID);
win_enter(save_curwin, false); // Return to original window win_enter(save_curwin, false); // Return to original window
win_size_restore(&save_winsizes); update_topline();
ga_clear(&save_winsizes);
set_option_value((char_u *)"shm", 0L, save_shm_p, 0);
xfree(save_shm_p);
// Update screen now. Must do this _before_ close_windows(). // Update screen now. Must do this _before_ close_windows().
int save_rd = RedrawingDisabled; int save_rd = RedrawingDisabled;
RedrawingDisabled = 0; RedrawingDisabled = 0;
update_screen(NOT_VALID); update_screen(SOME_VALID);
RedrawingDisabled = save_rd; RedrawingDisabled = save_rd;
set_string_option_direct((char_u *)"shm", -1, save_shm_p, OPT_FREE, SID_NONE);
xfree(save_shm_p);
cmdmod = save_cmdmod; cmdmod = save_cmdmod;
return preview_buf; return preview_buf;
@ -6117,14 +6123,17 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, char_u *pat, char_u *sub,
/// from undo history. /// from undo history.
void ex_substitute(exarg_T *eap) void ex_substitute(exarg_T *eap)
{ {
if (*p_icm == NUL || !eap->is_live) { // 'inccommand' is disabled bool preview = (State & CMDPREVIEW);
(void)do_sub(eap); if (*p_icm == NUL || !preview) { // 'inccommand' is disabled
(void)do_sub(eap, profile_zero());
return; return;
} }
block_autocmds(); // Disable events during command preview. block_autocmds(); // Disable events during command preview.
char_u *save_eap = eap->arg; char_u *save_eap = eap->arg;
garray_T save_view;
win_size_save(&save_view); // Save current window sizes.
save_search_patterns(); save_search_patterns();
int save_changedtick = curbuf->b_changedtick; int save_changedtick = curbuf->b_changedtick;
time_t save_b_u_time_cur = curbuf->b_u_time_cur; time_t save_b_u_time_cur = curbuf->b_u_time_cur;
@ -6138,7 +6147,7 @@ void ex_substitute(exarg_T *eap)
curwin->w_p_cul = false; // Disable 'cursorline' curwin->w_p_cul = false; // Disable 'cursorline'
curwin->w_p_cuc = false; // Disable 'cursorcolumn' curwin->w_p_cuc = false; // Disable 'cursorcolumn'
buf_T *preview_buf = do_sub(eap); buf_T *preview_buf = do_sub(eap, profile_setlimit(p_rdt));
if (save_changedtick != curbuf->b_changedtick) { if (save_changedtick != curbuf->b_changedtick) {
// Undo invisibly. This also moves the cursor! // Undo invisibly. This also moves the cursor!
@ -6158,6 +6167,8 @@ void ex_substitute(exarg_T *eap)
curwin->w_p_cuc = save_w_p_cuc; // Restore 'cursorcolumn' curwin->w_p_cuc = save_w_p_cuc; // Restore 'cursorcolumn'
eap->arg = save_eap; eap->arg = save_eap;
restore_search_patterns(); restore_search_patterns();
win_size_restore(&save_view);
ga_clear(&save_view);
emsg_off--; emsg_off--;
unblock_autocmds(); unblock_autocmds();
} }

View File

@ -124,7 +124,6 @@ struct exarg {
LineGetter getline; ///< Function used to get the next line LineGetter getline; ///< Function used to get the next line
void *cookie; ///< argument for getline() void *cookie; ///< argument for getline()
struct condstack *cstack; ///< condition stack for ":if" etc. struct condstack *cstack; ///< condition stack for ":if" etc.
bool is_live; ///< 'inccommand' live preview
}; };
#define FORCE_BIN 1 // ":edit ++bin file" #define FORCE_BIN 1 // ":edit ++bin file"

View File

@ -1248,7 +1248,6 @@ static char_u * do_one_cmd(char_u **cmdlinep,
memset(&ea, 0, sizeof(ea)); memset(&ea, 0, sizeof(ea));
ea.line1 = 1; ea.line1 = 1;
ea.line2 = 1; ea.line2 = 1;
ea.is_live = flags & DOCMD_LIVE;
ex_nesting_level++; ex_nesting_level++;
/* When the last file has not been edited :q has to be typed twice. */ /* When the last file has not been edited :q has to be typed twice. */
@ -9648,12 +9647,12 @@ static void ex_terminal(exarg_T *eap)
} }
} }
/// Check whether commandline starts with a live command /// Checks if `cmd` is "previewable" (i.e. supported by 'inccommand').
/// ///
/// @param[in] cmd Commandline to check. May start with a range. /// @param[in] cmd Commandline to check. May start with a range.
/// ///
/// @return True if first command is a live command /// @return true if `cmd` is previewable
bool cmd_is_live(char_u *cmd) bool cmd_can_preview(char_u *cmd)
{ {
if (cmd == NULL) { if (cmd == NULL) {
return false; return false;

View File

@ -10,7 +10,6 @@
#define DOCMD_KEYTYPED 0x08 // don't reset KeyTyped #define DOCMD_KEYTYPED 0x08 // don't reset KeyTyped
#define DOCMD_EXCRESET 0x10 // reset exception environment (for debugging #define DOCMD_EXCRESET 0x10 // reset exception environment (for debugging
#define DOCMD_KEEPLINE 0x20 // keep typed line for repeating with "." #define DOCMD_KEEPLINE 0x20 // keep typed line for repeating with "."
#define DOCMD_LIVE 0x40 // show updates as-you-type ("live" command)
/* defines for eval_vars() */ /* defines for eval_vars() */
#define VALID_PATH 1 #define VALID_PATH 1

View File

@ -95,19 +95,20 @@ typedef struct command_line_state {
char_u *lookfor; // string to match char_u *lookfor; // string to match
int hiscnt; // current history line in use int hiscnt; // current history line in use
int histype; // history type to be used int histype; // history type to be used
pos_T old_cursor; pos_T old_cursor;
colnr_T old_curswant; colnr_T old_curswant;
colnr_T old_leftcol; colnr_T old_leftcol;
linenr_T old_topline; linenr_T old_topline;
int old_topfill; int old_topfill;
linenr_T old_botline; linenr_T old_botline;
int did_incsearch; int did_incsearch;
int incsearch_postponed; int incsearch_postponed;
int did_wild_list; // did wild_list() recently int did_wild_list; // did wild_list() recently
int wim_index; // index in wim_flags[] int wim_index; // index in wim_flags[]
int res; int res;
int save_msg_scroll; int save_msg_scroll;
int save_State; // remember State when called int save_State; // remember State when called
char_u *save_p_icm;
int some_key_typed; // one of the keys was typed int some_key_typed; // one of the keys was typed
// mouse drag and release events are ignored, unless they are // mouse drag and release events are ignored, unless they are
// preceded with a mouse down event // preceded with a mouse down event
@ -159,6 +160,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
s->indent = indent; s->indent = indent;
s->save_msg_scroll = msg_scroll; s->save_msg_scroll = msg_scroll;
s->save_State = State; s->save_State = State;
s->save_p_icm = vim_strsave(p_icm);
s->ignore_drag_release = true; s->ignore_drag_release = true;
if (s->firstc == -1) { if (s->firstc == -1) {
@ -323,9 +325,12 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
need_wait_return = false; need_wait_return = false;
} }
set_string_option_direct((char_u *)"icm", -1, s->save_p_icm, OPT_FREE,
SID_NONE);
State = s->save_State; State = s->save_State;
setmouse(); setmouse();
ui_cursor_shape(); // may show different cursor shape ui_cursor_shape(); // may show different cursor shape
xfree(s->save_p_icm);
{ {
char_u *p = ccline.cmdbuff; char_u *p = ccline.cmdbuff;
@ -981,7 +986,6 @@ static int command_line_handle_key(CommandLineState *s)
status_redraw_curbuf(); status_redraw_curbuf();
return command_line_not_changed(s); return command_line_not_changed(s);
// case '@': only in very old vi
case Ctrl_U: case Ctrl_U:
// delete all characters left of the cursor // delete all characters left of the cursor
s->j = ccline.cmdpos; s->j = ccline.cmdpos;
@ -996,7 +1000,6 @@ static int command_line_handle_key(CommandLineState *s)
redrawcmd(); redrawcmd();
return command_line_changed(s); return command_line_changed(s);
case ESC: // get here if p_wc != ESC or when ESC typed twice case ESC: // get here if p_wc != ESC or when ESC typed twice
case Ctrl_C: case Ctrl_C:
// In exmode it doesn't make sense to return. Except when // In exmode it doesn't make sense to return. Except when
@ -1489,11 +1492,11 @@ static int command_line_handle_key(CommandLineState *s)
static int command_line_not_changed(CommandLineState *s) static int command_line_not_changed(CommandLineState *s)
{ {
// This part implements incremental searches for "/" and "?" Jump to // Incremental searches for "/" and "?":
// cmdline_not_changed when a character has been read but the command line // Enter command_line_not_changed() when a character has been read but the
// did not change. Then we only search and redraw if something changed in // command line did not change. Then we only search and redraw if something
// the past. Jump to cmdline_changed when the command line did change. // changed in the past.
// (Sorry for the goto's, I know it is ugly). // Enter command_line_changed() when the command line did change.
if (!s->incsearch_postponed) { if (!s->incsearch_postponed) {
return 1; return 1;
} }
@ -1592,15 +1595,21 @@ static int command_line_changed(CommandLineState *s)
redrawcmdline(); redrawcmdline();
s->did_incsearch = true; s->did_incsearch = true;
} else if (s->firstc == ':' } else if (s->firstc == ':'
&& KeyTyped // only if interactive && current_SID == 0 // only if interactive
&& *p_icm != NUL // 'inccommand' is set && *p_icm != NUL // 'inccommand' is set
&& curbuf->b_p_ma // buffer is modifiable && curbuf->b_p_ma // buffer is modifiable
&& cmdline_star == 0 // not typing a password && cmdline_star == 0 // not typing a password
&& cmd_is_live(ccline.cmdbuff)) { && cmd_can_preview(ccline.cmdbuff)
// process a "live" command ('inccommand') && !vpeekc_any()) {
do_cmdline(ccline.cmdbuff, NULL, NULL, DOCMD_KEEPLINE|DOCMD_LIVE); // Show 'inccommand' preview. It works like this:
// 1. Do the command.
// 2. Command implementation detects CMDPREVIEW state, then:
// - Update the screen while the effects are in place.
// - Immediately undo the effects.
State |= CMDPREVIEW;
do_cmdline(ccline.cmdbuff, NULL, NULL, DOCMD_KEEPLINE|DOCMD_NOWAIT);
// restore the window "view" // Restore the window "view".
curwin->w_cursor = s->old_cursor; curwin->w_cursor = s->old_cursor;
curwin->w_curswant = s->old_curswant; curwin->w_curswant = s->old_curswant;
curwin->w_leftcol = s->old_leftcol; curwin->w_leftcol = s->old_leftcol;
@ -1610,6 +1619,9 @@ static int command_line_changed(CommandLineState *s)
update_topline(); update_topline();
redrawcmdline(); redrawcmdline();
} else if (State & CMDPREVIEW) {
State = (State & ~CMDPREVIEW);
update_screen(SOME_VALID); // Clear 'inccommand' preview.
} }
if (cmdmsg_rl || (p_arshape && !p_tbidi && enc_utf8)) { if (cmdmsg_rl || (p_arshape && !p_tbidi && enc_utf8)) {

View File

@ -1583,29 +1583,27 @@ vungetc ( /* unget one character (can only be done once!) */
old_mouse_col = mouse_col; old_mouse_col = mouse_col;
} }
/* /// get a character:
* get a character: /// 1. from the stuffbuffer
* 1. from the stuffbuffer /// This is used for abbreviated commands like "D" -> "d$".
* This is used for abbreviated commands like "D" -> "d$". /// Also used to redo a command for ".".
* Also used to redo a command for ".". /// 2. from the typeahead buffer
* 2. from the typeahead buffer /// Stores text obtained previously but not used yet.
* Stores text obtained previously but not used yet. /// Also stores the result of mappings.
* Also stores the result of mappings. /// Also used for the ":normal" command.
* Also used for the ":normal" command. /// 3. from the user
* 3. from the user /// This may do a blocking wait if "advance" is TRUE.
* This may do a blocking wait if "advance" is TRUE. ///
* /// if "advance" is TRUE (vgetc()):
* if "advance" is TRUE (vgetc()): /// really get the character.
* really get the character. /// KeyTyped is set to TRUE in the case the user typed the key.
* KeyTyped is set to TRUE in the case the user typed the key. /// KeyStuffed is TRUE if the character comes from the stuff buffer.
* KeyStuffed is TRUE if the character comes from the stuff buffer. /// if "advance" is FALSE (vpeekc()):
* if "advance" is FALSE (vpeekc()): /// just look whether there is a character available.
* just look whether there is a character available. ///
* /// When "no_mapping" is zero, checks for mappings in the current mode.
* When "no_mapping" is zero, checks for mappings in the current mode. /// Only returns one byte (of a multi-byte character).
* Only returns one byte (of a multi-byte character). /// K_SPECIAL and CSI may be escaped, need to get two more bytes then.
* K_SPECIAL and CSI may be escaped, need to get two more bytes then.
*/
static int vgetorpeek(int advance) static int vgetorpeek(int advance)
{ {
int c, c1; int c, c1;

View File

@ -13,12 +13,12 @@
/// When OPT_GLOBAL and OPT_LOCAL are both missing, set both local and global /// When OPT_GLOBAL and OPT_LOCAL are both missing, set both local and global
/// values, get local value. /// values, get local value.
typedef enum { typedef enum {
OPT_FREE = 1, ///< Free old value if it was allocated. OPT_FREE = 1, ///< Free old value if it was allocated.
OPT_GLOBAL = 2, ///< Use global value. OPT_GLOBAL = 2, ///< Use global value.
OPT_LOCAL = 4, ///< Use local value. OPT_LOCAL = 4, ///< Use local value.
OPT_MODELINE = 8, ///< Option in modeline. OPT_MODELINE = 8, ///< Option in modeline.
OPT_WINONLY = 16, ///< Only set window-local options. OPT_WINONLY = 16, ///< Only set window-local options.
OPT_NOWIN = 32, ///< Dont set window-local options. OPT_NOWIN = 32, ///< Dont set window-local options.
} OptionFlags; } OptionFlags;
#ifdef INCLUDE_GENERATED_DECLARATIONS #ifdef INCLUDE_GENERATED_DECLARATIONS

View File

@ -955,7 +955,6 @@ static void invalidate_terminal(Terminal *term, int start_row, int end_row)
static void refresh_terminal(Terminal *term) static void refresh_terminal(Terminal *term)
{ {
// TODO(SplinterOfChaos): Find the condition that makes term->buf invalid.
buf_T *buf = handle_get_buffer(term->buf_handle); buf_T *buf = handle_get_buffer(term->buf_handle);
bool valid = true; bool valid = true;
if (!buf || !(valid = buf_valid(buf))) { if (!buf || !(valid = buf_valid(buf))) {

View File

@ -104,6 +104,7 @@ Error: configure did not run properly.Check auto/config.log.
#define CONFIRM 0x800 /* ":confirm" prompt */ #define CONFIRM 0x800 /* ":confirm" prompt */
#define SELECTMODE 0x1000 /* Select mode, only for mappings */ #define SELECTMODE 0x1000 /* Select mode, only for mappings */
#define TERM_FOCUS 0x2000 // Terminal focus mode #define TERM_FOCUS 0x2000 // Terminal focus mode
#define CMDPREVIEW 0x4000 // Showing 'inccommand' command "live" preview.
// all mode bits used for mapping // all mode bits used for mapping
#define MAP_ALL_MODES (0x3f | SELECTMODE | TERM_FOCUS) #define MAP_ALL_MODES (0x3f | SELECTMODE | TERM_FOCUS)

File diff suppressed because it is too large Load Diff

View File

@ -600,46 +600,18 @@ describe(":substitute, 'inccommand' preserves undo", function()
feed(":%s/tw/MO/g<esc>") feed(":%s/tw/MO/g<esc>")
feed("u") feed("u")
if case == "split" then screen:expect([[
screen:expect([[ ^LInc substitution on|
^LInc substitution on| two lines |
two lines | |
| {15:~ }|
{15:~ }| {15:~ }|
{15:~ }| {15:~ }|
{15:~ }| {15:~ }|
{15:~ }| {15:~ }|
{15:~ }| {15:~ }|
{15:~ }| Already...st change |
Already...st change | ]])
]])
elseif case == "" then
screen:expect([[
^LInc substitution on|
two lines |
|
{15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
Already...st change |
]])
else
screen:expect([[
LInc substitution on|
^two lines |
|
{15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
Already...st change |
]])
end
end end
screen:detach() screen:detach()
end) end)
@ -789,6 +761,7 @@ describe(":substitute, inccommand=split", function()
it('does not show split window for :s/', function() it('does not show split window for :s/', function()
feed("2gg") feed("2gg")
feed(":s/tw") feed(":s/tw")
wait()
screen:expect([[ screen:expect([[
Inc substitution on | Inc substitution on |
two lines | two lines |
@ -905,11 +878,11 @@ describe(":substitute, inccommand=split", function()
feed(":%s/tw/X") feed(":%s/tw/X")
screen:expect([[ screen:expect([[
Inc substitution on |
BBo lines | BBo lines |
Inc substitution on | Inc substitution on |
Xo lines | Xo lines |
Inc substitution on | Inc substitution on |
Xo lines |
{11:[No Name] [+] }| {11:[No Name] [+] }|
|1001| {12:X}o lines | |1001| {12:X}o lines |
|1003| {12:X}o lines | |1003| {12:X}o lines |
@ -963,6 +936,89 @@ describe(":substitute, inccommand=split", function()
]]) ]])
end) end)
it("deactivates if 'redrawtime' is exceeded #5602", function()
-- Assert that 'inccommand' is ENABLED initially.
eq("split", eval("&inccommand"))
-- Set 'redrawtime' to minimal value, to ensure timeout is triggered.
execute("set redrawtime=1 nowrap")
-- Load a big file.
execute("silent edit! test/functional/fixtures/bigfile.txt")
-- Start :substitute with a slow pattern.
feed([[:%s/B.*N/x]])
wait()
-- Assert that 'inccommand' is DISABLED in cmdline mode.
eq("", eval("&inccommand"))
-- Assert that preview cleared (or never manifested).
screen:expect([[
0000;<control>;Cc;0;BN;;;;;N;N|
0001;<control>;Cc;0;BN;;;;;N;S|
0002;<control>;Cc;0;BN;;;;;N;S|
0003;<control>;Cc;0;BN;;;;;N;E|
0004;<control>;Cc;0;BN;;;;;N;E|
0005;<control>;Cc;0;BN;;;;;N;E|
0006;<control>;Cc;0;BN;;;;;N;A|
0007;<control>;Cc;0;BN;;;;;N;B|
0008;<control>;Cc;0;BN;;;;;N;B|
0009;<control>;Cc;0;S;;;;;N;CH|
000A;<control>;Cc;0;B;;;;;N;LI|
000B;<control>;Cc;0;S;;;;;N;LI|
000C;<control>;Cc;0;WS;;;;;N;F|
000D;<control>;Cc;0;B;;;;;N;CA|
:%s/B.*N/x^ |
]])
-- Assert that 'inccommand' is again ENABLED after leaving cmdline mode.
feed([[<C-\><C-N>]])
eq("split", eval("&inccommand"))
end)
it("clears preview if non-previewable command is edited #5585", function()
-- Put a non-previewable command in history.
execute("echo 'foo'")
-- Start an incomplete :substitute command.
feed(":1,2s/t/X")
screen:expect([[
Inc subsXitution on |
Xwo lines |
Inc substitution on |
two lines |
|
{11:[No Name] [+] }|
|1| Inc subs{12:X}itution on |
|2| {12:X}wo lines |
|
{15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
{10:[Preview] }|
:1,2s/t/X^ |
]])
-- Select the previous command.
feed("<C-P>")
-- Assert that preview was cleared.
screen:expect([[
Inc substitution on |
two lines |
Inc substitution on |
two lines |
|
{15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
:echo 'foo'^ |
]])
end)
end) end)
describe("inccommand=nosplit", function() describe("inccommand=nosplit", function()
@ -1074,6 +1130,41 @@ describe("inccommand=nosplit", function()
]]) ]])
end) end)
it("clears preview if non-previewable command is edited", function()
-- Put a non-previewable command in history.
execute("echo 'foo'")
-- Start an incomplete :substitute command.
feed(":1,2s/t/X")
screen:expect([[
Inc subsXitution on |
Xwo lines |
Inc substitution on |
two lines |
|
{15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
:1,2s/t/X^ |
]])
-- Select the previous command.
feed("<C-P>")
-- Assert that preview was cleared.
screen:expect([[
Inc substitution on |
two lines |
Inc substitution on |
two lines |
|
{15:~ }|
{15:~ }|
{15:~ }|
{15:~ }|
:echo 'foo'^ |
]])
end)
end) end)
describe(":substitute, 'inccommand' with a failing expression", function() describe(":substitute, 'inccommand' with a failing expression", function()