diff options
Diffstat (limited to 'src/nvim/ex_docmd.c')
-rw-r--r-- | src/nvim/ex_docmd.c | 113 |
1 files changed, 72 insertions, 41 deletions
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 4b7958efa5..0e9c8dcf01 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -294,7 +294,6 @@ int do_cmdline_cmd(const char *cmd) /// DOCMD_KEYTYPED - Don't reset KeyTyped. /// DOCMD_EXCRESET - Reset the exception environment (used for debugging). /// DOCMD_KEEPLINE - Store first typed line (for repeating with "."). -/// DOCMD_PREVIEW - During 'inccommand' preview. /// /// @param cookie argument for fgetline() /// @@ -593,11 +592,6 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags) next_cmdline = do_one_cmd(&cmdline_copy, flags, &cstack, cmd_getline, cmd_cookie); recursive--; - // Ignore trailing '|'-separated commands in preview-mode ('inccommand'). - if ((State & MODE_CMDPREVIEW) && (flags & DOCMD_PREVIEW)) { - next_cmdline = NULL; - } - if (cmd_cookie == (void *)&cmd_loop_cookie) { // Use "current_line" from "cmd_loop_cookie", it may have been // incremented when defining a function. @@ -1578,9 +1572,11 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er /// /// @param eap Ex-command arguments /// @param cmdinfo Command parse information -void execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo) +/// @param preview Execute command preview callback instead of actual command +int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview) { char *errormsg = NULL; + int retv = 0; #define ERROR(msg) \ do { \ @@ -1698,11 +1694,17 @@ void execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo) // Execute the command if (IS_USER_CMDIDX(eap->cmdidx)) { // Execute a user-defined command. - do_ucmd(eap); + retv = do_ucmd(eap, preview); } else { - // Call the function to execute the command. + // Call the function to execute the command or the preview callback. eap->errmsg = NULL; - (cmdnames[eap->cmdidx].cmd_func)(eap); + + if (preview) { + retv = (cmdnames[eap->cmdidx].cmd_preview_func)(eap, cmdpreview_get_ns(), + cmdpreview_get_bufnr()); + } else { + (cmdnames[eap->cmdidx].cmd_func)(eap); + } if (eap->errmsg != NULL) { errormsg = _(eap->errmsg); } @@ -1718,6 +1720,7 @@ end: if (eap->did_sandbox) { sandbox--; } + return retv; #undef ERROR } @@ -2350,7 +2353,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter /* * Execute a user-defined command. */ - do_ucmd(&ea); + do_ucmd(&ea, false); } else { /* * Call the function to execute the command. @@ -2751,6 +2754,8 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent) { int address_count = 1; linenr_T lnum; + bool need_check_cursor = false; + int ret = FAIL; // Repeat for all ',' or ';' separated addresses. for (;;) { @@ -2760,7 +2765,7 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent) lnum = get_address(eap, &eap->cmd, eap->addr_type, eap->skip, silent, eap->addr_count == 0, address_count++); if (eap->cmd == NULL) { // error detected - return FAIL; + goto theend; } if (lnum == MAXLNUM) { if (*eap->cmd == '%') { // '%' - all lines @@ -2799,14 +2804,14 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent) // there is no Vim command which uses '%' and // ADDR_WINDOWS or ADDR_TABS *errormsg = _(e_invrange); - return FAIL; + goto theend; } break; case ADDR_TABS_RELATIVE: case ADDR_UNSIGNED: case ADDR_QUICKFIX: *errormsg = _(e_invrange); - return FAIL; + goto theend; case ADDR_ARGUMENTS: if (ARGCOUNT == 0) { eap->line1 = eap->line2 = 0; @@ -2831,19 +2836,19 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent) // '*' - visual area if (eap->addr_type != ADDR_LINES) { *errormsg = _(e_invrange); - return FAIL; + goto theend; } eap->cmd++; if (!eap->skip) { pos_T *fp = getmark('<', false); if (check_mark(fp) == FAIL) { - return FAIL; + goto theend; } eap->line1 = fp->lnum; fp = getmark('>', false); if (check_mark(fp) == FAIL) { - return FAIL; + goto theend; } eap->line2 = fp->lnum; eap->addr_count++; @@ -2857,11 +2862,14 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent) if (*eap->cmd == ';') { if (!eap->skip) { curwin->w_cursor.lnum = eap->line2; + // Don't leave the cursor on an illegal line or column, but do // accept zero as address, so 0;/PATTERN/ works correctly. + // Check the cursor position before returning. if (eap->line2 > 0) { check_cursor(); } + need_check_cursor = true; } } else if (*eap->cmd != ',') { break; @@ -2877,7 +2885,13 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent) eap->addr_count = 0; } } - return OK; + ret = OK; + +theend: + if (need_check_cursor) { + check_cursor(); + } + return ret; } /// Check for an Ex command with optional tail. @@ -5530,8 +5544,8 @@ char *uc_validate_name(char *name) /// /// @return OK if the command is created, FAIL otherwise. int uc_add_command(char *name, size_t name_len, char *rep, uint32_t argt, long def, int flags, - int compl, char *compl_arg, LuaRef compl_luaref, cmd_addr_T addr_type, - LuaRef luaref, bool force) + int compl, char *compl_arg, LuaRef compl_luaref, LuaRef preview_luaref, + cmd_addr_T addr_type, LuaRef luaref, bool force) FUNC_ATTR_NONNULL_ARG(1, 3) { ucmd_T *cmd = NULL; @@ -5586,6 +5600,7 @@ int uc_add_command(char *name, size_t name_len, char *rep, uint32_t argt, long d XFREE_CLEAR(cmd->uc_compl_arg); NLUA_CLEAR_REF(cmd->uc_luaref); NLUA_CLEAR_REF(cmd->uc_compl_luaref); + NLUA_CLEAR_REF(cmd->uc_preview_luaref); break; } @@ -5618,6 +5633,7 @@ int uc_add_command(char *name, size_t name_len, char *rep, uint32_t argt, long d nlua_set_sctx(&cmd->uc_script_ctx); cmd->uc_compl_arg = (char_u *)compl_arg; cmd->uc_compl_luaref = compl_luaref; + cmd->uc_preview_luaref = preview_luaref; cmd->uc_addr_type = addr_type; cmd->uc_luaref = luaref; @@ -5628,6 +5644,7 @@ fail: xfree(compl_arg); NLUA_CLEAR_REF(luaref); NLUA_CLEAR_REF(compl_luaref); + NLUA_CLEAR_REF(preview_luaref); return FAIL; } @@ -6060,8 +6077,7 @@ static void ex_command(exarg_T *eap) } else if (compl > 0 && (argt & EX_EXTRA) == 0) { emsg(_(e_complete_used_without_nargs)); } else { - uc_add_command(name, name_len, p, argt, def, flags, compl, - compl_arg, LUA_NOREF, + uc_add_command(name, name_len, p, argt, def, flags, compl, compl_arg, LUA_NOREF, LUA_NOREF, addr_type_arg, LUA_NOREF, eap->forceit); } } @@ -6081,6 +6097,7 @@ void free_ucmd(ucmd_T *cmd) xfree(cmd->uc_compl_arg); NLUA_CLEAR_REF(cmd->uc_compl_luaref); NLUA_CLEAR_REF(cmd->uc_luaref); + NLUA_CLEAR_REF(cmd->uc_preview_luaref); } /// Clear all user commands for "gap". @@ -6611,7 +6628,7 @@ size_t uc_mods(char *buf) return result; } -static void do_ucmd(exarg_T *eap) +static int do_ucmd(exarg_T *eap, bool preview) { char *buf; char *p; @@ -6632,9 +6649,14 @@ static void do_ucmd(exarg_T *eap) cmd = USER_CMD_GA(&curbuf->b_ucmds, eap->useridx); } + if (preview) { + assert(cmd->uc_preview_luaref > 0); + return nlua_do_ucmd(cmd, eap, true); + } + if (cmd->uc_luaref > 0) { - nlua_do_ucmd(cmd, eap); - return; + nlua_do_ucmd(cmd, eap, false); + return 0; } /* @@ -6729,6 +6751,8 @@ static void do_ucmd(exarg_T *eap) } xfree(buf); xfree(split_buf); + + return 0; } static char *expand_user_command_name(int idx) @@ -6785,7 +6809,8 @@ char *get_user_cmd_flags(expand_T *xp, int idx) { static char *user_cmd_flags[] = { "addr", "bang", "bar", "buffer", "complete", "count", - "nargs", "range", "register", "keepscript" }; + "nargs", "range", "register", + "keepscript" }; if (idx >= (int)ARRAY_SIZE(user_cmd_flags)) { return NULL; @@ -8557,6 +8582,18 @@ static void ex_submagic(exarg_T *eap) p_magic = magic_save; } +/// ":smagic" and ":snomagic" preview callback. +static int ex_submagic_preview(exarg_T *eap, long cmdpreview_ns, handle_T cmdpreview_bufnr) +{ + int magic_save = p_magic; + + p_magic = (eap->cmdidx == CMD_smagic); + int retv = ex_substitute_preview(eap, cmdpreview_ns, cmdpreview_bufnr); + p_magic = magic_save; + + return retv; +} + /// ":join". static void ex_join(exarg_T *eap) { @@ -8798,7 +8835,7 @@ static void ex_redir(exarg_T *eap) /// ":redraw": force redraw static void ex_redraw(exarg_T *eap) { - if (State & MODE_CMDPREVIEW) { + if (cmdpreview) { return; // Ignore :redraw during 'inccommand' preview. #9777 } int r = RedrawingDisabled; @@ -8832,7 +8869,7 @@ static void ex_redraw(exarg_T *eap) /// ":redrawstatus": force redraw of status line(s) and window bar(s) static void ex_redrawstatus(exarg_T *eap) { - if (State & MODE_CMDPREVIEW) { + if (cmdpreview) { return; // Ignore :redrawstatus during 'inccommand' preview. #9777 } int r = RedrawingDisabled; @@ -10096,22 +10133,15 @@ bool cmd_can_preview(char *cmd) if (*ea.cmd == '*') { ea.cmd = skipwhite(ea.cmd + 1); } - char *end = find_ex_command(&ea, NULL); - switch (ea.cmdidx) { - case CMD_substitute: - case CMD_smagic: - case CMD_snomagic: - // Only preview once the pattern delimiter has been typed - if (*end && !ASCII_ISALNUM(*end)) { - return true; - } - break; - default: - break; + if (find_ex_command(&ea, NULL) == NULL || ea.cmdidx == CMD_SIZE) { + return false; + } else if (!IS_USER_CMDIDX(ea.cmdidx)) { + // find_ex_command sets the flags for user commands automatically + ea.argt = cmdnames[(int)ea.cmdidx].cmd_argt; } - return false; + return (ea.argt & EX_PREVIEW); } /// Gets a map of maps describing user-commands defined for buffer `buf` or @@ -10138,6 +10168,7 @@ Dictionary commands_array(buf_T *buf) PUT(d, "bar", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_TRLBAR))); PUT(d, "register", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_REGSTR))); PUT(d, "keepscript", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_KEEPSCRIPT))); + PUT(d, "preview", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_PREVIEW))); switch (cmd->uc_argt & (EX_EXTRA | EX_NOSPC | EX_NEEDARG)) { case 0: |