aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkylo252 <59826753+kylo252@users.noreply.github.com>2022-06-09 15:18:56 +0200
committerGitHub <noreply@github.com>2022-06-09 07:18:56 -0600
commit3da3cfc864e89a2dca6917183915683373c85af8 (patch)
tree8233b38ee94a3aa3c8cede35dabb9ee8c774993a
parentc5720c72213810adb75d3277ac645eb6fc8dafa8 (diff)
downloadrneovim-3da3cfc864e89a2dca6917183915683373c85af8.tar.gz
rneovim-3da3cfc864e89a2dca6917183915683373c85af8.tar.bz2
rneovim-3da3cfc864e89a2dca6917183915683373c85af8.zip
feat(autocmds): retrieve lua callback (#18642)
add a new `callback` field to `nvim_get_autocmds`
-rw-r--r--runtime/doc/api.txt6
-rw-r--r--src/nvim/api/autocmd.c38
-rw-r--r--src/nvim/autocmd.c28
-rw-r--r--src/nvim/eval/typval.c24
-rw-r--r--test/functional/api/autocmd_spec.lua54
5 files changed, 112 insertions, 38 deletions
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 2c75acbe1f..e47c5cbd6f 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -3610,7 +3610,11 @@ nvim_get_autocmds({*opts}) *nvim_get_autocmds()*
• group_name (string): the autocommand group name.
• desc (string): the autocommand description.
• 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.
• pattern (string): the autocommand pattern. If the
diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c
index 19b4119344..3a35e49dc8 100644
--- a/src/nvim/api/autocmd.c
+++ b/src/nvim/api/autocmd.c
@@ -66,7 +66,9 @@ static int64_t next_autocmd_id = 1;
/// - group_name (string): the autocommand group name.
/// - desc (string): the autocommand description.
/// - 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.
/// - pattern (string): the autocommand pattern.
/// 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,
- "command",
- STRING_OBJ(cstr_as_string(aucmd_exec_to_string(ac, ac->exec))));
+ if (ac->exec.type == CALLABLE_CB) {
+ PUT(autocmd_info, "command", STRING_OBJ(STRING_INIT));
+
+ 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,
"pattern",
@@ -442,7 +463,8 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
// not do that.
Object *callback = &opts->callback;
- if (callback->type == kObjectTypeLuaRef) {
+ switch (callback->type) {
+ case kObjectTypeLuaRef:
if (callback->data.luaref == LUA_NOREF) {
api_set_error(err,
kErrorTypeValidation,
@@ -459,10 +481,12 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
cb.type = kCallbackLua;
cb.data.luaref = api_new_luaref(callback->data.luaref);
- } else if (callback->type == kObjectTypeString) {
+ break;
+ case kObjectTypeString:
cb.type = kCallbackFuncref;
cb.data.funcref = string_to_cstr(callback->data.string);
- } else {
+ break;
+ default:
api_set_error(err,
kErrorTypeException,
"'callback' must be a lua function or name of vim function");
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 31efce13f6..69f01afcb6 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -2477,32 +2477,6 @@ bool autocmd_delete_id(int64_t id)
// 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
char *aucmd_exec_to_string(AutoCmd *ac, AucmdExecutable acc)
FUNC_ATTR_PURE
@@ -2511,7 +2485,7 @@ char *aucmd_exec_to_string(AutoCmd *ac, AucmdExecutable acc)
case CALLABLE_EX:
return xstrdup(acc.callable.cmd);
case CALLABLE_CB:
- return aucmd_callback_to_string(acc.callable.cb);
+ return callback_to_string(&acc.callable.cb);
case CALLABLE_NONE:
return "This is not possible";
}
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index 2c76741891..97726da5f4 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -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
///
/// @param dict Dictionary to remove watcher from.
diff --git a/test/functional/api/autocmd_spec.lua b/test/functional/api/autocmd_spec.lua
index 491dac9f35..5dfcd09438 100644
--- a/test/functional/api/autocmd_spec.lua
+++ b/test/functional/api/autocmd_spec.lua
@@ -135,17 +135,22 @@ describe('autocmd api', function()
local desc = 'Can show description'
meths.set_var('desc', desc)
- exec_lua([[
+ local result = exec_lua([[
local callback = function() print 'Should Not Have Errored' end
vim.api.nvim_create_autocmd("BufReadPost", {
pattern = "*.py",
callback = callback,
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)
- matches('<lua: %d+>', meths.get_autocmds({ event = 'BufReadPost' })[1].command)
+ eq({ desc = desc, cbtype = 'function' }, result)
end)
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
eq({1, 2, 3, 4, 5, 6, 7}, bufs)
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)
describe('groups', function()