feat(api): nvim_get_commands returns desc #39623

Problem:
Can't get a command's description from nvim_get_commands when
cmd is string.

Solution:
Returns "desc" field in nvim_get_commands.
`definition` is now empty when cmd is function type.
This commit is contained in:
glepnir
2026-05-06 18:36:39 +08:00
committed by GitHub
parent c286c9d686
commit 1787965d77
6 changed files with 61 additions and 8 deletions
+1
View File
@@ -118,6 +118,7 @@ API
shape when an unfocused float is on top of the cursor.
• |nvim_echo()| distinguishes zero percent from omitted percent for Progress
events.
• |nvim_create_user_command()| accepts `desc` for Vimscript commands.
BUILD
@@ -130,6 +130,7 @@ error('Cannot require a meta file')
--- @field range? string
--- @field addr? string
--- @field callback? function
--- @field desc? string
--- @class vim.api.keyset.hl_info.base
--- @field reverse? true
+10 -6
View File
@@ -1257,14 +1257,18 @@ void create_user_command(uint64_t channel_id, String name, Union(String, LuaRef)
opts->preview.data.luaref = LUA_NOREF;
}
const char *desc = NULL;
if (HAS_KEY(opts, user_command, desc)) {
VALIDATE_T("desc", kObjectTypeString, opts->desc.type, {
goto err;
});
desc = opts->desc.data.string.data;
}
switch (cmd.type) {
case kObjectTypeLuaRef:
luaref = api_new_luaref(cmd.data.luaref);
if (opts->desc.type == kObjectTypeString) {
rep = opts->desc.data.string.data;
} else {
rep = "";
}
rep = "";
break;
case kObjectTypeString:
rep = cmd.data.string.data;
@@ -1277,7 +1281,7 @@ void create_user_command(uint64_t channel_id, String name, Union(String, LuaRef)
WITH_SCRIPT_CONTEXT(channel_id, {
if (uc_add_command(name.data, name.size, rep, argt, def, flags, context, compl_arg,
compl_luaref, preview_luaref, addr_type_arg, luaref, force) != OK) {
compl_luaref, preview_luaref, addr_type_arg, luaref, desc, force) != OK) {
api_set_error(err, kErrorTypeException, "Failed to create user command");
// Do not goto err, since uc_add_command now owns luaref, compl_luaref, preview_luaref,
// and compl_arg
+7 -2
View File
@@ -890,7 +890,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, const char *rep, uint32_t argt, int64_t def,
int flags, int context, char *compl_arg, LuaRef compl_luaref,
LuaRef preview_luaref, cmd_addr_T addr_type, LuaRef luaref, bool force)
LuaRef preview_luaref, cmd_addr_T addr_type, LuaRef luaref, const char *desc,
bool force)
FUNC_ATTR_NONNULL_ARG(1, 3)
{
ucmd_T *cmd = NULL;
@@ -942,6 +943,7 @@ int uc_add_command(char *name, size_t name_len, const char *rep, uint32_t argt,
XFREE_CLEAR(cmd->uc_rep);
XFREE_CLEAR(cmd->uc_compl_arg);
XFREE_CLEAR(cmd->uc_desc);
NLUA_CLEAR_REF(cmd->uc_luaref);
NLUA_CLEAR_REF(cmd->uc_compl_luaref);
NLUA_CLEAR_REF(cmd->uc_preview_luaref);
@@ -969,6 +971,7 @@ int uc_add_command(char *name, size_t name_len, const char *rep, uint32_t argt,
}
cmd->uc_rep = rep_buf;
cmd->uc_desc = (desc != NULL && *desc != NUL) ? xstrdup(desc) : NULL;
cmd->uc_argt = argt;
cmd->uc_def = def;
cmd->uc_compl = context;
@@ -1039,7 +1042,7 @@ void ex_command(exarg_T *eap)
emsg(_(e_complete_used_without_allowing_arguments));
} else {
uc_add_command(name, name_len, p, argt, def, flags, context, compl_arg, LUA_NOREF, LUA_NOREF,
addr_type_arg, LUA_NOREF, eap->forceit);
addr_type_arg, LUA_NOREF, NULL, eap->forceit);
return; // success
}
@@ -1063,6 +1066,7 @@ void free_ucmd(ucmd_T *cmd)
xfree(cmd->uc_name);
xfree(cmd->uc_rep);
xfree(cmd->uc_compl_arg);
xfree(cmd->uc_desc);
NLUA_CLEAR_REF(cmd->uc_compl_luaref);
NLUA_CLEAR_REF(cmd->uc_luaref);
NLUA_CLEAR_REF(cmd->uc_preview_luaref);
@@ -1782,6 +1786,7 @@ Dict commands_array(buf_T *buf, Arena *arena)
PUT_C(d, "name", CSTR_AS_OBJ(cmd->uc_name));
PUT_C(d, "definition", CSTR_AS_OBJ(cmd->uc_rep));
PUT_C(d, "desc", CSTR_AS_OBJ(cmd->uc_desc));
PUT_C(d, "script_id", INTEGER_OBJ(cmd->uc_script_ctx.sc_sid));
PUT_C(d, "bang", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_BANG)));
PUT_C(d, "bar", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_TRLBAR)));
+1
View File
@@ -22,6 +22,7 @@ typedef struct {
LuaRef uc_compl_luaref; ///< Reference to Lua completion function
LuaRef uc_preview_luaref; ///< Reference to Lua preview function
LuaRef uc_luaref; ///< Reference to Lua function
char *uc_desc; ///< Command description
} ucmd_T;
enum { UC_BUFFER = 1, }; ///< -buffer: local to current buffer
+41
View File
@@ -23,6 +23,7 @@ describe('nvim_get_commands', function()
complete_arg = NIL,
count = NIL,
definition = 'echo "Hello World"',
desc = '',
name = 'Hello',
nargs = '1',
range = NIL,
@@ -38,6 +39,7 @@ describe('nvim_get_commands', function()
complete_arg = NIL,
count = NIL,
definition = 'pwd',
desc = '',
name = 'Pwd',
nargs = '?',
range = NIL,
@@ -54,6 +56,15 @@ describe('nvim_get_commands', function()
it('validation', function()
eq('builtin=true not implemented', pcall_err(api.nvim_get_commands, { builtin = true }))
eq("Invalid key: 'foo'", pcall_err(api.nvim_get_commands, { foo = 'blah' }))
matches(
"Invalid 'desc'",
pcall_err(
exec_lua,
[[
vim.api.nvim_create_user_command('Bad', 'echo "hi"', { desc = 123 })
]]
)
)
end)
it('gets global user-defined commands', function()
@@ -92,6 +103,7 @@ describe('nvim_get_commands', function()
complete_arg = NIL,
count = '10',
definition = 'pwd <args>',
desc = '',
name = 'TestCmd',
nargs = '1',
range = '10',
@@ -107,6 +119,7 @@ describe('nvim_get_commands', function()
complete_arg = 'ListUsers',
count = NIL,
definition = '!finger <args>',
desc = '',
name = 'Finger',
nargs = '+',
range = NIL,
@@ -122,6 +135,7 @@ describe('nvim_get_commands', function()
complete_arg = NIL,
count = NIL,
definition = 'call \128\253R2_foo(<q-args>)',
desc = '',
name = 'Cmd2',
nargs = '*',
range = NIL,
@@ -137,6 +151,7 @@ describe('nvim_get_commands', function()
complete_arg = NIL,
count = NIL,
definition = 'call \128\253R3_ohyeah()',
desc = '',
name = 'Cmd3',
nargs = '0',
range = NIL,
@@ -152,6 +167,7 @@ describe('nvim_get_commands', function()
complete_arg = NIL,
count = NIL,
definition = 'call \128\253R4_just_great()',
desc = '',
name = 'Cmd4',
nargs = '0',
range = NIL,
@@ -167,6 +183,7 @@ describe('nvim_get_commands', function()
complete_arg = 's:cpt',
count = NIL,
definition = '',
desc = '',
name = 'PreviewCmd',
nargs = '1',
range = NIL,
@@ -184,6 +201,7 @@ describe('nvim_get_commands', function()
complete_arg = NIL,
count = NIL,
definition = '',
desc = 'Preview Lua Cmd',
name = 'PreviewLuaCmd',
nargs = '1',
range = NIL,
@@ -191,6 +209,22 @@ describe('nvim_get_commands', function()
keepscript = false,
script_id = -8, -- Lua
}
local withDesc = {
addr = vim.NIL,
bang = false,
bar = false,
complete = vim.NIL,
complete_arg = vim.NIL,
count = vim.NIL,
definition = 'echo "hi"',
desc = 'Says hi',
keepscript = false,
name = 'WithDesc',
nargs = '0',
range = vim.NIL,
register = false,
script_id = -8,
}
source([[
let s:foo = 1
@@ -230,8 +264,14 @@ describe('nvim_get_commands', function()
nargs = 1,
complete = function() return 3 end,
preview = function() return 4 end,
desc = 'Preview Lua Cmd'
}
)
vim.api.nvim_create_user_command(
'WithDesc',
'echo "hi"',
{ desc = 'Says hi' }
)
EOF
]])
-- TODO(justinmk): Order is stable but undefined. Sort before return?
@@ -244,6 +284,7 @@ describe('nvim_get_commands', function()
TestCmd = cmd0,
PreviewCmd = previewCmd,
PreviewLuaCmd = previewLuaCmd,
WithDesc = withDesc,
}, commands)
end)