summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
authorOlivia Kinnear <git@superatomic.dev>2026-03-28 22:07:04 -0500
committerOlivia Kinnear <git@superatomic.dev>2026-04-10 11:08:26 -0500
commit8715877417b5c5fee98e6cac9e4e60ca08050048 (patch)
treec0283a005101a7507e9f78b28fd6eede384cf073 /src
parent6bea0cdbdcb576fa9633521dbb560985e8f0076b (diff)
feat(ex): add `:log` command
Diffstat (limited to 'src')
-rw-r--r--src/nvim/cmdexpand.c43
-rw-r--r--src/nvim/cmdexpand_defs.h1
-rw-r--r--src/nvim/ex_cmds.lua6
-rw-r--r--src/nvim/ex_docmd.c25
4 files changed, 75 insertions, 0 deletions
diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c
index 04fcde7ee6..6030197357 100644
--- a/src/nvim/cmdexpand.c
+++ b/src/nvim/cmdexpand.c
@@ -1304,6 +1304,7 @@ char *addstar(char *fname, size_t len, int context)
&& fname[0] == '/')
|| context == EXPAND_CHECKHEALTH
|| context == EXPAND_LSP
+ || context == EXPAND_LOG
|| context == EXPAND_LUA) {
retval = xstrnsave(fname, len);
} else {
@@ -2316,6 +2317,10 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, expa
xp->xp_context = EXPAND_CHECKHEALTH;
break;
+ case CMD_log:
+ xp->xp_context = EXPAND_LOG;
+ break;
+
case CMD_lsp:
xp->xp_context = EXPAND_LSP;
break;
@@ -2858,6 +2863,43 @@ static char *get_healthcheck_names(expand_T *xp FUNC_ATTR_UNUSED, int idx)
return NULL;
}
+/// Completion for |:log| command.
+///
+/// Given to ExpandGeneric() to obtain `:log` completion.
+/// @param[in] idx Index of the item.
+/// @param[in] xp Not used.
+static char *get_log_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
+{
+ static Object names = OBJECT_INIT;
+ static char *last_xp_line = NULL;
+ static unsigned last_gen = 0;
+
+ if (last_xp_line == NULL || strcmp(last_xp_line,
+ xp->xp_line) != 0
+ || last_gen != get_cmdline_last_prompt_id()) {
+ xfree(last_xp_line);
+ last_xp_line = xstrdup(xp->xp_line);
+ MAXSIZE_TEMP_ARRAY(args, 1);
+ Error err = ERROR_INIT;
+
+ ADD_C(args, CSTR_AS_OBJ(xp->xp_line));
+ // Build the current command line as a Lua string argument
+ Object res = NLUA_EXEC_STATIC("return require'vim._core.ex_cmd'.log_complete(...)", args,
+ kRetObject, NULL,
+ &err);
+ api_clear_error(&err);
+ api_free_object(names);
+ names = res;
+ last_gen = get_cmdline_last_prompt_id();
+ }
+
+ if (names.type == kObjectTypeArray && idx < (int)names.data.array.size
+ && names.data.array.items[idx].type == kObjectTypeString) {
+ return names.data.array.items[idx].data.string.data;
+ }
+ return NULL;
+}
+
/// Completion for |:lsp| command.
///
/// Given to ExpandGeneric() to obtain `:lsp` completion.
@@ -2937,6 +2979,7 @@ static int ExpandOther(char *pat, expand_T *xp, regmatch_T *rmp, char ***matches
{ EXPAND_SCRIPTNAMES, get_scriptnames_arg, true, false },
{ EXPAND_RETAB, get_retab_arg, true, true },
{ EXPAND_CHECKHEALTH, get_healthcheck_names, true, false },
+ { EXPAND_LOG, get_log_arg, true, false },
{ EXPAND_LSP, get_lsp_arg, true, false },
};
int ret = FAIL;
diff --git a/src/nvim/cmdexpand_defs.h b/src/nvim/cmdexpand_defs.h
index 3535e216d6..532ea7fd11 100644
--- a/src/nvim/cmdexpand_defs.h
+++ b/src/nvim/cmdexpand_defs.h
@@ -119,6 +119,7 @@ enum {
EXPAND_CHECKHEALTH,
EXPAND_LUA,
EXPAND_LSP,
+ EXPAND_LOG,
};
/// Type used by ExpandGeneric()
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index 93cc0f3bfe..679b2d25ae 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -1587,6 +1587,12 @@ M.cmds = {
func = 'ex_lockvar',
},
{
+ command = 'log',
+ flags = bit.bor(EXTRA, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_log',
+ },
+ {
command = 'lolder',
flags = bit.bor(RANGE, COUNT, TRLBAR),
addr_type = 'ADDR_UNSIGNED',
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 2f332a6e33..3971bf998b 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -8291,6 +8291,31 @@ static void ex_terminal(exarg_T *eap)
do_cmdline_cmd(ex_cmd);
}
+/// ":log {name}"
+static void ex_log(exarg_T *eap)
+{
+ Error err = ERROR_INIT;
+ MAXSIZE_TEMP_ARRAY(args, 2);
+
+ char mods[1024];
+ size_t mods_len = 0;
+ mods[0] = NUL;
+
+ if (cmdmod.cmod_tab > 0 || cmdmod.cmod_split != 0) {
+ bool multi_mods = false;
+ mods_len = add_win_cmd_modifiers(mods, &cmdmod, &multi_mods);
+ assert(mods_len < sizeof(mods));
+ }
+ ADD_C(args, CSTR_AS_OBJ(eap->arg));
+ ADD_C(args, STRING_OBJ(((String){ .data = mods, .size = mods_len })));
+
+ NLUA_EXEC_STATIC("require'vim._core.ex_cmd'.ex_log(...)", args, kRetNilBool, NULL, &err);
+ if (ERROR_SET(&err)) {
+ emsg_multiline(err.msg, "lua_error", HLF_E, true);
+ }
+ api_clear_error(&err);
+}
+
/// ":lsp {subcmd} {clients}"
static void ex_lsp(exarg_T *eap)
{