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.c193
1 files changed, 101 insertions, 92 deletions
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 25eaacd687..71c34f98ff 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -81,23 +81,7 @@
static int quitmore = 0;
static bool ex_pressedreturn = false;
-typedef struct ucmd {
- char_u *uc_name; // The command name
- uint32_t uc_argt; // The argument type
- char_u *uc_rep; // The command's replacement string
- long uc_def; // The default value for a range/count
- int uc_compl; // completion type
- cmd_addr_T uc_addr_type; // The command's address type
- sctx_T uc_script_ctx; // SCTX where the command was defined
- char_u *uc_compl_arg; // completion argument if any
-} ucmd_T;
-
-#define UC_BUFFER 1 // -buffer: local to current buffer
-
-static garray_T ucmds = { 0, 0, sizeof(ucmd_T), 4, NULL };
-
-#define USER_CMD(i) (&((ucmd_T *)(ucmds.ga_data))[i])
-#define USER_CMD_GA(gap, i) (&((ucmd_T *)((gap)->ga_data))[i])
+garray_T ucmds = { 0, 0, sizeof(ucmd_T), 4, NULL };
// Whether a command index indicates a user command.
#define IS_USER_CMDIDX(idx) ((int)(idx) < 0)
@@ -2761,6 +2745,7 @@ static char_u *find_ucmd(exarg_T *eap, char_u *p, int *full, expand_T *xp, int *
*complp = uc->uc_compl;
}
if (xp != NULL) {
+ xp->xp_luaref = uc->uc_compl_luaref;
xp->xp_arg = uc->uc_compl_arg;
xp->xp_script_ctx = uc->uc_script_ctx;
xp->xp_script_ctx.sc_lnum += sourcing_lnum;
@@ -5171,8 +5156,9 @@ char_u *get_command_name(expand_T *xp, int idx)
return cmdnames[idx].cmd_name;
}
-static int uc_add_command(char_u *name, size_t name_len, char_u *rep, uint32_t argt, long def,
- int flags, int compl, char_u *compl_arg, cmd_addr_T addr_type, bool force)
+int uc_add_command(char_u *name, size_t name_len, char_u *rep, uint32_t argt, long def, int flags,
+ int compl, char_u *compl_arg, LuaRef compl_luaref, cmd_addr_T addr_type,
+ LuaRef luaref, bool force)
FUNC_ATTR_NONNULL_ARG(1, 3)
{
ucmd_T *cmd = NULL;
@@ -5226,6 +5212,8 @@ static int uc_add_command(char_u *name, size_t name_len, char_u *rep, uint32_t a
XFREE_CLEAR(cmd->uc_rep);
XFREE_CLEAR(cmd->uc_compl_arg);
+ NLUA_CLEAR_REF(cmd->uc_luaref);
+ NLUA_CLEAR_REF(cmd->uc_compl_luaref);
break;
}
@@ -5256,13 +5244,17 @@ static int uc_add_command(char_u *name, size_t name_len, char_u *rep, uint32_t a
cmd->uc_script_ctx = current_sctx;
cmd->uc_script_ctx.sc_lnum += sourcing_lnum;
cmd->uc_compl_arg = compl_arg;
+ cmd->uc_compl_luaref = compl_luaref;
cmd->uc_addr_type = addr_type;
+ cmd->uc_luaref = luaref;
return OK;
fail:
xfree(rep_buf);
xfree(compl_arg);
+ NLUA_CLEAR_REF(luaref);
+ NLUA_CLEAR_REF(compl_luaref);
return FAIL;
}
@@ -5301,6 +5293,7 @@ static const char *command_complete[] =
[EXPAND_CSCOPE] = "cscope",
[EXPAND_USER_DEFINED] = "custom",
[EXPAND_USER_LIST] = "customlist",
+ [EXPAND_USER_LUA] = "<Lua function>",
[EXPAND_DIFF_BUFFERS] = "diff_buffer",
[EXPAND_DIRECTORIES] = "dir",
[EXPAND_ENV_VARS] = "environment",
@@ -5702,8 +5695,8 @@ 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, end - name, p, argt, def, flags, compl, compl_arg,
- addr_type_arg, eap->forceit);
+ uc_add_command(name, end - name, p, argt, def, flags, compl, compl_arg, LUA_NOREF,
+ addr_type_arg, LUA_NOREF, eap->forceit);
}
}
@@ -5717,11 +5710,13 @@ void ex_comclear(exarg_T *eap)
uc_clear(&curbuf->b_ucmds);
}
-static void free_ucmd(ucmd_T *cmd)
+void free_ucmd(ucmd_T *cmd)
{
xfree(cmd->uc_name);
xfree(cmd->uc_rep);
xfree(cmd->uc_compl_arg);
+ NLUA_CLEAR_REF(cmd->uc_compl_luaref);
+ NLUA_CLEAR_REF(cmd->uc_luaref);
}
/*
@@ -5759,9 +5754,7 @@ static void ex_delcommand(exarg_T *eap)
return;
}
- xfree(cmd->uc_name);
- xfree(cmd->uc_rep);
- xfree(cmd->uc_compl_arg);
+ free_ucmd(cmd);
--gap->ga_len;
@@ -5843,7 +5836,7 @@ static char_u *uc_split_args(char_u *arg, size_t *lenp)
return buf;
}
-static size_t add_cmd_modifier(char_u *buf, char *mod_str, bool *multi_mods)
+static size_t add_cmd_modifier(char *buf, char *mod_str, bool *multi_mods)
{
size_t result = STRLEN(mod_str);
if (*multi_mods) {
@@ -6044,70 +6037,8 @@ static size_t uc_check_code(char_u *code, size_t len, char_u *buf, ucmd_T *cmd,
*buf = '\0';
}
- bool multi_mods = false;
-
- // :aboveleft and :leftabove
- if (cmdmod.split & WSP_ABOVE) {
- result += add_cmd_modifier(buf, "aboveleft", &multi_mods);
- }
- // :belowright and :rightbelow
- if (cmdmod.split & WSP_BELOW) {
- result += add_cmd_modifier(buf, "belowright", &multi_mods);
- }
- // :botright
- if (cmdmod.split & WSP_BOT) {
- result += add_cmd_modifier(buf, "botright", &multi_mods);
- }
-
- typedef struct {
- bool *set;
- char *name;
- } mod_entry_T;
- static mod_entry_T mod_entries[] = {
- { &cmdmod.browse, "browse" },
- { &cmdmod.confirm, "confirm" },
- { &cmdmod.hide, "hide" },
- { &cmdmod.keepalt, "keepalt" },
- { &cmdmod.keepjumps, "keepjumps" },
- { &cmdmod.keepmarks, "keepmarks" },
- { &cmdmod.keeppatterns, "keeppatterns" },
- { &cmdmod.lockmarks, "lockmarks" },
- { &cmdmod.noswapfile, "noswapfile" }
- };
- // the modifiers that are simple flags
- for (size_t i = 0; i < ARRAY_SIZE(mod_entries); i++) {
- if (*mod_entries[i].set) {
- result += add_cmd_modifier(buf, mod_entries[i].name, &multi_mods);
- }
- }
-
- // TODO(vim): How to support :noautocmd?
- // TODO(vim): How to support :sandbox?
+ result += uc_mods((char *)buf);
- // :silent
- if (msg_silent > 0) {
- result += add_cmd_modifier(buf, emsg_silent > 0 ? "silent!" : "silent",
- &multi_mods);
- }
- // :tab
- if (cmdmod.tab > 0) {
- result += add_cmd_modifier(buf, "tab", &multi_mods);
- }
- // :topleft
- if (cmdmod.split & WSP_TOP) {
- result += add_cmd_modifier(buf, "topleft", &multi_mods);
- }
-
- // TODO(vim): How to support :unsilent?
-
- // :verbose
- if (p_verbose > 0) {
- result += add_cmd_modifier(buf, "verbose", &multi_mods);
- }
- // :vertical
- if (cmdmod.split & WSP_VERT) {
- result += add_cmd_modifier(buf, "vertical", &multi_mods);
- }
if (quote && buf != NULL) {
buf += result - 2;
*buf = '"';
@@ -6152,6 +6083,76 @@ static size_t uc_check_code(char_u *code, size_t len, char_u *buf, ucmd_T *cmd,
return result;
}
+size_t uc_mods(char *buf)
+{
+ size_t result = 0;
+ bool multi_mods = false;
+
+ // :aboveleft and :leftabove
+ if (cmdmod.split & WSP_ABOVE) {
+ result += add_cmd_modifier(buf, "aboveleft", &multi_mods);
+ }
+ // :belowright and :rightbelow
+ if (cmdmod.split & WSP_BELOW) {
+ result += add_cmd_modifier(buf, "belowright", &multi_mods);
+ }
+ // :botright
+ if (cmdmod.split & WSP_BOT) {
+ result += add_cmd_modifier(buf, "botright", &multi_mods);
+ }
+
+ typedef struct {
+ bool *set;
+ char *name;
+ } mod_entry_T;
+ static mod_entry_T mod_entries[] = {
+ { &cmdmod.browse, "browse" },
+ { &cmdmod.confirm, "confirm" },
+ { &cmdmod.hide, "hide" },
+ { &cmdmod.keepalt, "keepalt" },
+ { &cmdmod.keepjumps, "keepjumps" },
+ { &cmdmod.keepmarks, "keepmarks" },
+ { &cmdmod.keeppatterns, "keeppatterns" },
+ { &cmdmod.lockmarks, "lockmarks" },
+ { &cmdmod.noswapfile, "noswapfile" }
+ };
+ // the modifiers that are simple flags
+ for (size_t i = 0; i < ARRAY_SIZE(mod_entries); i++) {
+ if (*mod_entries[i].set) {
+ result += add_cmd_modifier(buf, mod_entries[i].name, &multi_mods);
+ }
+ }
+
+ // TODO(vim): How to support :noautocmd?
+ // TODO(vim): How to support :sandbox?
+
+ // :silent
+ if (msg_silent > 0) {
+ result += add_cmd_modifier(buf, emsg_silent > 0 ? "silent!" : "silent", &multi_mods);
+ }
+ // :tab
+ if (cmdmod.tab > 0) {
+ result += add_cmd_modifier(buf, "tab", &multi_mods);
+ }
+ // :topleft
+ if (cmdmod.split & WSP_TOP) {
+ result += add_cmd_modifier(buf, "topleft", &multi_mods);
+ }
+
+ // TODO(vim): How to support :unsilent?
+
+ // :verbose
+ if (p_verbose > 0) {
+ result += add_cmd_modifier(buf, "verbose", &multi_mods);
+ }
+ // :vertical
+ if (cmdmod.split & WSP_VERT) {
+ result += add_cmd_modifier(buf, "vertical", &multi_mods);
+ }
+
+ return result;
+}
+
static void do_ucmd(exarg_T *eap)
{
char_u *buf;
@@ -6174,6 +6175,11 @@ static void do_ucmd(exarg_T *eap)
cmd = USER_CMD_GA(&curbuf->b_ucmds, eap->useridx);
}
+ if (cmd->uc_luaref > 0) {
+ nlua_do_ucmd(cmd, eap);
+ return;
+ }
+
/*
* Replace <> in the command by the arguments.
* First round: "buf" is NULL, compute length, allocate "buf".
@@ -9545,15 +9551,18 @@ static void ex_filetype(exarg_T *eap)
void filetype_maybe_enable(void)
{
if (filetype_detect == kNone) {
- source_runtime(FILETYPE_FILE, true);
+ // Normally .vim files are sourced before .lua files when both are
+ // supported, but we reverse the order here because we want the Lua
+ // autocommand to be defined first so that it runs first
+ source_runtime(FILETYPE_FILE, DIP_ALL);
filetype_detect = kTrue;
}
if (filetype_plugin == kNone) {
- source_runtime(FTPLUGIN_FILE, true);
+ source_runtime(FTPLUGIN_FILE, DIP_ALL);
filetype_plugin = kTrue;
}
if (filetype_indent == kNone) {
- source_runtime(INDENT_FILE, true);
+ source_runtime(INDENT_FILE, DIP_ALL);
filetype_indent = kTrue;
}
}