diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/command.c | 8 | ||||
-rw-r--r-- | src/nvim/ex_cmds_defs.h | 23 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 191 | ||||
-rw-r--r-- | src/nvim/lua/executor.c | 12 |
4 files changed, 120 insertions, 114 deletions
diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index a7115c09a3..26aa26004f 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -284,8 +284,6 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error { exarg_T ea; memset(&ea, 0, sizeof(ea)); - ea.verbose_save = -1; - ea.save_msg_silent = -1; CmdParseInfo cmdinfo; memset(&cmdinfo, 0, sizeof(cmdinfo)); @@ -514,9 +512,9 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error if (HAS_KEY(mods.verbose)) { if (mods.verbose.type != kObjectTypeInteger) { VALIDATION_ERROR("'mods.verbose' must be a Integer"); - } else if (mods.verbose.data.integer >= 0) { + } else if ((int)mods.verbose.data.integer >= 0) { // Silently ignore negative integers to allow mods.verbose to be set to -1. - cmdinfo.verbose = mods.verbose.data.integer; + cmdinfo.verbose = (int)mods.verbose.data.integer; } } @@ -662,7 +660,7 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin kv_printf(cmdline, "%dtab ", cmdinfo->cmdmod.tab - 1); } if (cmdinfo->verbose != -1) { - kv_printf(cmdline, "%ldverbose ", cmdinfo->verbose); + kv_printf(cmdline, "%dverbose ", cmdinfo->verbose); } if (cmdinfo->emsg_silent) { diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h index a5c9c6be2d..db76851c97 100644 --- a/src/nvim/ex_cmds_defs.h +++ b/src/nvim/ex_cmds_defs.h @@ -209,10 +209,6 @@ struct exarg { LineGetter getline; ///< Function used to get the next line void *cookie; ///< argument for getline() cstack_T *cstack; ///< condition stack for ":if" etc. - long verbose_save; ///< saved value of p_verbose - int save_msg_silent; ///< saved value of msg_silent - int did_esilent; ///< how many times emsg_silent was incremented - bool did_sandbox; ///< when true did sandbox++ }; #define FORCE_BIN 1 // ":edit ++bin file" @@ -251,6 +247,7 @@ struct expand { /// flag. This needs to be saved for recursive commands, put them in a /// structure for easy manipulation. typedef struct { + int cmod_flags; ///< CMOD_ flags, see below int split; ///< flags for win_split() int tab; ///< > 0 when ":tab" was used bool browse; ///< true to invoke file dialog @@ -262,18 +259,32 @@ typedef struct { bool keeppatterns; ///< true when ":keeppatterns" was used bool lockmarks; ///< true when ":lockmarks" was used bool noswapfile; ///< true when ":noswapfile" was used - char *save_ei; ///< saved value of 'eventignore' regmatch_T filter_regmatch; ///< set by :filter /pat/ bool filter_force; ///< set for :filter! + + int cmod_verbose; ///< non-zero to set 'verbose', -1 is used for zero override + + // values for undo_cmdmod() + char_u *cmod_save_ei; ///< saved value of 'eventignore' + int cmod_did_sandbox; ///< set when "sandbox" was incremented + long cmod_verbose_save; ///< if 'verbose' was set: value of p_verbose plus one + int cmod_save_msg_silent; ///< if non-zero: saved value of msg_silent + 1 + int cmod_did_esilent; ///< incremented when emsg_silent is } cmdmod_T; +#define CMOD_SANDBOX 0x01 +#define CMOD_SILENT 0x02 +#define CMOD_ERRSILENT 0x04 +#define CMOD_UNSILENT 0x08 +#define CMOD_NOAUTOCMD 0x10 + /// Stores command modifier info used by `nvim_parse_cmd` typedef struct { bool silent; bool emsg_silent; bool sandbox; bool noautocmd; - long verbose; + int verbose; ///< unlike cmod_verbose, -1 is used when unspecified and 0 for zero override cmdmod_T cmdmod; struct { bool file; diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index bbac74fc55..857723a336 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -1431,31 +1431,12 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er } after_modifier = eap->cmd; - // Revert the side-effects of `parse_command_modifiers` - if (eap->save_msg_silent != -1) { - cmdinfo->silent = !!msg_silent; - msg_silent = eap->save_msg_silent; - eap->save_msg_silent = -1; - } - if (eap->did_esilent) { - cmdinfo->emsg_silent = true; - emsg_silent--; - eap->did_esilent = false; - } - if (eap->did_sandbox) { - cmdinfo->sandbox = true; - sandbox--; - eap->did_sandbox = false; - } - if (cmdmod.save_ei != NULL) { - cmdinfo->noautocmd = true; - set_string_option_direct("ei", -1, (char_u *)cmdmod.save_ei, OPT_FREE, SID_NONE); - free_string_option((char_u *)cmdmod.save_ei); - } - if (eap->verbose_save != -1) { - cmdinfo->verbose = p_verbose; - p_verbose = eap->verbose_save; - eap->verbose_save = -1; + cmdinfo->silent = cmdmod.cmod_flags & CMOD_SILENT; + cmdinfo->emsg_silent = cmdmod.cmod_flags & CMOD_ERRSILENT; + cmdinfo->sandbox = cmdmod.cmod_flags & CMOD_SANDBOX; + cmdinfo->noautocmd = cmdmod.cmod_flags & CMOD_NOAUTOCMD; + if (cmdmod.cmod_verbose != 0) { + cmdinfo->verbose = cmdmod.cmod_verbose < 0 ? 0 : cmdmod.cmod_verbose; } else { cmdinfo->verbose = -1; } @@ -1586,25 +1567,21 @@ int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview) // Apply command modifiers if (cmdinfo->silent) { - eap->save_msg_silent = msg_silent; - msg_silent++; + cmdmod.cmod_flags |= CMOD_SILENT; } if (cmdinfo->emsg_silent) { - eap->did_esilent = true; - emsg_silent++; + cmdmod.cmod_flags |= CMOD_ERRSILENT; } if (cmdinfo->sandbox) { - eap->did_sandbox = true; - sandbox++; + cmdmod.cmod_flags |= CMOD_SANDBOX; } if (cmdinfo->noautocmd) { - cmdmod.save_ei = (char *)vim_strsave(p_ei); - set_string_option_direct("ei", -1, (char_u *)"all", OPT_FREE, SID_NONE); + cmdmod.cmod_flags |= CMOD_NOAUTOCMD; } - if (cmdinfo->verbose != -1) { - eap->verbose_save = p_verbose; - p_verbose = cmdinfo->verbose; + if (cmdinfo->verbose >= 0) { + cmdmod.cmod_verbose = cmdinfo->verbose == 0 ? -1 : cmdinfo->verbose; } + apply_cmdmod(&cmdmod); if (!MODIFIABLE(curbuf) && (eap->argt & EX_MODIFY) // allow :put in terminals @@ -1712,11 +1689,8 @@ end: emsg(errormsg); } // Undo command modifiers - undo_cmdmod(eap, msg_scroll); + undo_cmdmod(msg_scroll); cmdmod = save_cmdmod; - if (eap->did_sandbox) { - sandbox--; - } return retv; #undef ERROR } @@ -1791,6 +1765,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter if (parse_command_modifiers(&ea, &errormsg, false) == FAIL) { goto doend; } + apply_cmdmod(&cmdmod); after_modifier = ea.cmd; @@ -2337,12 +2312,12 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter // The :try command saves the emsg_silent flag, reset it here when // ":silent! try" was used, it should only apply to :try itself. - if (ea.cmdidx == CMD_try && ea.did_esilent > 0) { - emsg_silent -= ea.did_esilent; + if (ea.cmdidx == CMD_try && cmdmod.cmod_did_esilent > 0) { + emsg_silent -= cmdmod.cmod_did_esilent; if (emsg_silent < 0) { emsg_silent = 0; } - ea.did_esilent = 0; + cmdmod.cmod_did_esilent = 0; } // 7. Execute the command. @@ -2402,15 +2377,11 @@ doend: (ea.cmdidx != CMD_SIZE && !IS_USER_CMDIDX(ea.cmdidx)) ? cmdnames[(int)ea.cmdidx].cmd_name : NULL); - undo_cmdmod(&ea, save_msg_scroll); + undo_cmdmod(save_msg_scroll); cmdmod = save_cmdmod; reg_executing = save_reg_executing; pending_end_reg_executing = save_pending_end_reg_executing; - if (ea.did_sandbox) { - sandbox--; - } - if (ea.nextcmd && *ea.nextcmd == NUL) { // not really a next command ea.nextcmd = NULL; } @@ -2438,21 +2409,21 @@ char *ex_errmsg(const char *const msg, const char *const arg) /// - Set ex_pressedreturn for an empty command line. /// - set msg_silent for ":silent" /// - set 'eventignore' to "all" for ":noautocmd" -/// - set p_verbose for ":verbose" -/// - Increment "sandbox" for ":sandbox" /// /// @param skip_only if true, the global variables are not changed, except for /// "cmdmod". /// @param[out] errormsg potential error message. /// +/// Call apply_cmdmod() to get the side effects of the modifiers: +/// - Increment "sandbox" for ":sandbox" +/// - set p_verbose for ":verbose" +/// /// @return FAIL when the command is not to be executed. int parse_command_modifiers(exarg_T *eap, char **errormsg, bool skip_only) { char *p; memset(&cmdmod, 0, sizeof(cmdmod)); - eap->verbose_save = -1; - eap->save_msg_silent = -1; // Repeat until no more command modifiers are found. for (;;) { @@ -2590,12 +2561,7 @@ int parse_command_modifiers(exarg_T *eap, char **errormsg, bool skip_only) case 'n': if (checkforcmd(&eap->cmd, "noautocmd", 3)) { - if (cmdmod.save_ei == NULL && !skip_only) { - // Set 'eventignore' to "all". Restore the - // existing option value later. - cmdmod.save_ei = (char *)vim_strsave(p_ei); - set_string_option_direct("ei", -1, (char_u *)"all", OPT_FREE, SID_NONE); - } + cmdmod.cmod_flags |= CMOD_NOAUTOCMD; continue; } if (!checkforcmd(&eap->cmd, "noswapfile", 3)) { @@ -2613,30 +2579,17 @@ int parse_command_modifiers(exarg_T *eap, char **errormsg, bool skip_only) case 's': if (checkforcmd(&eap->cmd, "sandbox", 3)) { - if (!skip_only) { - if (!eap->did_sandbox) { - sandbox++; - } - eap->did_sandbox = true; - } + cmdmod.cmod_flags |= CMOD_SANDBOX; continue; } if (!checkforcmd(&eap->cmd, "silent", 3)) { break; } - if (!skip_only) { - if (eap->save_msg_silent == -1) { - eap->save_msg_silent = msg_silent; - } - msg_silent++; - } + cmdmod.cmod_flags |= CMOD_SILENT; if (*eap->cmd == '!' && !ascii_iswhite(eap->cmd[-1])) { // ":silent!", but not "silent !cmd" eap->cmd = skipwhite(eap->cmd + 1); - if (!skip_only) { - emsg_silent++; - eap->did_esilent++; - } + cmdmod.cmod_flags |= CMOD_ERRSILENT; } continue; @@ -2669,12 +2622,7 @@ int parse_command_modifiers(exarg_T *eap, char **errormsg, bool skip_only) if (!checkforcmd(&eap->cmd, "unsilent", 3)) { break; } - if (!skip_only) { - if (eap->save_msg_silent == -1) { - eap->save_msg_silent = msg_silent; - } - msg_silent = 0; - } + cmdmod.cmod_flags |= CMOD_UNSILENT; continue; case 'v': @@ -2685,15 +2633,13 @@ int parse_command_modifiers(exarg_T *eap, char **errormsg, bool skip_only) if (!checkforcmd(&p, "verbose", 4)) { break; } - if (!skip_only) { - if (eap->verbose_save < 0) { - eap->verbose_save = p_verbose; - } - if (ascii_isdigit(*eap->cmd)) { - p_verbose = atoi(eap->cmd); - } else { - p_verbose = 1; + if (ascii_isdigit(*eap->cmd)) { + cmdmod.cmod_verbose = atoi((char *)eap->cmd); + if (cmdmod.cmod_verbose == 0) { + cmdmod.cmod_verbose = -1; } + } else { + cmdmod.cmod_verbose = 1; } eap->cmd = p; continue; @@ -2704,29 +2650,75 @@ int parse_command_modifiers(exarg_T *eap, char **errormsg, bool skip_only) return OK; } +/// Apply the command modifiers. Saves current state in "cmdmod", call +/// undo_cmdmod() later. +static void apply_cmdmod(cmdmod_T *cmod) +{ + if ((cmod->cmod_flags & CMOD_SANDBOX) && !cmod->cmod_did_sandbox) { + sandbox++; + cmod->cmod_did_sandbox = true; + } + if (cmod->cmod_verbose != 0) { + if (cmod->cmod_verbose_save == 0) { + cmod->cmod_verbose_save = p_verbose + 1; + } + p_verbose = cmod->cmod_verbose < 0 ? 0 : cmod->cmod_verbose; + } + + if ((cmod->cmod_flags & (CMOD_SILENT | CMOD_UNSILENT)) + && cmod->cmod_save_msg_silent == 0) { + cmod->cmod_save_msg_silent = msg_silent + 1; + } + if (cmod->cmod_flags & CMOD_SILENT) { + msg_silent++; + } + if (cmod->cmod_flags & CMOD_UNSILENT) { + msg_silent = 0; + } + + if (cmod->cmod_flags & CMOD_ERRSILENT) { + emsg_silent++; + cmod->cmod_did_esilent++; + } + + if ((cmod->cmod_flags & CMOD_NOAUTOCMD) && cmdmod.cmod_save_ei == NULL) { + // Set 'eventignore' to "all". + // First save the existing option value for restoring it later. + cmdmod.cmod_save_ei = vim_strsave(p_ei); + set_string_option_direct("ei", -1, (char_u *)"all", OPT_FREE, SID_NONE); + } +} + /// Undo and free contents of "cmdmod". -static void undo_cmdmod(const exarg_T *eap, int save_msg_scroll) +static void undo_cmdmod(int save_msg_scroll) FUNC_ATTR_NONNULL_ALL { - if (eap->verbose_save >= 0) { - p_verbose = eap->verbose_save; + if (cmdmod.cmod_verbose_save > 0) { + p_verbose = cmdmod.cmod_verbose_save - 1; + cmdmod.cmod_verbose_save = 0; + } + + if (cmdmod.cmod_did_sandbox) { + sandbox--; + cmdmod.cmod_did_sandbox = false; } - if (cmdmod.save_ei != NULL) { + if (cmdmod.cmod_save_ei != NULL) { // Restore 'eventignore' to the value before ":noautocmd". - set_string_option_direct("ei", -1, (char_u *)cmdmod.save_ei, OPT_FREE, SID_NONE); - free_string_option((char_u *)cmdmod.save_ei); + set_string_option_direct("ei", -1, (char_u *)cmdmod.cmod_save_ei, OPT_FREE, SID_NONE); + free_string_option((char_u *)cmdmod.cmod_save_ei); + cmdmod.cmod_save_ei = NULL; } vim_regfree(cmdmod.filter_regmatch.regprog); - if (eap->save_msg_silent != -1) { + if (cmdmod.cmod_save_msg_silent > 0) { // messages could be enabled for a serious error, need to check if the // counters don't become negative - if (!did_emsg || msg_silent > eap->save_msg_silent) { - msg_silent = eap->save_msg_silent; + if (!did_emsg || msg_silent > cmdmod.cmod_save_msg_silent - 1) { + msg_silent = cmdmod.cmod_save_msg_silent - 1; } - emsg_silent -= eap->did_esilent; + emsg_silent -= cmdmod.cmod_did_esilent; if (emsg_silent < 0) { emsg_silent = 0; } @@ -2739,6 +2731,9 @@ static void undo_cmdmod(const exarg_T *eap, int save_msg_scroll) if (redirecting()) { msg_col = 0; } + + cmdmod.cmod_save_msg_silent = 0; + cmdmod.cmod_did_esilent = 0; } } diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index bd06123d5f..ac68c02d8b 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -1920,7 +1920,9 @@ int nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap, bool preview) lua_pushinteger(lstate, cmdmod.tab); lua_setfield(lstate, -2, "tab"); - lua_pushinteger(lstate, eap->verbose_save != -1 ? p_verbose : -1); + lua_pushinteger(lstate, (cmdmod.cmod_verbose != 0 + ? cmdmod.cmod_verbose < 0 ? 0 : cmdmod.cmod_verbose + : -1)); lua_setfield(lstate, -2, "verbose"); if (cmdmod.split & WSP_ABOVE) { @@ -1938,13 +1940,13 @@ int nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap, bool preview) lua_pushboolean(lstate, cmdmod.split & WSP_VERT); lua_setfield(lstate, -2, "vertical"); - lua_pushboolean(lstate, eap->save_msg_silent != -1 ? (msg_silent != 0) : 0); + lua_pushboolean(lstate, cmdmod.cmod_flags & CMOD_SILENT); lua_setfield(lstate, -2, "silent"); - lua_pushboolean(lstate, eap->did_esilent); + lua_pushboolean(lstate, cmdmod.cmod_flags & CMOD_ERRSILENT); lua_setfield(lstate, -2, "emsg_silent"); - lua_pushboolean(lstate, eap->did_sandbox); + lua_pushboolean(lstate, cmdmod.cmod_flags & CMOD_SANDBOX); lua_setfield(lstate, -2, "sandbox"); - lua_pushboolean(lstate, cmdmod.save_ei != NULL); + lua_pushboolean(lstate, cmdmod.cmod_flags & CMOD_NOAUTOCMD); lua_setfield(lstate, -2, "noautocmd"); typedef struct { |