aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ex_docmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/ex_docmd.c')
-rw-r--r--src/nvim/ex_docmd.c113
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: