diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/buffer.c | 12 | ||||
-rw-r--r-- | src/nvim/ex_cmds.c | 71 | ||||
-rw-r--r-- | src/nvim/ex_cmds.h | 1 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 10 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 14 | ||||
-rw-r--r-- | src/nvim/undo.c | 3 |
6 files changed, 59 insertions, 52 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 75caf2223b..8e6066453c 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -5273,14 +5273,20 @@ wipe_buffer ( } } -/// Creates or switches to a special-purpose buffer. +/// Creates or switches to a scratch buffer. :h special-buffers +/// Scratch buffer is: +/// - buftype=nofile bufhidden=hide noswapfile +/// - Always considered 'nomodified' /// /// @param bufnr Buffer to switch to, or 0 to create a new buffer. -void buf_open_special(handle_T bufnr, char *bufname, char *buftype) +/// +/// @see curbufIsChanged() +void buf_open_scratch(handle_T bufnr, char *bufname) { (void)do_ecmd((int)bufnr, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, NULL); (void)setfname(curbuf, (char_u *)bufname, NULL, true); - set_option_value((char_u *)"bt", 0L, (char_u *)buftype, OPT_LOCAL); + set_option_value((char_u *)"bh", 0L, (char_u *)"hide", OPT_LOCAL); + set_option_value((char_u *)"bt", 0L, (char_u *)"nofile", OPT_LOCAL); set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL); RESET_BINDING(curwin); } diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 13a0282b76..66b6aa2f46 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -2188,7 +2188,6 @@ int do_ecmd( if (fnum) { buf = buflist_findnr(fnum); } else { - ILOG("here"); if (flags & ECMD_ADDBUF) { linenr_T tlnum = 1L; @@ -3275,8 +3274,7 @@ buf_T *do_sub(exarg_T *eap) return NULL; } - int search_options = eap->is_live ? 0 : SEARCH_HIS; - if (search_regcomp(pat, RE_SUBST, which_pat, search_options, + if (search_regcomp(pat, RE_SUBST, which_pat, (eap->is_live ? 0 : SEARCH_HIS), ®match) == FAIL) { if (subflags.do_error) { EMSG(_(e_invcmd)); @@ -3951,13 +3949,9 @@ skip: // Show 'inccommand' preview if there are matched lines. buf_T *preview_buf = NULL; - if (eap->is_live && matched_lines.size != 0 && pat != NULL && *p_icm != NUL) { + 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(old_cursor, pat, sub, eap->line1, eap->line2, - &matched_lines); - - } else if (*p_icm != NUL && eap->is_live) { - curwin->w_cursor = old_cursor; // don't move the cursor + preview_buf = show_sub(eap, old_cursor, pat, sub, &matched_lines); } for (MatchedLine m; kv_size(matched_lines);) { @@ -6004,8 +5998,8 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg) /// 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(pos_T old_cusr, char_u *pat, char_u *sub, linenr_T line1, - linenr_T line2, MatchedLineVec *matched_lines) +static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, char_u *pat, char_u *sub, + MatchedLineVec *matched_lines) FUNC_ATTR_NONNULL_ALL { static handle_T bufnr = 0; // special buffer, re-used on each visit @@ -6025,49 +6019,35 @@ static buf_T *show_sub(pos_T old_cusr, char_u *pat, char_u *sub, linenr_T line1, // disable file info message set_option_value((char_u *)"shm", 0L, (char_u *)"F", 0); - bool outside_curline = (line1 != curwin->w_cursor.lnum - || line2 != curwin->w_cursor.lnum); + bool outside_curline = (eap->line1 != old_cusr.lnum + || eap->line2 != old_cusr.lnum); bool split = outside_curline && (*p_icm != 'n') && (sub_size || pat_size); if (preview_buf == curbuf) { // Preview buffer cannot preview itself! split = false; preview_buf = NULL; } - // Place cursor on the first match after the cursor. (If all matches are - // above, then do_sub already placed cursor on the last match.) - colnr_T cur_col = -1; - MatchedLine curmatch; - for (size_t j = 0; j < matched_lines->size && cur_col == -1; j++) { - curmatch = matched_lines->items[j]; - if (curmatch.lnum == old_cusr.lnum) { - // On cursor line; iterate in-line matches to find one after cursor. - for (size_t i = 0; i < curmatch.cols.size; i++) { - if (curmatch.cols.items[i] >= old_cusr.col) { - cur_col = curmatch.cols.items[i]; - curwin->w_cursor.lnum = curmatch.lnum; - curwin->w_cursor.col = cur_col; - break; - } - } - } else if (curmatch.lnum > old_cusr.lnum) { - // After cursor; put cursor on first match there. - cur_col = curmatch.cols.items[0]; + // Place cursor on nearest matching line, to undo do_sub() cursor placement. + for (size_t i = 0; i < matched_lines->size; i++) { + MatchedLine curmatch = matched_lines->items[i]; + if (curmatch.lnum >= old_cusr.lnum) { curwin->w_cursor.lnum = curmatch.lnum; - curwin->w_cursor.col = cur_col; - } + curwin->w_cursor.col = curmatch.cols.items[0]; + break; + } // Else: All matches are above, do_sub() already placed cursor. } if (split && win_split((int)p_cwh, WSP_BOT) != FAIL) { - buf_open_special(preview_buf ? bufnr : 0, "[Preview]", "incsub"); + buf_open_scratch(preview_buf ? bufnr : 0, "[Preview]"); buf_clear(); preview_buf = curbuf; - set_option_value((char_u *)"bufhidden", 0L, (char_u *)"hide", OPT_LOCAL); bufnr = preview_buf->handle; curbuf->b_p_bl = false; curbuf->b_p_ma = true; curbuf->b_p_ul = -1; curbuf->b_p_tw = 0; // Reset 'textwidth' (was set by ftplugin) curwin->w_p_cul = false; + curwin->w_p_cuc = false; curwin->w_p_spell = false; curwin->w_p_fen = false; @@ -6092,7 +6072,7 @@ static buf_T *show_sub(pos_T old_cusr, char_u *pat, char_u *sub, linenr_T line1, old_line_size = line_size; } - // put " | lnum|line" into str and append it to the preview buffer + // Put "|lnum| line" into `str` and append it to the preview buffer. snprintf(str, line_size, "|%*ld| %s", col_width - 3, mat.lnum, mat.line); ml_append(line, (char_u *)str, (colnr_T)line_size, false); @@ -6132,8 +6112,8 @@ static buf_T *show_sub(pos_T old_cusr, char_u *pat, char_u *sub, linenr_T line1, /// :substitute command /// -/// If 'inccommand' is empty this just calls do_sub(). -/// If 'inccommand' is set, shows a "live" preview then removes the changes +/// If 'inccommand' is empty: calls do_sub(). +/// If 'inccommand' is set: shows a "live" preview then removes the changes. /// from undo history. void ex_substitute(exarg_T *eap) { @@ -6142,19 +6122,26 @@ void ex_substitute(exarg_T *eap) return; } + block_autocmds(); // Disable events during command preview. + char_u *save_eap = eap->arg; save_search_patterns(); int save_changedtick = curbuf->b_changedtick; time_t save_b_u_time_cur = curbuf->b_u_time_cur; u_header_T *save_b_u_newhead = curbuf->b_u_newhead; long save_b_p_ul = curbuf->b_p_ul; + int save_w_p_cul = curwin->w_p_cul; + int save_w_p_cuc = curwin->w_p_cuc; + + emsg_off++; // No error messages during command preview. curbuf->b_p_ul = LONG_MAX; // make sure we can undo all changes - block_autocmds(); // disable events before show_sub() opens window/buffer - emsg_off++; // No error messages for live commands + curwin->w_p_cul = false; // Disable 'cursorline' + curwin->w_p_cuc = false; // Disable 'cursorcolumn' buf_T *preview_buf = do_sub(eap); if (save_changedtick != curbuf->b_changedtick) { + // Undo invisibly. This also moves the cursor! if (!u_undo_and_forget(1)) { abort(); } // Restore newhead. It is meaningless when curhead is valid, but we must // restore it so that undotree() is identical before/after the preview. @@ -6167,6 +6154,8 @@ void ex_substitute(exarg_T *eap) 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' eap->arg = save_eap; restore_search_patterns(); emsg_off--; diff --git a/src/nvim/ex_cmds.h b/src/nvim/ex_cmds.h index ccb2202edb..243b11255e 100644 --- a/src/nvim/ex_cmds.h +++ b/src/nvim/ex_cmds.h @@ -14,7 +14,6 @@ #define ECMD_OLDBUF 0x04 // use existing buffer if it exists #define ECMD_FORCEIT 0x08 // ! used in Ex command #define ECMD_ADDBUF 0x10 // don't edit, just add to buffer list -#define ECMD_RESERVED_BUFNR 0x20 // bufnr argument is reserved bufnr /* for lnum argument in do_ecmd() */ diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 30347cbe85..07e0fa8844 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -7295,15 +7295,13 @@ void ex_may_print(exarg_T *eap) } } -/* - * ":smagic" and ":snomagic". - */ +/// ":smagic" and ":snomagic". static void ex_submagic(exarg_T *eap) { int magic_save = p_magic; p_magic = (eap->cmdidx == CMD_smagic); - do_sub(eap); + ex_substitute(eap); p_magic = magic_save; } @@ -9669,5 +9667,7 @@ bool cmd_is_live(char_u *cmd) } find_command(&ea, NULL); - return (ea.cmdidx == CMD_substitute); + return ea.cmdidx == CMD_substitute + || ea.cmdidx == CMD_smagic + || ea.cmdidx == CMD_snomagic; } diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 17693ecfc8..c4169f03f0 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1599,6 +1599,16 @@ static int command_line_changed(CommandLineState *s) && cmd_is_live(ccline.cmdbuff)) { // process a "live" command ('inccommand') do_cmdline(ccline.cmdbuff, NULL, NULL, DOCMD_KEEPLINE|DOCMD_LIVE); + + // restore the window "view" + curwin->w_cursor = s->old_cursor; + curwin->w_curswant = s->old_curswant; + curwin->w_leftcol = s->old_leftcol; + curwin->w_topline = s->old_topline; + curwin->w_topfill = s->old_topfill; + curwin->w_botline = s->old_botline; + update_topline(); + redrawcmdline(); } @@ -5147,7 +5157,9 @@ static int ex_window(void) cmdwin_type = get_cmdline_type(); // Create empty command-line buffer. - buf_open_special(0, "[Command Line]", "nofile"); + buf_open_scratch(0, "[Command Line]"); + // Command-line buffer has bufhidden=wipe, unlike a true "scratch" buffer. + set_option_value((char_u *)"bh", 0L, (char_u *)"wipe", OPT_LOCAL); curwin->w_p_rl = cmdmsg_rl; cmdmsg_rl = false; curbuf->b_p_ma = true; diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 2f4317980a..d6428d63f7 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -1685,7 +1685,8 @@ void u_redo(int count) u_doit(count, false); } -/// undo, and remove the undo branch from the undo tree. +/// Undo and remove the branch from the undo tree. +/// Also moves the cursor (as a "normal" undo would). bool u_undo_and_forget(int count) { if (curbuf->b_u_synced == false) { |