aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLewis Russell <lewis6991@gmail.com>2022-08-03 11:44:17 +0100
committerGitHub <noreply@github.com>2022-08-03 11:44:17 +0100
commit5ee56f95c7c4aa588b37fec297e21a040a8d2367 (patch)
tree571172d70e8ca74f26ca85b9ff01dc8140daa039
parentb8dcbcc732baf84fc48d6b272c3ade0bcb129b3b (diff)
parentdc2745e9eac08d4537c409a8700c37bc9d42d6de (diff)
downloadrneovim-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.c5
-rw-r--r--src/nvim/ex_cmds_defs.h56
-rw-r--r--src/nvim/ex_docmd.c606
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);
}