diff options
Diffstat (limited to 'src/nvim/ex_docmd.c')
-rw-r--r-- | src/nvim/ex_docmd.c | 193 |
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; } } |