diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/ex_cmds.c | 65 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 7 |
2 files changed, 56 insertions, 16 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 8a0f2e634a..519978f4fb 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -109,6 +109,8 @@ typedef struct { # include "ex_cmds.c.generated.h" #endif +static int preview_bufnr = 0; + /// ":ascii" and "ga" implementation void do_ascii(const exarg_T *const eap) { @@ -3244,7 +3246,7 @@ static char_u *sub_parse_flags(char_u *cmd, subflags_T *subflags, /// @param do_buf_event If `true`, send buffer updates. /// @return buffer used for 'inccommand' preview static buf_T *do_sub(exarg_T *eap, proftime_T timeout, - bool do_buf_event) + bool do_buf_event, handle_T bufnr) { long i = 0; regmmatch_T regmatch; @@ -4198,7 +4200,7 @@ skip: } curbuf->b_changed = save_b_changed; // preserve 'modified' during preview preview_buf = show_sub(eap, old_cursor, &preview_lines, - pre_hl_id, pre_src_id); + pre_hl_id, pre_src_id, bufnr); if (subsize > 0) { extmark_clear(orig_buf, pre_src_id, eap->line1-1, 0, kv_last(preview_lines.subresults).end.lnum-1, MAXCOL); @@ -5575,14 +5577,31 @@ void ex_helpclose(exarg_T *eap) } } +/// Tries to enter to an existing window of given buffer. If no existing buffer +/// is found, creates a new split. +/// +/// Returns OK/FAIL. +int sub_preview_win(buf_T *preview_buf) +{ + if (preview_buf != NULL) { + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + if (wp->w_buffer == preview_buf) { + win_enter(wp, false); + + return OK; + } + } + } + return win_split((int)p_cwh, WSP_BOT); +} + /// Shows the effects of the :substitute command being typed ('inccommand'). /// If inccommand=split, shows a preview window and later restores the layout. static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, - PreviewLines *preview_lines, int hl_id, int src_id) + PreviewLines *preview_lines, int hl_id, int src_id, + handle_T bufnr) FUNC_ATTR_NONNULL_ALL { - static handle_T bufnr = 0; // special buffer, re-used on each visit - win_T *save_curwin = curwin; cmdmod_T save_cmdmod = cmdmod; char_u *save_shm_p = vim_strsave(p_shm); @@ -5600,9 +5619,9 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, bool outside_curline = (eap->line1 != old_cusr.lnum || eap->line2 != old_cusr.lnum); - bool split = outside_curline && (*p_icm != 'n'); + bool preview = outside_curline && (*p_icm != 'n'); if (preview_buf == curbuf) { // Preview buffer cannot preview itself! - split = false; + preview = false; preview_buf = NULL; } @@ -5620,11 +5639,10 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, linenr_T highest_num_line = 0; int col_width = 0; - if (split && win_split((int)p_cwh, WSP_BOT) != FAIL) { + if (preview && sub_preview_win(preview_buf) != FAIL) { buf_open_scratch(preview_buf ? bufnr : 0, "[Preview]"); buf_clear(); preview_buf = curbuf; - bufnr = preview_buf->handle; curbuf->b_p_bl = false; curbuf->b_p_ma = true; curbuf->b_p_ul = -1; @@ -5713,7 +5731,7 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, win_enter(save_curwin, false); // Return to original window update_topline(); - // Update screen now. Must do this _before_ close_windows(). + // Update screen now. int save_rd = RedrawingDisabled; RedrawingDisabled = 0; update_screen(SOME_VALID); @@ -5727,6 +5745,17 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, return preview_buf; } +/// Closes any open windows for inccommand preview buffer. +void close_preview_windows(void) +{ + block_autocmds(); + buf_T *buf = preview_bufnr ? buflist_findnr(preview_bufnr) : NULL; + if (buf != NULL) { + close_windows(buf, false); + } + unblock_autocmds(); +} + /// :substitute command /// /// If 'inccommand' is empty: calls do_sub(). @@ -5736,7 +5765,9 @@ void ex_substitute(exarg_T *eap) { bool preview = (State & CMDPREVIEW); if (*p_icm == NUL || !preview) { // 'inccommand' is disabled - (void)do_sub(eap, profile_zero(), true); + close_preview_windows(); + (void)do_sub(eap, profile_zero(), true, preview_bufnr); + return; } @@ -5760,9 +5791,14 @@ void ex_substitute(exarg_T *eap) // Don't show search highlighting during live substitution bool save_hls = p_hls; p_hls = false; - buf_T *preview_buf = do_sub(eap, profile_setlimit(p_rdt), false); + buf_T *preview_buf = do_sub(eap, profile_setlimit(p_rdt), false, + preview_bufnr); p_hls = save_hls; + if (preview_buf != NULL) { + preview_bufnr = preview_buf->handle; + } + if (save_changedtick != buf_get_changedtick(curbuf)) { // Undo invisibly. This also moves the cursor! if (!u_undo_and_forget(1)) { abort(); } @@ -5772,10 +5808,7 @@ void ex_substitute(exarg_T *eap) curbuf->b_u_time_cur = save_b_u_time_cur; buf_set_changedtick(curbuf, save_changedtick); } - if (buf_valid(preview_buf)) { - // XXX: Must do this *after* u_undo_and_forget(), why? - close_windows(preview_buf, false); - } + curbuf->b_p_ul = save_b_p_ul; curwin->w_p_cul = save_w_p_cul; // Restore 'cursorline' curwin->w_p_cuc = save_w_p_cuc; // Restore 'cursorcolumn' diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 1a836b7a98..93684e8606 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -450,6 +450,11 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) ExpandCleanup(&s->xpc); ccline.xpc = NULL; + if (s->gotesc) { + // There might be a preview window open for inccommand. Close it. + close_preview_windows(); + } + if (s->did_incsearch) { if (s->gotesc) { curwin->w_cursor = s->save_cursor; @@ -1958,8 +1963,10 @@ static int command_line_changed(CommandLineState *s) update_topline(); redrawcmdline(); + } else if (State & CMDPREVIEW) { State = (State & ~CMDPREVIEW); + close_preview_windows(); update_screen(SOME_VALID); // Clear 'inccommand' preview. } |