diff options
Diffstat (limited to 'src/nvim/ex_getln.c')
-rw-r--r-- | src/nvim/ex_getln.c | 154 |
1 files changed, 102 insertions, 52 deletions
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 64ef17b157..44a78711d2 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -17,9 +17,12 @@ #include "nvim/arabic.h" #include "nvim/ascii_defs.h" #include "nvim/autocmd.h" +#include "nvim/autocmd_defs.h" #include "nvim/buffer.h" +#include "nvim/buffer_defs.h" #include "nvim/charset.h" #include "nvim/cmdexpand.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/cmdhist.h" #include "nvim/cursor.h" #include "nvim/digraph.h" @@ -34,21 +37,24 @@ #include "nvim/ex_eval.h" #include "nvim/ex_getln.h" #include "nvim/extmark.h" -#include "nvim/func_attr.h" #include "nvim/garray.h" +#include "nvim/garray_defs.h" #include "nvim/getchar.h" -#include "nvim/gettext.h" +#include "nvim/gettext_defs.h" #include "nvim/globals.h" #include "nvim/highlight.h" +#include "nvim/highlight_defs.h" #include "nvim/highlight_group.h" #include "nvim/keycodes.h" #include "nvim/macros_defs.h" #include "nvim/map_defs.h" #include "nvim/mapping.h" #include "nvim/mark.h" +#include "nvim/mark_defs.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" +#include "nvim/memory_defs.h" #include "nvim/message.h" #include "nvim/mouse.h" #include "nvim/move.h" @@ -65,16 +71,21 @@ #include "nvim/pos_defs.h" #include "nvim/profile.h" #include "nvim/regexp.h" +#include "nvim/regexp_defs.h" #include "nvim/search.h" #include "nvim/state.h" +#include "nvim/state_defs.h" #include "nvim/strings.h" #include "nvim/types_defs.h" #include "nvim/ui.h" +#include "nvim/ui_defs.h" #include "nvim/undo.h" +#include "nvim/undo_defs.h" #include "nvim/usercmd.h" #include "nvim/vim_defs.h" #include "nvim/viml/parser/expressions.h" #include "nvim/viml/parser/parser.h" +#include "nvim/viml/parser/parser_defs.h" #include "nvim/window.h" /// Last value of prompt_id, incremented when doing new prompt @@ -104,13 +115,13 @@ typedef struct { optmagic_T magic_overruled_save; } incsearch_state_T; -typedef struct command_line_state { +typedef struct { VimState state; int firstc; int count; int indent; int c; - int gotesc; // true when <ESC> just typed + bool gotesc; // true when <ESC> just typed int do_abbr; // when true check for abbr. char *lookfor; // string to match int hiscnt; // current history line in use @@ -133,7 +144,7 @@ typedef struct command_line_state { buf_T *b_im_ptr_buf; ///< buffer where b_im_ptr is valid } CommandLineState; -typedef struct cmdpreview_undo_info { +typedef struct { u_header_T *save_b_u_oldhead; u_header_T *save_b_u_newhead; u_header_T *save_b_u_curhead; @@ -149,15 +160,17 @@ typedef struct cmdpreview_undo_info { colnr_T save_b_u_line_colnr; } CpUndoInfo; -typedef struct cmdpreview_buf_info { +typedef struct { buf_T *buf; OptInt save_b_p_ul; int save_b_changed; + pos_T save_b_op_start; + pos_T save_b_op_end; varnumber_T save_changedtick; CpUndoInfo undo_info; } CpBufInfo; -typedef struct cmdpreview_win_info { +typedef struct { win_T *win; pos_T save_w_cursor; viewstate_T save_viewstate; @@ -165,7 +178,7 @@ typedef struct cmdpreview_win_info { int save_w_p_cuc; } CpWinInfo; -typedef struct cmdpreview_info { +typedef struct { kvec_t(CpWinInfo) win_info; kvec_t(CpBufInfo) buf_info; bool save_hls; @@ -206,6 +219,9 @@ static int cedit_key = -1; ///< key value of 'cedit' option static handle_T cmdpreview_bufnr = 0; static int cmdpreview_ns = 0; +static const char e_active_window_or_buffer_changed_or_deleted[] + = N_("E199: Active window or buffer changed or deleted"); + static void save_viewstate(win_T *wp, viewstate_T *vs) FUNC_ATTR_NONNULL_ALL { @@ -467,7 +483,7 @@ static void may_do_incsearch_highlighting(int firstc, int count, incsearch_state // if interrupted while searching, behave like it failed if (got_int) { - (void)vpeekc(); // remove <C-C> from input stream + vpeekc(); // remove <C-C> from input stream got_int = false; // don't abandon the command line found = 0; } else if (char_avail()) { @@ -583,7 +599,8 @@ static int may_add_char_to_search(int firstc, int *c, incsearch_state_T *s) return OK; } -static void finish_incsearch_highlighting(int gotesc, incsearch_state_T *s, bool call_update_screen) +static void finish_incsearch_highlighting(bool gotesc, incsearch_state_T *s, + bool call_update_screen) { if (!s->did_incsearch) { return; @@ -839,7 +856,7 @@ static uint8_t *command_line_enter(int firstc, int count, int indent, bool clear // error printed below, to avoid redraw issues tl_ret = try_leave(&tstate, &err); if (tv_dict_get_number(dict, "abort") != 0) { - s->gotesc = 1; + s->gotesc = true; } restore_v_event(dict, &save_v_event); } @@ -885,9 +902,7 @@ static uint8_t *command_line_enter(int firstc, int count, int indent, bool clear // not get printed in the middle of it. msg_check(); if (p_ch == 0 && !ui_has(kUIMessages)) { - if (must_redraw < UPD_VALID) { - must_redraw = UPD_VALID; - } + set_must_redraw(UPD_VALID); } msg_scroll = s->save_msg_scroll; redir_off = false; @@ -904,7 +919,7 @@ static uint8_t *command_line_enter(int firstc, int count, int indent, bool clear need_wait_return = false; } - set_string_option_direct("icm", -1, s->save_p_icm, OPT_FREE, SID_NONE); + set_string_option_direct(kOptInccommand, s->save_p_icm, 0, SID_NONE); State = s->save_State; if (cmdpreview != save_cmdpreview) { cmdpreview = save_cmdpreview; // restore preview state @@ -1051,7 +1066,7 @@ static int command_line_wildchar_complete(CommandLineState *s) && !s->did_wild_list && ((wim_flags[s->wim_index] & WIM_LIST) || (p_wmnu && (wim_flags[s->wim_index] & WIM_FULL) != 0))) { - (void)showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & WIM_LIST) == 0)); + showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & WIM_LIST) == 0)); redrawcmd(); s->did_wild_list = true; } @@ -1077,9 +1092,9 @@ static int command_line_wildchar_complete(CommandLineState *s) // if interrupted while completing, behave like it failed if (got_int) { - (void)vpeekc(); // remove <C-C> from input stream + vpeekc(); // remove <C-C> from input stream got_int = false; // don't abandon the command line - (void)ExpandOne(&s->xpc, NULL, NULL, 0, WILD_FREE); + ExpandOne(&s->xpc, NULL, NULL, 0, WILD_FREE); s->xpc.xp_context = EXPAND_NOTHING; return CMDLINE_CHANGED; } @@ -1103,7 +1118,7 @@ static int command_line_wildchar_complete(CommandLineState *s) p_wmnu = p_wmnu_save; } - (void)showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & WIM_LIST) == 0)); + showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & WIM_LIST) == 0)); redrawcmd(); s->did_wild_list = true; @@ -1137,7 +1152,7 @@ static void command_line_end_wildmenu(CommandLineState *s) cmdline_pum_remove(); } if (s->xpc.xp_numfiles != -1) { - (void)ExpandOne(&s->xpc, NULL, NULL, 0, WILD_FREE); + ExpandOne(&s->xpc, NULL, NULL, 0, WILD_FREE); } s->did_wild_list = false; if (!p_wmnu || (s->c != K_UP && s->c != K_DOWN)) { @@ -1249,7 +1264,7 @@ static int command_line_execute(VimState *state, int key) // Ctrl-E: cancel the cmdline popup menu and return the original text. if (s->c == Ctrl_E || s->c == Ctrl_Y) { wild_type = (s->c == Ctrl_E) ? WILD_CANCEL : WILD_APPLY; - (void)nextwild(&s->xpc, wild_type, WILD_NO_BEEP, s->firstc != '@'); + nextwild(&s->xpc, wild_type, WILD_NO_BEEP, s->firstc != '@'); } } @@ -1418,7 +1433,7 @@ static int may_do_command_line_next_incsearch(int firstc, int count, incsearch_s if (lt(s->match_start, s->match_end)) { // start searching at the end of the match // not at the beginning of the next column - (void)decl(&t); + decl(&t); } search_flags += SEARCH_COL; } else { @@ -1446,21 +1461,21 @@ static int may_do_command_line_next_incsearch(int firstc, int count, incsearch_s // when nv_search finishes the cursor will be // put back on the match s->search_start = t; - (void)decl(&s->search_start); + decl(&s->search_start); } else if (next_match && firstc == '?') { // move just after the current match, so that // when nv_search finishes the cursor will be // put back on the match s->search_start = t; - (void)incl(&s->search_start); + incl(&s->search_start); } if (lt(t, s->search_start) && next_match) { // wrap around s->search_start = t; if (firstc == '?') { - (void)incl(&s->search_start); + incl(&s->search_start); } else { - (void)decl(&s->search_start); + decl(&s->search_start); } } @@ -1495,10 +1510,8 @@ static int command_line_erase_chars(CommandLineState *s) if (s->c == K_DEL && ccline.cmdpos != ccline.cmdlen) { ccline.cmdpos++; } - if (s->c == K_DEL) { - ccline.cmdpos += mb_off_next(ccline.cmdbuff, - ccline.cmdbuff + ccline.cmdpos); + ccline.cmdpos += mb_off_next(ccline.cmdbuff, ccline.cmdbuff + ccline.cmdpos); } if (ccline.cmdpos > 0) { @@ -2175,7 +2188,7 @@ static bool empty_pattern(char *p, int delim) magic_T magic_val = MAGIC_ON; if (n > 0) { - (void)skip_regexp_ex(p, delim, magic_isset(), NULL, NULL, &magic_val); + skip_regexp_ex(p, delim, magic_isset(), NULL, NULL, &magic_val); } else { return true; } @@ -2263,6 +2276,7 @@ static buf_T *cmdpreview_open_buf(void) /// /// @return Pointer to command preview window if succeeded, NULL if failed. static win_T *cmdpreview_open_win(buf_T *cmdpreview_buf) + FUNC_ATTR_NONNULL_ALL { win_T *save_curwin = curwin; @@ -2361,6 +2375,8 @@ static void cmdpreview_prepare(CpInfo *cpinfo) cp_bufinfo.buf = buf; cp_bufinfo.save_b_p_ul = buf->b_p_ul; cp_bufinfo.save_b_changed = buf->b_changed; + cp_bufinfo.save_b_op_start = buf->b_op_start; + cp_bufinfo.save_b_op_end = buf->b_op_end; cp_bufinfo.save_changedtick = buf_get_changedtick(buf); cmdpreview_save_undo(&cp_bufinfo.undo_info, buf); kv_push(cpinfo->buf_info, cp_bufinfo); @@ -2439,6 +2455,9 @@ static void cmdpreview_restore_state(CpInfo *cpinfo) u_blockfree(buf); cmdpreview_restore_undo(&cp_bufinfo.undo_info, buf); + buf->b_op_start = cp_bufinfo.save_b_op_start; + buf->b_op_end = cp_bufinfo.save_b_op_end; + if (cp_bufinfo.save_changedtick != buf_get_changedtick(buf)) { buf_set_changedtick(buf, cp_bufinfo.save_changedtick); } @@ -2529,10 +2548,10 @@ static bool cmdpreview_may_show(CommandLineState *s) cmdpreview_prepare(&cpinfo); // Open preview buffer if inccommand=split. - if (!icm_split) { - cmdpreview_bufnr = 0; - } else if ((cmdpreview_buf = cmdpreview_open_buf()) == NULL) { - abort(); + if (icm_split && (cmdpreview_buf = cmdpreview_open_buf()) == NULL) { + // Failed to create preview buffer, so disable preview. + set_string_option_direct(kOptInccommand, "nosplit", 0, SID_NONE); + icm_split = false; } // Setup preview namespace if it's not already set. if (!cmdpreview_ns) { @@ -2627,6 +2646,7 @@ static int command_line_changed(CommandLineState *s) if (s->firstc == ':' && current_sctx.sc_sid == 0 // only if interactive && *p_icm != NUL // 'inccommand' is set + && !exmode_active // not in ex mode && curbuf->b_p_ma // buffer is modifiable && cmdline_star == 0 // not typing a password && !vpeekc_any() @@ -2932,7 +2952,7 @@ char *getexline(int c, void *cookie, int indent, bool do_concat) { // When executing a register, remove ':' that's in front of each line. if (exec_from_reg && vpeekc() == ':') { - (void)vgetc(); + vgetc(); } return getcmdline(c, 1, indent, do_concat); @@ -3447,7 +3467,7 @@ void cmdline_ui_flush(void) // Put a character on the command line. Shifts the following text to the // right when "shift" is true. Used for CTRL-V, CTRL-K, etc. // "c" must be printable (fit in one display cell)! -void putcmdline(char c, int shift) +void putcmdline(char c, bool shift) { if (cmd_silent) { return; @@ -3494,7 +3514,7 @@ void unputcmdline(void) // part will be redrawn, otherwise it will not. If this function is called // twice in a row, then 'redraw' should be false and redrawcmd() should be // called afterwards. -void put_on_cmdline(const char *str, int len, int redraw) +void put_on_cmdline(const char *str, int len, bool redraw) { int i; int m; @@ -3704,7 +3724,7 @@ static bool cmdline_paste(int regname, bool literally, bool remcr) // When "literally" is true, insert literally. // When "literally" is false, insert as typed, but don't leave the command // line. -void cmdline_paste_str(const char *s, int literally) +void cmdline_paste_str(const char *s, bool literally) { if (literally) { put_on_cmdline(s, -1, true); @@ -4200,7 +4220,7 @@ int get_cmdline_firstc(void) int get_list_range(char **str, int *num1, int *num2) { int len; - int first = false; + bool first = false; varnumber_T num; *str = skipwhite((*str)); @@ -4274,7 +4294,7 @@ static int open_cmdwin(void) int save_restart_edit = restart_edit; int save_State = State; bool save_exmode = exmode_active; - int save_cmdmsg_rl = cmdmsg_rl; + bool save_cmdmsg_rl = cmdmsg_rl; // Can't do this when text or buffer is locked. // Can't do this recursively. Can't do it when typing a password. @@ -4302,25 +4322,52 @@ static int open_cmdwin(void) ga_clear(&winsizes); return K_IGNORE; } + // win_split() autocommands may have messed with the old window or buffer. + // Treat it as abandoning this command-line. + if (!win_valid(old_curwin) || curwin == old_curwin || !bufref_valid(&old_curbuf) + || old_curwin->w_buffer != old_curbuf.br_buf) { + beep_flush(); + ga_clear(&winsizes); + return Ctrl_C; + } // Don't let quitting the More prompt make this fail. got_int = false; - // Set "cmdwin_type" before any autocommands may mess things up. + // Set "cmdwin_..." variables before any autocommands may mess things up. cmdwin_type = get_cmdline_type(); cmdwin_level = ccline.level; + cmdwin_win = curwin; cmdwin_old_curwin = old_curwin; - // Create empty command-line buffer. - if (buf_open_scratch(0, _("[Command Line]")) == FAIL) { - // Some autocommand messed it up? - win_close(curwin, true, false); - ga_clear(&winsizes); + // Create empty command-line buffer. Be especially cautious of BufLeave + // autocommands from do_ecmd(), as cmdwin restrictions do not apply to them! + const int newbuf_status = buf_open_scratch(0, NULL); + const bool cmdwin_valid = win_valid(cmdwin_win); + if (newbuf_status == FAIL || !cmdwin_valid || curwin != cmdwin_win || !win_valid(old_curwin) + || !bufref_valid(&old_curbuf) || old_curwin->w_buffer != old_curbuf.br_buf) { + if (newbuf_status == OK) { + set_bufref(&bufref, curbuf); + } + if (cmdwin_valid && !last_window(cmdwin_win)) { + win_close(cmdwin_win, true, false); + } + // win_close() autocommands may have already deleted the buffer. + if (newbuf_status == OK && bufref_valid(&bufref) && bufref.br_buf != curbuf) { + close_buffer(NULL, bufref.br_buf, DOBUF_WIPE, false, false); + } + cmdwin_type = 0; + cmdwin_level = 0; + cmdwin_win = NULL; cmdwin_old_curwin = NULL; + beep_flush(); + ga_clear(&winsizes); return Ctrl_C; } + cmdwin_buf = curbuf; + // Command-line buffer has bufhidden=wipe, unlike a true "scratch" buffer. - set_option_value_give_err("bh", STATIC_CSTR_AS_OPTVAL("wipe"), OPT_LOCAL); + set_option_value_give_err(kOptBufhidden, STATIC_CSTR_AS_OPTVAL("wipe"), OPT_LOCAL); curbuf->b_p_ma = true; curwin->w_p_fen = false; curwin->w_p_rl = cmdmsg_rl; @@ -4338,7 +4385,7 @@ static int open_cmdwin(void) add_map("<Tab>", "<C-X><C-V>", MODE_INSERT, true); add_map("<Tab>", "a<C-X><C-V>", MODE_NORMAL, true); } - set_option_value_give_err("ft", STATIC_CSTR_AS_OPTVAL("vim"), OPT_LOCAL); + set_option_value_give_err(kOptFiletype, STATIC_CSTR_AS_OPTVAL("vim"), OPT_LOCAL); } curbuf->b_ro_locked--; @@ -4413,15 +4460,18 @@ static int open_cmdwin(void) cmdwin_type = 0; cmdwin_level = 0; + cmdwin_buf = NULL; + cmdwin_win = NULL; cmdwin_old_curwin = NULL; exmode_active = save_exmode; - // Safety check: The old window or buffer was deleted: It's a bug when - // this happens! - if (!win_valid(old_curwin) || !bufref_valid(&old_curbuf)) { + // Safety check: The old window or buffer was changed or deleted: It's a bug + // when this happens! + if (!win_valid(old_curwin) || !bufref_valid(&old_curbuf) + || old_curwin->w_buffer != old_curbuf.br_buf) { cmdwin_result = Ctrl_C; - emsg(_("E199: Active window or buffer deleted")); + emsg(_(e_active_window_or_buffer_changed_or_deleted)); } else { win_T *wp; // autocmds may abort script processing |