mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
feat(autocmds): retrieve lua callback (#18642)
add a new `callback` field to `nvim_get_autocmds`
This commit is contained in:
parent
c5720c7221
commit
3da3cfc864
@ -3610,7 +3610,11 @@ nvim_get_autocmds({*opts}) *nvim_get_autocmds()*
|
|||||||
• group_name (string): the autocommand group name.
|
• group_name (string): the autocommand group name.
|
||||||
• desc (string): the autocommand description.
|
• desc (string): the autocommand description.
|
||||||
• event (string): the autocommand event.
|
• event (string): the autocommand event.
|
||||||
• command (string): the autocommand command.
|
• command (string): the autocommand command. Note: this
|
||||||
|
will be empty if a callback is set.
|
||||||
|
• callback (function|string|nil): Lua function or name of
|
||||||
|
a Vim script function which is executed when this
|
||||||
|
autocommand is triggered.
|
||||||
• once (boolean): whether the autocommand is only run
|
• once (boolean): whether the autocommand is only run
|
||||||
once.
|
once.
|
||||||
• pattern (string): the autocommand pattern. If the
|
• pattern (string): the autocommand pattern. If the
|
||||||
|
@ -66,7 +66,9 @@ static int64_t next_autocmd_id = 1;
|
|||||||
/// - group_name (string): the autocommand group name.
|
/// - group_name (string): the autocommand group name.
|
||||||
/// - desc (string): the autocommand description.
|
/// - desc (string): the autocommand description.
|
||||||
/// - event (string): the autocommand event.
|
/// - event (string): the autocommand event.
|
||||||
/// - command (string): the autocommand command.
|
/// - command (string): the autocommand command. Note: this will be empty if a callback is set.
|
||||||
|
/// - callback (function|string|nil): Lua function or name of a Vim script function
|
||||||
|
/// which is executed when this autocommand is triggered.
|
||||||
/// - once (boolean): whether the autocommand is only run once.
|
/// - once (boolean): whether the autocommand is only run once.
|
||||||
/// - pattern (string): the autocommand pattern.
|
/// - pattern (string): the autocommand pattern.
|
||||||
/// If the autocommand is buffer local |autocmd-buffer-local|:
|
/// If the autocommand is buffer local |autocmd-buffer-local|:
|
||||||
@ -280,9 +282,28 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
|
|||||||
PUT(autocmd_info, "desc", CSTR_TO_OBJ(ac->desc));
|
PUT(autocmd_info, "desc", CSTR_TO_OBJ(ac->desc));
|
||||||
}
|
}
|
||||||
|
|
||||||
PUT(autocmd_info,
|
if (ac->exec.type == CALLABLE_CB) {
|
||||||
"command",
|
PUT(autocmd_info, "command", STRING_OBJ(STRING_INIT));
|
||||||
STRING_OBJ(cstr_as_string(aucmd_exec_to_string(ac, ac->exec))));
|
|
||||||
|
Callback *cb = &ac->exec.callable.cb;
|
||||||
|
switch (cb->type) {
|
||||||
|
case kCallbackLua:
|
||||||
|
if (nlua_ref_is_function(cb->data.luaref)) {
|
||||||
|
PUT(autocmd_info, "callback", LUAREF_OBJ(api_new_luaref(cb->data.luaref)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case kCallbackFuncref:
|
||||||
|
case kCallbackPartial:
|
||||||
|
PUT(autocmd_info, "callback", STRING_OBJ(cstr_as_string(callback_to_string(cb))));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PUT(autocmd_info,
|
||||||
|
"command",
|
||||||
|
STRING_OBJ(cstr_as_string(xstrdup(ac->exec.callable.cmd))));
|
||||||
|
}
|
||||||
|
|
||||||
PUT(autocmd_info,
|
PUT(autocmd_info,
|
||||||
"pattern",
|
"pattern",
|
||||||
@ -442,7 +463,8 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
|
|||||||
// not do that.
|
// not do that.
|
||||||
|
|
||||||
Object *callback = &opts->callback;
|
Object *callback = &opts->callback;
|
||||||
if (callback->type == kObjectTypeLuaRef) {
|
switch (callback->type) {
|
||||||
|
case kObjectTypeLuaRef:
|
||||||
if (callback->data.luaref == LUA_NOREF) {
|
if (callback->data.luaref == LUA_NOREF) {
|
||||||
api_set_error(err,
|
api_set_error(err,
|
||||||
kErrorTypeValidation,
|
kErrorTypeValidation,
|
||||||
@ -459,10 +481,12 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
|
|||||||
|
|
||||||
cb.type = kCallbackLua;
|
cb.type = kCallbackLua;
|
||||||
cb.data.luaref = api_new_luaref(callback->data.luaref);
|
cb.data.luaref = api_new_luaref(callback->data.luaref);
|
||||||
} else if (callback->type == kObjectTypeString) {
|
break;
|
||||||
|
case kObjectTypeString:
|
||||||
cb.type = kCallbackFuncref;
|
cb.type = kCallbackFuncref;
|
||||||
cb.data.funcref = string_to_cstr(callback->data.string);
|
cb.data.funcref = string_to_cstr(callback->data.string);
|
||||||
} else {
|
break;
|
||||||
|
default:
|
||||||
api_set_error(err,
|
api_set_error(err,
|
||||||
kErrorTypeException,
|
kErrorTypeException,
|
||||||
"'callback' must be a lua function or name of vim function");
|
"'callback' must be a lua function or name of vim function");
|
||||||
|
@ -2477,32 +2477,6 @@ bool autocmd_delete_id(int64_t id)
|
|||||||
// AucmdExecutable Functions
|
// AucmdExecutable Functions
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
|
|
||||||
/// Generate a string description of a callback
|
|
||||||
static char *aucmd_callback_to_string(Callback cb)
|
|
||||||
{
|
|
||||||
// NOTE: this function probably belongs in a helper
|
|
||||||
|
|
||||||
size_t msglen = 100;
|
|
||||||
char *msg = (char *)xmallocz(msglen);
|
|
||||||
|
|
||||||
switch (cb.type) {
|
|
||||||
case kCallbackLua:
|
|
||||||
snprintf(msg, msglen, "<lua: %d>", cb.data.luaref);
|
|
||||||
break;
|
|
||||||
case kCallbackFuncref:
|
|
||||||
// TODO(tjdevries): Is this enough space for this?
|
|
||||||
snprintf(msg, msglen, "<vim function: %s>", cb.data.funcref);
|
|
||||||
break;
|
|
||||||
case kCallbackPartial:
|
|
||||||
snprintf(msg, msglen, "<vim partial: %s>", cb.data.partial->pt_name);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
snprintf(msg, msglen, "%s", "");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generate a string description for the command/callback of an autocmd
|
/// Generate a string description for the command/callback of an autocmd
|
||||||
char *aucmd_exec_to_string(AutoCmd *ac, AucmdExecutable acc)
|
char *aucmd_exec_to_string(AutoCmd *ac, AucmdExecutable acc)
|
||||||
FUNC_ATTR_PURE
|
FUNC_ATTR_PURE
|
||||||
@ -2511,7 +2485,7 @@ char *aucmd_exec_to_string(AutoCmd *ac, AucmdExecutable acc)
|
|||||||
case CALLABLE_EX:
|
case CALLABLE_EX:
|
||||||
return xstrdup(acc.callable.cmd);
|
return xstrdup(acc.callable.cmd);
|
||||||
case CALLABLE_CB:
|
case CALLABLE_CB:
|
||||||
return aucmd_callback_to_string(acc.callable.cb);
|
return callback_to_string(&acc.callable.cb);
|
||||||
case CALLABLE_NONE:
|
case CALLABLE_NONE:
|
||||||
return "This is not possible";
|
return "This is not possible";
|
||||||
}
|
}
|
||||||
|
@ -1205,6 +1205,30 @@ void callback_copy(Callback *dest, Callback *src)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generate a string description of a callback
|
||||||
|
char *callback_to_string(Callback *cb)
|
||||||
|
{
|
||||||
|
size_t msglen = 100;
|
||||||
|
char *msg = (char *)xmallocz(msglen);
|
||||||
|
|
||||||
|
switch (cb->type) {
|
||||||
|
case kCallbackLua:
|
||||||
|
snprintf(msg, msglen, "<lua: %d>", cb->data.luaref);
|
||||||
|
break;
|
||||||
|
case kCallbackFuncref:
|
||||||
|
// TODO(tjdevries): Is this enough space for this?
|
||||||
|
snprintf(msg, msglen, "<vim function: %s>", cb->data.funcref);
|
||||||
|
break;
|
||||||
|
case kCallbackPartial:
|
||||||
|
snprintf(msg, msglen, "<vim partial: %s>", cb->data.partial->pt_name);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
snprintf(msg, msglen, "%s", "");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
/// Remove watcher from a dictionary
|
/// Remove watcher from a dictionary
|
||||||
///
|
///
|
||||||
/// @param dict Dictionary to remove watcher from.
|
/// @param dict Dictionary to remove watcher from.
|
||||||
|
@ -135,17 +135,22 @@ describe('autocmd api', function()
|
|||||||
local desc = 'Can show description'
|
local desc = 'Can show description'
|
||||||
meths.set_var('desc', desc)
|
meths.set_var('desc', desc)
|
||||||
|
|
||||||
exec_lua([[
|
local result = exec_lua([[
|
||||||
local callback = function() print 'Should Not Have Errored' end
|
local callback = function() print 'Should Not Have Errored' end
|
||||||
vim.api.nvim_create_autocmd("BufReadPost", {
|
vim.api.nvim_create_autocmd("BufReadPost", {
|
||||||
pattern = "*.py",
|
pattern = "*.py",
|
||||||
callback = callback,
|
callback = callback,
|
||||||
desc = vim.g.desc,
|
desc = vim.g.desc,
|
||||||
})
|
})
|
||||||
|
local aus = vim.api.nvim_get_autocmds({ event = 'BufReadPost' })
|
||||||
|
local first = aus[1]
|
||||||
|
return {
|
||||||
|
desc = first.desc,
|
||||||
|
cbtype = type(first.callback)
|
||||||
|
}
|
||||||
]])
|
]])
|
||||||
|
|
||||||
eq(desc, meths.get_autocmds({ event = 'BufReadPost' })[1].desc)
|
eq({ desc = desc, cbtype = 'function' }, result)
|
||||||
matches('<lua: %d+>', meths.get_autocmds({ event = 'BufReadPost' })[1].command)
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('will not add a description unless it was provided', function()
|
it('will not add a description unless it was provided', function()
|
||||||
@ -465,6 +470,49 @@ describe('autocmd api', function()
|
|||||||
-- 3-7 for the 5 we make in the autocmd
|
-- 3-7 for the 5 we make in the autocmd
|
||||||
eq({1, 2, 3, 4, 5, 6, 7}, bufs)
|
eq({1, 2, 3, 4, 5, 6, 7}, bufs)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('can retrieve a callback from an autocmd', function()
|
||||||
|
local content = 'I Am A Callback'
|
||||||
|
meths.set_var('content', content)
|
||||||
|
|
||||||
|
local result = exec_lua([[
|
||||||
|
local cb = function() return vim.g.content end
|
||||||
|
vim.api.nvim_create_autocmd("User", {
|
||||||
|
pattern = "TestTrigger",
|
||||||
|
desc = "A test autocommand with a callback",
|
||||||
|
callback = cb,
|
||||||
|
})
|
||||||
|
local aus = vim.api.nvim_get_autocmds({ event = 'User', pattern = 'TestTrigger'})
|
||||||
|
local first = aus[1]
|
||||||
|
return {
|
||||||
|
cb = {
|
||||||
|
type = type(first.callback),
|
||||||
|
can_retrieve = first.callback() == vim.g.content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]])
|
||||||
|
|
||||||
|
eq("function", result.cb.type)
|
||||||
|
eq(true, result.cb.can_retrieve)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('will return an empty string as the command for an autocmd that uses a callback', function()
|
||||||
|
local result = exec_lua([[
|
||||||
|
local callback = function() print 'I Am A Callback' end
|
||||||
|
vim.api.nvim_create_autocmd("BufWritePost", {
|
||||||
|
pattern = "*.py",
|
||||||
|
callback = callback,
|
||||||
|
})
|
||||||
|
local aus = vim.api.nvim_get_autocmds({ event = 'BufWritePost' })
|
||||||
|
local first = aus[1]
|
||||||
|
return {
|
||||||
|
command = first.command,
|
||||||
|
cbtype = type(first.callback)
|
||||||
|
}
|
||||||
|
]])
|
||||||
|
|
||||||
|
eq({ command = "", cbtype = 'function' }, result)
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('groups', function()
|
describe('groups', function()
|
||||||
|
Loading…
Reference in New Issue
Block a user