diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2016-11-15 00:10:39 +0100 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2016-11-15 04:22:24 +0100 |
commit | 3f7a2d785dcc8c3dad341669c83f29779987d9a4 (patch) | |
tree | ea4f1e8e75a81a01c0807c61721d93531251b695 /src | |
parent | 708617ebb6aa9f078549646930c73f0755c2c2e6 (diff) | |
download | rneovim-3f7a2d785dcc8c3dad341669c83f29779987d9a4.tar.gz rneovim-3f7a2d785dcc8c3dad341669c83f29779987d9a4.tar.bz2 rneovim-3f7a2d785dcc8c3dad341669c83f29779987d9a4.zip |
'inccommand': Introduce CMDPREVIEW state.
Command "live preview" is fundamentally a non-recursive concept
("preview of a preview" is not useful). Maintaining this as a
global is less awkward and closer to what we actually want to
express, vs adorning exarg_T, CommandLineState, etc.
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/ex_cmds.c | 40 | ||||
-rw-r--r-- | src/nvim/ex_cmds_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 7 | ||||
-rw-r--r-- | src/nvim/ex_docmd.h | 1 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 24 | ||||
-rw-r--r-- | src/nvim/terminal.c | 1 | ||||
-rw-r--r-- | src/nvim/vim.h | 1 |
7 files changed, 38 insertions, 37 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 40e506e80e..42af5989a1 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -2952,10 +2952,11 @@ void sub_set_replacement(SubReplacementString sub) /// @param[in] pat Search pattern /// @param[in] sub Replacement string /// @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 -static bool sub_joining_lines(exarg_T *eap, char_u *pat, - char_u *sub, char_u *cmd) +static bool sub_joining_lines(exarg_T *eap, char_u *pat, char_u *sub, + char_u *cmd, bool save) FUNC_ATTR_NONNULL_ARG(1, 3, 4) { // 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); } - if (!eap->is_live) { + if (save) { if (!cmdmod.keeppatterns) { save_re_pat(RE_SUBST, pat, p_magic); } @@ -3108,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. /// /// @return buffer used for 'inccommand' preview -static buf_T *do_sub(exarg_T *eap) +static buf_T *do_sub(exarg_T *eap, proftime_T timeout) { long i = 0; regmmatch_T regmatch; @@ -3137,10 +3138,10 @@ static 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; + bool preview = (State & CMDPREVIEW); if (!global_busy) { sub_nsubs = 0; @@ -3208,7 +3209,7 @@ static buf_T *do_sub(exarg_T *eap) mb_ptr_adv(cmd); } - if (!eap->skip && !eap->is_live) { + if (!eap->skip && !preview) { sub_set_replacement((SubReplacementString) { .sub = xstrdup((char *) sub), .timestamp = os_time(), @@ -3228,7 +3229,7 @@ static buf_T *do_sub(exarg_T *eap) endcolumn = (curwin->w_curswant == MAXCOL); } - if (sub_joining_lines(eap, pat, sub, cmd)) { + if (sub_joining_lines(eap, pat, sub, cmd, !preview)) { return NULL; } @@ -3273,7 +3274,7 @@ static buf_T *do_sub(exarg_T *eap) 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), ®match) == FAIL) { if (subflags.do_error) { EMSG(_(e_invcmd)); @@ -3403,7 +3404,7 @@ static buf_T *do_sub(exarg_T *eap) curwin->w_cursor.lnum = lnum; do_again = FALSE; - if (eap->is_live) { + if (preview) { // Increment the in-line match count and store the column. matched_line.nmatch++; kv_push(matched_line.cols, regmatch.startpos[0].col); @@ -3456,7 +3457,7 @@ static buf_T *do_sub(exarg_T *eap) goto skip; } - if (subflags.do_ask && !eap->is_live) { + if (subflags.do_ask && !preview) { int typed = 0; /* change State to CONFIRM, so that the mouse works @@ -3627,9 +3628,9 @@ static buf_T *do_sub(exarg_T *eap) * use "\=col("."). */ curwin->w_cursor.col = regmatch.startpos[0].col; - // 3. Substitute the string. During 'inccommand' only do this if there - // is a replace pattern. - if (!eap->is_live || has_second_delim) { + // 3. Substitute the string. During 'inccommand' preview only do this if + // there is a replace pattern. + if (!preview || has_second_delim) { if (subflags.do_count) { // prevent accidentally changing the buffer by a function save_ma = curbuf->b_p_ma; @@ -3873,7 +3874,7 @@ skip: xfree(sub_firstline); /* free the copy of the original line */ sub_firstline = NULL; - if (eap->is_live) { + if (preview) { matched_line.lnum = lnum; matched_line.line = vim_strsave(ml_get(lnum)); kv_push(matched_lines, matched_line); @@ -3917,7 +3918,7 @@ skip: 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(""); } } else { @@ -3952,7 +3953,7 @@ skip: // Show 'inccommand' preview if there are matched lines. buf_T *preview_buf = NULL; - if (eap->is_live && !aborting()) { + if (preview && !aborting()) { if (got_quit) { // Substitution is too slow, disable 'inccommand'. set_string_option_direct((char_u *)"icm", -1, (char_u *)"", OPT_FREE, SID_NONE); @@ -6122,8 +6123,9 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, char_u *pat, char_u *sub, /// from undo history. void ex_substitute(exarg_T *eap) { - if (*p_icm == NUL || !eap->is_live) { // 'inccommand' is disabled - (void)do_sub(eap); + bool preview = (State & CMDPREVIEW); + if (*p_icm == NUL || !preview) { // 'inccommand' is disabled + (void)do_sub(eap, profile_zero()); return; } @@ -6145,7 +6147,7 @@ void ex_substitute(exarg_T *eap) curwin->w_p_cul = false; // Disable 'cursorline' 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) { // Undo invisibly. This also moves the cursor! diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h index 8a2ebe2cd4..8148eb5cee 100644 --- a/src/nvim/ex_cmds_defs.h +++ b/src/nvim/ex_cmds_defs.h @@ -124,7 +124,6 @@ struct exarg { LineGetter getline; ///< Function used to get the next line void *cookie; ///< argument for getline() struct condstack *cstack; ///< condition stack for ":if" etc. - bool is_live; ///< 'inccommand' live preview }; #define FORCE_BIN 1 // ":edit ++bin file" diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 07e0fa8844..76dddf874d 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -1248,7 +1248,6 @@ static char_u * do_one_cmd(char_u **cmdlinep, memset(&ea, 0, sizeof(ea)); ea.line1 = 1; ea.line2 = 1; - ea.is_live = flags & DOCMD_LIVE; ex_nesting_level++; /* 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. /// -/// @return True if first command is a live command -bool cmd_is_live(char_u *cmd) +/// @return true if `cmd` is previewable +bool cmd_can_preview(char_u *cmd) { if (cmd == NULL) { return false; diff --git a/src/nvim/ex_docmd.h b/src/nvim/ex_docmd.h index 84f1a13a15..fb6aac223f 100644 --- a/src/nvim/ex_docmd.h +++ b/src/nvim/ex_docmd.h @@ -10,7 +10,6 @@ #define DOCMD_KEYTYPED 0x08 // don't reset KeyTyped #define DOCMD_EXCRESET 0x10 // reset exception environment (for debugging #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() */ #define VALID_PATH 1 diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 3093caebaf..532775ad0b 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -103,7 +103,6 @@ typedef struct command_line_state { 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; @@ -400,8 +399,7 @@ static int command_line_execute(VimState *state, int key) if ((s->c == Ctrl_C) && s->firstc != '@' && !s->break_ctrl_c - && !global_busy - && !cmd_is_live(ccline.cmdbuff)) { + && !global_busy) { got_int = false; } @@ -1601,13 +1599,17 @@ static int command_line_changed(CommandLineState *s) && *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_can_preview(ccline.cmdbuff) && !vpeekc_any()) { - s->live = true; - // process a "live" command ('inccommand') - do_cmdline(ccline.cmdbuff, NULL, NULL, DOCMD_KEEPLINE|DOCMD_LIVE); - - // restore the window "view" + // 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". curwin->w_cursor = s->old_cursor; curwin->w_curswant = s->old_curswant; curwin->w_leftcol = s->old_leftcol; @@ -1617,8 +1619,8 @@ static int command_line_changed(CommandLineState *s) update_topline(); redrawcmdline(); - } else if (s->live) { - s->live = false; + } else if (State & CMDPREVIEW) { + State = (State & ~CMDPREVIEW); update_screen(SOME_VALID); // Clear 'inccommand' preview. } diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index 499716a7a8..bd7b9fc58f 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -955,7 +955,6 @@ static void invalidate_terminal(Terminal *term, int start_row, int end_row) 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); bool valid = true; if (!buf || !(valid = buf_valid(buf))) { diff --git a/src/nvim/vim.h b/src/nvim/vim.h index 6bbd9b58ef..32eba55c18 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -104,6 +104,7 @@ Error: configure did not run properly.Check auto/config.log. #define CONFIRM 0x800 /* ":confirm" prompt */ #define SELECTMODE 0x1000 /* Select mode, only for mappings */ #define TERM_FOCUS 0x2000 // Terminal focus mode +#define CMDPREVIEW 0x4000 // Showing 'inccommand' command "live" preview. // all mode bits used for mapping #define MAP_ALL_MODES (0x3f | SELECTMODE | TERM_FOCUS) |