diff options
author | Lewis Russell <lewis6991@gmail.com> | 2022-08-03 11:44:17 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-03 11:44:17 +0100 |
commit | 5ee56f95c7c4aa588b37fec297e21a040a8d2367 (patch) | |
tree | 571172d70e8ca74f26ca85b9ff01dc8140daa039 | |
parent | b8dcbcc732baf84fc48d6b272c3ade0bcb129b3b (diff) | |
parent | dc2745e9eac08d4537c409a8700c37bc9d42d6de (diff) | |
download | rneovim-5ee56f95c7c4aa588b37fec297e21a040a8d2367.tar.gz rneovim-5ee56f95c7c4aa588b37fec297e21a040a8d2367.tar.bz2 rneovim-5ee56f95c7c4aa588b37fec297e21a040a8d2367.zip |
Merge pull request #19540 from lewis6991/cmd_refactor
-rw-r--r-- | src/nvim/api/command.c | 5 | ||||
-rw-r--r-- | src/nvim/ex_cmds_defs.h | 56 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 606 |
3 files changed, 304 insertions, 363 deletions
diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index 33efa6b326..5ab0beec9d 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -505,6 +505,11 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error OBJ_TO_BOOL(cmdinfo.magic.file, magic.file, ea.argt & EX_XFILE, "'magic.file'"); OBJ_TO_BOOL(cmdinfo.magic.bar, magic.bar, ea.argt & EX_TRLBAR, "'magic.bar'"); + if (cmdinfo.magic.file) { + ea.argt |= EX_XFILE; + } else { + ea.argt &= ~EX_XFILE; + } } else { cmdinfo.magic.file = ea.argt & EX_XFILE; cmdinfo.magic.bar = ea.argt & EX_TRLBAR; diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h index 052926fa1f..e80e47bcff 100644 --- a/src/nvim/ex_cmds_defs.h +++ b/src/nvim/ex_cmds_defs.h @@ -37,34 +37,34 @@ // 4. Add documentation in ../doc/xxx.txt. Add a tag for both the short and // long name of the command. -#define EX_RANGE 0x001 // allow a linespecs -#define EX_BANG 0x002 // allow a ! after the command name -#define EX_EXTRA 0x004 // allow extra args after command name -#define EX_XFILE 0x008 // expand wildcards in extra part -#define EX_NOSPC 0x010 // no spaces allowed in the extra part -#define EX_DFLALL 0x020 // default file range is 1,$ -#define EX_WHOLEFOLD 0x040 // extend range to include whole fold also - // when less than two numbers given -#define EX_NEEDARG 0x080 // argument required -#define EX_TRLBAR 0x100 // check for trailing vertical bar -#define EX_REGSTR 0x200 // allow "x for register designation -#define EX_COUNT 0x400 // allow count in argument, after command -#define EX_NOTRLCOM 0x800 // no trailing comment allowed -#define EX_ZEROR 0x1000 // zero line number allowed -#define EX_CTRLV 0x2000 // do not remove CTRL-V from argument -#define EX_CMDARG 0x4000 // allow "+command" argument -#define EX_BUFNAME 0x8000 // accepts buffer name -#define EX_BUFUNL 0x10000 // accepts unlisted buffer too -#define EX_ARGOPT 0x20000 // allow "++opt=val" argument -#define EX_SBOXOK 0x40000 // allowed in the sandbox -#define EX_CMDWIN 0x80000 // allowed in cmdline window -#define EX_MODIFY 0x100000 // forbidden in non-'modifiable' buffer -#define EX_FLAGS 0x200000 // allow flags after count in argument -#define EX_LOCK_OK 0x1000000 // command can be executed when textlock is - // set; when missing disallows editing another - // buffer when current buffer is locked -#define EX_KEEPSCRIPT 0x4000000 // keep sctx of where command was invoked -#define EX_PREVIEW 0x8000000 // allow incremental command preview +#define EX_RANGE 0x001u // allow a linespecs +#define EX_BANG 0x002u // allow a ! after the command name +#define EX_EXTRA 0x004u // allow extra args after command name +#define EX_XFILE 0x008u // expand wildcards in extra part +#define EX_NOSPC 0x010u // no spaces allowed in the extra part +#define EX_DFLALL 0x020u // default file range is 1,$ +#define EX_WHOLEFOLD 0x040u // extend range to include whole fold also + // when less than two numbers given +#define EX_NEEDARG 0x080u // argument required +#define EX_TRLBAR 0x100u // check for trailing vertical bar +#define EX_REGSTR 0x200u // allow "x for register designation +#define EX_COUNT 0x400u // allow count in argument, after command +#define EX_NOTRLCOM 0x800u // no trailing comment allowed +#define EX_ZEROR 0x1000u // zero line number allowed +#define EX_CTRLV 0x2000u // do not remove CTRL-V from argument +#define EX_CMDARG 0x4000u // allow "+command" argument +#define EX_BUFNAME 0x8000u // accepts buffer name +#define EX_BUFUNL 0x10000u // accepts unlisted buffer too +#define EX_ARGOPT 0x20000u // allow "++opt=val" argument +#define EX_SBOXOK 0x40000u // allowed in the sandbox +#define EX_CMDWIN 0x80000u // allowed in cmdline window +#define EX_MODIFY 0x100000u // forbidden in non-'modifiable' buffer +#define EX_FLAGS 0x200000u // allow flags after count in argument +#define EX_LOCK_OK 0x1000000u // command can be executed when textlock is + // set; when missing disallows editing another + // buffer when current buffer is locked +#define EX_KEEPSCRIPT 0x4000000u // keep sctx of where command was invoked +#define EX_PREVIEW 0x8000000u // allow incremental command preview #define EX_FILES (EX_XFILE | EX_EXTRA) // multiple extra files allowed #define EX_FILE1 (EX_FILES | EX_NOSPC) // 1 file, defaults to current file #define EX_WORD1 (EX_EXTRA | EX_NOSPC) // one extra word allowed diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index a7d91a47d7..31314fd8b9 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -1563,69 +1563,12 @@ err: return false; } -/// Execute an Ex command using parsed command line information. -/// Does not do any validation of the Ex command arguments. -/// -/// @param eap Ex-command arguments -/// @param cmdinfo Command parse information -/// @param preview Execute command preview callback instead of actual command -int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview) +static int execute_cmd0(int *retv, exarg_T *eap, char **errormsg, bool preview) { - char *errormsg = NULL; - int retv = 0; - -#define ERROR(msg) \ - do { \ - errormsg = msg; \ - goto end; \ - } while (0) - - cmdmod_T save_cmdmod = cmdmod; - cmdmod = cmdinfo->cmdmod; - - // Apply command modifiers - apply_cmdmod(&cmdmod); - - if (!MODIFIABLE(curbuf) && (eap->argt & EX_MODIFY) - // allow :put in terminals - && !(curbuf->terminal && eap->cmdidx == CMD_put)) { - ERROR(_(e_modifiable)); - } - if (!IS_USER_CMDIDX(eap->cmdidx)) { - if (cmdwin_type != 0 && !(eap->argt & EX_CMDWIN)) { - // Command not allowed in the command line window - ERROR(_(e_cmdwin)); - } - if (text_locked() && !(eap->argt & EX_LOCK_OK)) { - // Command not allowed when text is locked - ERROR(_(get_text_locked_msg())); - } - } - // Disallow editing another buffer when "curbuf->b_ro_locked" is set. - // Do allow ":checktime" (it is postponed). - // Do allow ":edit" (check for an argument later). - // Do allow ":file" with no arguments - if (!(eap->argt & EX_CMDWIN) - && eap->cmdidx != CMD_checktime - && eap->cmdidx != CMD_edit - && !(eap->cmdidx == CMD_file && *eap->arg == NUL) - && !IS_USER_CMDIDX(eap->cmdidx) - && curbuf_locked()) { - ERROR(_(e_cannot_edit_other_buf)); - } - - if (((eap->argt & EX_WHOLEFOLD) || eap->addr_count >= 2) && !global_busy - && eap->addr_type == ADDR_LINES) { - // Put the first line at the start of a closed fold, put the last line - // at the end of a closed fold. - (void)hasFolding(eap->line1, &eap->line1, NULL); - (void)hasFolding(eap->line2, NULL, &eap->line2); - } - // If filename expansion is enabled, expand filenames - if (cmdinfo->magic.file) { - if (expand_filename(eap, eap->cmdlinep, &errormsg) == FAIL) { - goto end; + if (eap->argt & EX_XFILE) { + if (expand_filename(eap, eap->cmdlinep, errormsg) == FAIL) { + return FAIL; } } @@ -1670,29 +1613,104 @@ int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview) eap->arg = eap->args[0]; } if (eap->line2 < 0) { // failed - goto end; + return FAIL; } } + // The :try command saves the emsg_silent flag, reset it here when + // ":silent! try" was used, it should only apply to :try itself. + if (eap->cmdidx == CMD_try && cmdmod.cmod_did_esilent > 0) { + emsg_silent -= cmdmod.cmod_did_esilent; + if (emsg_silent < 0) { + emsg_silent = 0; + } + cmdmod.cmod_did_esilent = 0; + } + // Execute the command if (IS_USER_CMDIDX(eap->cmdidx)) { // Execute a user-defined command. - retv = do_ucmd(eap, preview); + *retv = do_ucmd(eap, preview); } else { // Call the function to execute the command or the preview callback. eap->errmsg = NULL; if (preview) { - retv = (cmdnames[eap->cmdidx].cmd_preview_func)(eap, cmdpreview_get_ns(), - cmdpreview_get_bufnr()); + *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); + *errormsg = _(eap->errmsg); } } + return OK; +} + +/// Execute an Ex command using parsed command line information. +/// Does not do any validation of the Ex command arguments. +/// +/// @param eap Ex-command arguments +/// @param cmdinfo Command parse information +/// @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 { \ + errormsg = msg; \ + goto end; \ + } while (0) + + cmdmod_T save_cmdmod = cmdmod; + cmdmod = cmdinfo->cmdmod; + + // Apply command modifiers + apply_cmdmod(&cmdmod); + + if (!MODIFIABLE(curbuf) && (eap->argt & EX_MODIFY) + // allow :put in terminals + && !(curbuf->terminal && eap->cmdidx == CMD_put)) { + ERROR(_(e_modifiable)); + } + if (!IS_USER_CMDIDX(eap->cmdidx)) { + if (cmdwin_type != 0 && !(eap->argt & EX_CMDWIN)) { + // Command not allowed in the command line window + ERROR(_(e_cmdwin)); + } + if (text_locked() && !(eap->argt & EX_LOCK_OK)) { + // Command not allowed when text is locked + ERROR(_(get_text_locked_msg())); + } + } + // Disallow editing another buffer when "curbuf->b_ro_locked" is set. + // Do allow ":checktime" (it is postponed). + // Do allow ":edit" (check for an argument later). + // Do allow ":file" with no arguments + if (!(eap->argt & EX_CMDWIN) + && eap->cmdidx != CMD_checktime + && eap->cmdidx != CMD_edit + && !(eap->cmdidx == CMD_file && *eap->arg == NUL) + && !IS_USER_CMDIDX(eap->cmdidx) + && curbuf_locked()) { + ERROR(_(e_cannot_edit_other_buf)); + } + + if (((eap->argt & EX_WHOLEFOLD) || eap->addr_count >= 2) && !global_busy + && eap->addr_type == ADDR_LINES) { + // Put the first line at the start of a closed fold, put the last line + // at the end of a closed fold. + (void)hasFolding(eap->line1, &eap->line1, NULL); + (void)hasFolding(eap->line2, NULL, &eap->line2); + } + + // Execute the command + execute_cmd0(&retv, eap, &errormsg, preview); + end: if (errormsg != NULL && *errormsg != NUL) { emsg(errormsg); @@ -1704,6 +1722,142 @@ end: #undef ERROR } +static void profile_cmd(const exarg_T *eap, cstack_T *cstack, LineGetter fgetline, void *cookie) +{ + // Count this line for profiling if skip is TRUE. + if (do_profiling == PROF_YES + && (!eap->skip || cstack->cs_idx == 0 + || (cstack->cs_idx > 0 + && (cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE)))) { + int skip = did_emsg || got_int || current_exception; + + if (eap->cmdidx == CMD_catch) { + skip = !skip && !(cstack->cs_idx >= 0 + && (cstack->cs_flags[cstack->cs_idx] & CSF_THROWN) + && !(cstack->cs_flags[cstack->cs_idx] & CSF_CAUGHT)); + } else if (eap->cmdidx == CMD_else || eap->cmdidx == CMD_elseif) { + skip = skip || !(cstack->cs_idx >= 0 + && !(cstack->cs_flags[cstack->cs_idx] + & (CSF_ACTIVE | CSF_TRUE))); + } else if (eap->cmdidx == CMD_finally) { + skip = false; + } else if (eap->cmdidx != CMD_endif + && eap->cmdidx != CMD_endfor + && eap->cmdidx != CMD_endtry + && eap->cmdidx != CMD_endwhile) { + skip = eap->skip; + } + + if (!skip) { + if (getline_equal(fgetline, cookie, get_func_line)) { + func_line_exec(getline_cookie(fgetline, cookie)); + } else if (getline_equal(fgetline, cookie, getsourceline)) { + script_line_exec(); + } + } + } +} + +static bool skip_cmd(const exarg_T *eap) +{ + // Skip the command when it's not going to be executed. + // The commands like :if, :endif, etc. always need to be executed. + // Also make an exception for commands that handle a trailing command + // themselves. + if (eap->skip) { + switch (eap->cmdidx) { + // commands that need evaluation + case CMD_while: + case CMD_endwhile: + case CMD_for: + case CMD_endfor: + case CMD_if: + case CMD_elseif: + case CMD_else: + case CMD_endif: + case CMD_try: + case CMD_catch: + case CMD_finally: + case CMD_endtry: + case CMD_function: + break; + + // Commands that handle '|' themselves. Check: A command should + // either have the EX_TRLBAR flag, appear in this list or appear in + // the list at ":help :bar". + case CMD_aboveleft: + case CMD_and: + case CMD_belowright: + case CMD_botright: + case CMD_browse: + case CMD_call: + case CMD_confirm: + case CMD_const: + case CMD_delfunction: + case CMD_djump: + case CMD_dlist: + case CMD_dsearch: + case CMD_dsplit: + case CMD_echo: + case CMD_echoerr: + case CMD_echomsg: + case CMD_echon: + case CMD_eval: + case CMD_execute: + case CMD_filter: + case CMD_help: + case CMD_hide: + case CMD_ijump: + case CMD_ilist: + case CMD_isearch: + case CMD_isplit: + case CMD_keepalt: + case CMD_keepjumps: + case CMD_keepmarks: + case CMD_keeppatterns: + case CMD_leftabove: + case CMD_let: + case CMD_lockmarks: + case CMD_lockvar: + case CMD_lua: + case CMD_match: + case CMD_mzscheme: + case CMD_noautocmd: + case CMD_noswapfile: + case CMD_perl: + case CMD_psearch: + case CMD_python: + case CMD_py3: + case CMD_python3: + case CMD_pythonx: + case CMD_pyx: + case CMD_return: + case CMD_rightbelow: + case CMD_ruby: + case CMD_silent: + case CMD_smagic: + case CMD_snomagic: + case CMD_substitute: + case CMD_syntax: + case CMD_tab: + case CMD_tcl: + case CMD_throw: + case CMD_tilde: + case CMD_topleft: + case CMD_unlet: + case CMD_unlockvar: + case CMD_verbose: + case CMD_vertical: + case CMD_wincmd: + break; + + default: + return true; + } + } + return false; +} + /// Execute one Ex command. /// /// If 'sourcing' is TRUE, the command will be included in the error message. @@ -1724,16 +1878,11 @@ end: static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter fgetline, void *cookie) { - char *p; - linenr_T lnum; char *errormsg = NULL; // error message - char *after_modifier = NULL; - exarg_T ea; - cmdmod_T save_cmdmod; const int save_reg_executing = reg_executing; const bool save_pending_end_reg_executing = pending_end_reg_executing; - char *cmd; + exarg_T ea; memset(&ea, 0, sizeof(ea)); ea.line1 = 1; ea.line2 = 1; @@ -1749,11 +1898,9 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter --quitmore; } - /* - * Reset browse, confirm, etc.. They are restored when returning, for - * recursive calls. - */ - save_cmdmod = cmdmod; + // Reset browse, confirm, etc.. They are restored when returning, for + // recursive calls. + cmdmod_T save_cmdmod = cmdmod; // "#!anything" is handled like a comment. if ((*cmdlinep)[0] == '#' && (*cmdlinep)[1] == '!') { @@ -1775,7 +1922,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter } apply_cmdmod(&cmdmod); - after_modifier = ea.cmd; + char *after_modifier = ea.cmd; ea.skip = (did_emsg || got_int @@ -1786,45 +1933,14 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter // 3. Skip over the range to find the command. Let "p" point to after it. // // We need the command to know what kind of range it uses. - cmd = ea.cmd; + char *cmd = ea.cmd; ea.cmd = skip_range(ea.cmd, NULL); if (*ea.cmd == '*') { ea.cmd = skipwhite(ea.cmd + 1); } - p = find_ex_command(&ea, NULL); - - // Count this line for profiling if skip is TRUE. - if (do_profiling == PROF_YES - && (!ea.skip || cstack->cs_idx == 0 - || (cstack->cs_idx > 0 - && (cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE)))) { - int skip = did_emsg || got_int || current_exception; + char *p = find_ex_command(&ea, NULL); - if (ea.cmdidx == CMD_catch) { - skip = !skip && !(cstack->cs_idx >= 0 - && (cstack->cs_flags[cstack->cs_idx] & CSF_THROWN) - && !(cstack->cs_flags[cstack->cs_idx] & CSF_CAUGHT)); - } else if (ea.cmdidx == CMD_else || ea.cmdidx == CMD_elseif) { - skip = skip || !(cstack->cs_idx >= 0 - && !(cstack->cs_flags[cstack->cs_idx] - & (CSF_ACTIVE | CSF_TRUE))); - } else if (ea.cmdidx == CMD_finally) { - skip = false; - } else if (ea.cmdidx != CMD_endif - && ea.cmdidx != CMD_endfor - && ea.cmdidx != CMD_endtry - && ea.cmdidx != CMD_endwhile) { - skip = ea.skip; - } - - if (!skip) { - if (getline_equal(fgetline, cookie, get_func_line)) { - func_line_exec(getline_cookie(fgetline, cookie)); - } else if (getline_equal(fgetline, cookie, getsourceline)) { - script_line_exec(); - } - } - } + profile_cmd(&ea, cstack, fgetline, cookie); // May go to debug mode. If this happens and the ">quit" debug command is // used, throw an interrupt exception and skip the next command. @@ -1855,19 +1971,13 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter goto doend; } - /* - * 5. Parse the command. - */ + // 5. Parse the command. - /* - * Skip ':' and any white space - */ + // Skip ':' and any white space ea.cmd = skip_colon_white(ea.cmd, true); - /* - * If we got a line, but no command, then go to the line. - * If we find a '|' or '\n' we set ea.nextcmd. - */ + // If we got a line, but no command, then go to the line. + // If we find a '|' or '\n' we set ea.nextcmd. if (*ea.cmd == NUL || *ea.cmd == '"' || (ea.nextcmd = (char *)check_nextcmd((char_u *)ea.cmd)) != NULL) { // strange vi behaviour: @@ -1947,12 +2057,12 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter const int ni = is_cmd_ni(ea.cmdidx); // Forced commands. - if (*p == '!' && ea.cmdidx != CMD_substitute - && ea.cmdidx != CMD_smagic && ea.cmdidx != CMD_snomagic) { + ea.forceit = *p == '!' + && ea.cmdidx != CMD_substitute + && ea.cmdidx != CMD_smagic + && ea.cmdidx != CMD_snomagic; + if (ea.forceit) { p++; - ea.forceit = true; - } else { - ea.forceit = false; } // 6. Parse arguments. Then check for errors. @@ -2012,10 +2122,8 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter goto doend; } - /* - * Don't complain about the range if it is not used - * (could happen if line_count is accidentally set to 0). - */ + // Don't complain about the range if it is not used + // (could happen if line_count is accidentally set to 0). if (!ea.skip && !ni && (ea.argt & EX_RANGE)) { // If the range is backwards, ask for confirmation and, if given, swap // ea.line1 & ea.line2 so it's forwards again. @@ -2030,7 +2138,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter goto doend; } } - lnum = ea.line1; + linenr_T lnum = ea.line1; ea.line1 = ea.line2; ea.line2 = lnum; } @@ -2054,34 +2162,24 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter (void)hasFolding(ea.line2, NULL, &ea.line2); } - /* - * For the ":make" and ":grep" commands we insert the 'makeprg'/'grepprg' - * option here, so things like % get expanded. - */ + // For the ":make" and ":grep" commands we insert the 'makeprg'/'grepprg' + // option here, so things like % get expanded. p = replace_makeprg(&ea, p, cmdlinep); if (p == NULL) { goto doend; } - /* - * Skip to start of argument. - * Don't do this for the ":!" command, because ":!! -l" needs the space. - */ - if (ea.cmdidx == CMD_bang) { - ea.arg = p; - } else { - ea.arg = skipwhite(p); - } + // Skip to start of argument. + // Don't do this for the ":!" command, because ":!! -l" needs the space. + ea.arg = ea.cmdidx == CMD_bang ? p : skipwhite(p); // ":file" cannot be run with an argument when "curbuf->b_ro_locked" is set if (ea.cmdidx == CMD_file && *ea.arg != NUL && curbuf_locked()) { goto doend; } - /* - * Check for "++opt=val" argument. - * Must be first, allow ":w ++enc=utf8 !cmd" - */ + // Check for "++opt=val" argument. + // Must be first, allow ":w ++enc=utf8 !cmd" if (ea.argt & EX_ARGOPT) { while (ea.arg[0] == '+' && ea.arg[1] == '+') { if (getargopt(&ea) == FAIL && !ni) { @@ -2103,9 +2201,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter ++ea.arg; ea.usefilter = TRUE; } - } - - if (ea.cmdidx == CMD_read) { + } else if (ea.cmdidx == CMD_read) { if (ea.forceit) { ea.usefilter = TRUE; // :r! filter if ea.forceit ea.forceit = FALSE; @@ -2113,9 +2209,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter ++ea.arg; ea.usefilter = TRUE; } - } - - if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift) { + } else if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift) { ea.amount = 1; while (*ea.arg == *ea.cmd) { // count number of '>' or '<' ea.arg++; @@ -2124,18 +2218,14 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter ea.arg = skipwhite(ea.arg); } - /* - * Check for "+command" argument, before checking for next command. - * Don't do this for ":read !cmd" and ":write !cmd". - */ + // Check for "+command" argument, before checking for next command. + // Don't do this for ":read !cmd" and ":write !cmd". if ((ea.argt & EX_CMDARG) && !ea.usefilter) { ea.do_ecmd_cmd = getargcmd(&ea.arg); } - /* - * Check for '|' to separate commands and '"' to start comments. - * Don't do this for ":read !cmd" and ":write !cmd". - */ + // Check for '|' to separate commands and '"' to start comments. + // Don't do this for ":read !cmd" and ":write !cmd". if ((ea.argt & EX_TRLBAR) && !ea.usefilter) { separate_nextcmd(&ea); } else if (ea.cmdidx == CMD_bang @@ -2146,18 +2236,18 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter // Check for <newline> to end a shell command. // Also do this for ":read !cmd", ":write !cmd" and ":global". // Any others? - for (p = ea.arg; *p; p++) { + for (char *s = ea.arg; *s; s++) { // Remove one backslash before a newline, so that it's possible to // pass a newline to the shell and also a newline that is preceded // with a backslash. This makes it impossible to end a shell // command in a backslash, but that doesn't appear useful. // Halving the number of backslashes is incompatible with previous // versions. - if (*p == '\\' && p[1] == '\n') { - STRMOVE(p, p + 1); - } else if (*p == '\n') { - ea.nextcmd = p + 1; - *p = NUL; + if (*s == '\\' && s[1] == '\n') { + STRMOVE(s, s + 1); + } else if (*s == '\n') { + ea.nextcmd = s + 1; + *s = NUL; break; } } @@ -2173,9 +2263,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter goto doend; } - /* - * Check for flags: 'l', 'p' and '#'. - */ + // Check for flags: 'l', 'p' and '#'. if (ea.argt & EX_FLAGS) { get_flags(&ea); } @@ -2191,173 +2279,21 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter goto doend; } - /* - * Skip the command when it's not going to be executed. - * The commands like :if, :endif, etc. always need to be executed. - * Also make an exception for commands that handle a trailing command - * themselves. - */ - if (ea.skip) { - switch (ea.cmdidx) { - // commands that need evaluation - case CMD_while: - case CMD_endwhile: - case CMD_for: - case CMD_endfor: - case CMD_if: - case CMD_elseif: - case CMD_else: - case CMD_endif: - case CMD_try: - case CMD_catch: - case CMD_finally: - case CMD_endtry: - case CMD_function: - break; - - // Commands that handle '|' themselves. Check: A command should - // either have the EX_TRLBAR flag, appear in this list or appear in - // the list at ":help :bar". - case CMD_aboveleft: - case CMD_and: - case CMD_belowright: - case CMD_botright: - case CMD_browse: - case CMD_call: - case CMD_confirm: - case CMD_const: - case CMD_delfunction: - case CMD_djump: - case CMD_dlist: - case CMD_dsearch: - case CMD_dsplit: - case CMD_echo: - case CMD_echoerr: - case CMD_echomsg: - case CMD_echon: - case CMD_eval: - case CMD_execute: - case CMD_filter: - case CMD_help: - case CMD_hide: - case CMD_ijump: - case CMD_ilist: - case CMD_isearch: - case CMD_isplit: - case CMD_keepalt: - case CMD_keepjumps: - case CMD_keepmarks: - case CMD_keeppatterns: - case CMD_leftabove: - case CMD_let: - case CMD_lockmarks: - case CMD_lockvar: - case CMD_lua: - case CMD_match: - case CMD_mzscheme: - case CMD_noautocmd: - case CMD_noswapfile: - case CMD_perl: - case CMD_psearch: - case CMD_python: - case CMD_py3: - case CMD_python3: - case CMD_pythonx: - case CMD_pyx: - case CMD_return: - case CMD_rightbelow: - case CMD_ruby: - case CMD_silent: - case CMD_smagic: - case CMD_snomagic: - case CMD_substitute: - case CMD_syntax: - case CMD_tab: - case CMD_tcl: - case CMD_throw: - case CMD_tilde: - case CMD_topleft: - case CMD_unlet: - case CMD_unlockvar: - case CMD_verbose: - case CMD_vertical: - case CMD_wincmd: - break; - - default: - goto doend; - } - } - - if (ea.argt & EX_XFILE) { - if (expand_filename(&ea, cmdlinep, &errormsg) == FAIL) { - goto doend; - } - } - - /* - * Accept buffer name. Cannot be used at the same time with a buffer - * number. Don't do this for a user command. - */ - if ((ea.argt & EX_BUFNAME) && *ea.arg != NUL && ea.addr_count == 0 - && !IS_USER_CMDIDX(ea.cmdidx)) { - /* - * :bdelete, :bwipeout and :bunload take several arguments, separated - * by spaces: find next space (skipping over escaped characters). - * The others take one argument: ignore trailing spaces. - */ - if (ea.cmdidx == CMD_bdelete || ea.cmdidx == CMD_bwipeout - || ea.cmdidx == CMD_bunload) { - p = skiptowhite_esc(ea.arg); - } else { - p = ea.arg + STRLEN(ea.arg); - while (p > ea.arg && ascii_iswhite(p[-1])) { - p--; - } - } - ea.line2 = buflist_findpat(ea.arg, p, (ea.argt & EX_BUFUNL) != 0, - false, false); - if (ea.line2 < 0) { // failed - goto doend; - } - ea.addr_count = 1; - ea.arg = skipwhite(p); - } - - // 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 && cmdmod.cmod_did_esilent > 0) { - emsg_silent -= cmdmod.cmod_did_esilent; - if (emsg_silent < 0) { - emsg_silent = 0; - } - cmdmod.cmod_did_esilent = 0; + if (skip_cmd(&ea)) { + goto doend; } // 7. Execute the command. - if (IS_USER_CMDIDX(ea.cmdidx)) { - /* - * Execute a user-defined command. - */ - do_ucmd(&ea, false); - } else { - /* - * Call the function to execute the command. - */ - ea.errmsg = NULL; - (cmdnames[ea.cmdidx].cmd_func)(&ea); - if (ea.errmsg != NULL) { - errormsg = _(ea.errmsg); - } + int retv = 0; + if (execute_cmd0(&retv, &ea, &errormsg, false) == FAIL) { + goto doend; } - /* - * If the command just executed called do_cmdline(), any throw or ":return" - * or ":finish" encountered there must also check the cstack of the still - * active do_cmdline() that called this do_one_cmd(). Rethrow an uncaught - * exception, or reanimate a returned function or finished script file and - * return or finish it again. - */ + // If the command just executed called do_cmdline(), any throw or ":return" + // or ":finish" encountered there must also check the cstack of the still + // active do_cmdline() that called this do_one_cmd(). Rethrow an uncaught + // exception, or reanimate a returned function or finished script file and + // return or finish it again. if (need_rethrow) { do_throw(cstack); } else if (check_cstack) { @@ -2383,7 +2319,7 @@ doend: STRCPY(IObuff, errormsg); errormsg = (char *)IObuff; } - append_command(*cmdlinep); + append_command(*ea.cmdlinep); } emsg(errormsg); } |