aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Anders <8965202+gpanders@users.noreply.github.com>2022-05-18 09:51:26 -0600
committerGitHub <noreply@github.com>2022-05-18 09:51:26 -0600
commit8a9ab88945cdabcbd23f23406353ec6110fefa83 (patch)
tree5e71bf2543032471d30fce29ced806bf07021bfd
parentd7dd6007167eac919205404bc4e556237118a7a7 (diff)
downloadrneovim-8a9ab88945cdabcbd23f23406353ec6110fefa83.tar.gz
rneovim-8a9ab88945cdabcbd23f23406353ec6110fefa83.tar.bz2
rneovim-8a9ab88945cdabcbd23f23406353ec6110fefa83.zip
feat(api): enable nvim_exec_autocmds to pass arbitrary data (#18613)
Add a "data" key to nvim_exec_autocmds that passes arbitrary data (API objects) to autocommand callbacks.
-rw-r--r--runtime/doc/api.txt5
-rw-r--r--src/nvim/api/autocmd.c10
-rw-r--r--src/nvim/api/keysets.lua1
-rw-r--r--src/nvim/autocmd.c17
-rw-r--r--src/nvim/autocmd.h1
-rw-r--r--test/functional/api/autocmd_spec.lua28
6 files changed, 56 insertions, 6 deletions
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 86ec05417c..7c669e3c9d 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -3469,6 +3469,8 @@ nvim_create_autocmd({event}, {*opts}) *nvim_create_autocmd()*
• buf: (number) the expanded value of |<abuf>|
• file: (string) the expanded value of
|<afile>|
+ • data: (any) arbitrary data passed to
+ |nvim_exec_autocmds()|
• command (string) optional: Vim command to
execute on event. Cannot be used with
@@ -3544,6 +3546,9 @@ nvim_exec_autocmds({event}, {*opts}) *nvim_exec_autocmds()*
• modeline (bool) optional: defaults to true.
Process the modeline after the autocommands
|<nomodeline>|.
+ • data (any): arbitrary data to send to the
+ autocommand callback. See
+ |nvim_create_autocmd()| for details.
See also: ~
|:doautocmd|
diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c
index 76e531e7aa..30a5d60c39 100644
--- a/src/nvim/api/autocmd.c
+++ b/src/nvim/api/autocmd.c
@@ -405,6 +405,7 @@ cleanup:
/// - match: (string) the expanded value of |<amatch>|
/// - buf: (number) the expanded value of |<abuf>|
/// - file: (string) the expanded value of |<afile>|
+/// - data: (any) arbitrary data passed to |nvim_exec_autocmds()|
/// - command (string) optional: Vim command to execute on event. Cannot be used with
/// {callback}
/// - once (boolean) optional: defaults to false. Run the autocommand
@@ -749,6 +750,8 @@ void nvim_del_augroup_by_name(String name, Error *err)
/// {pattern}.
/// - modeline (bool) optional: defaults to true. Process the
/// modeline after the autocommands |<nomodeline>|.
+/// - data (any): arbitrary data to send to the autocommand callback. See
+/// |nvim_create_autocmd()| for details.
/// @see |:doautocmd|
void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
FUNC_API_SINCE(9)
@@ -760,6 +763,7 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
bool set_buf = false;
char *pattern = NULL;
+ Object *data = NULL;
bool set_pattern = false;
Array event_array = ARRAY_DICT_INIT;
@@ -818,6 +822,10 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
set_pattern = true;
}
+ if (opts->data.type != kObjectTypeNil) {
+ data = &opts->data;
+ }
+
modeline = api_object_to_bool(opts->modeline, "modeline", true, err);
if (set_pattern && set_buf) {
@@ -829,7 +837,7 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
FOREACH_ITEM(event_array, event_str, {
GET_ONE_EVENT(event_nr, event_str, cleanup)
- did_aucmd |= apply_autocmds_group(event_nr, pattern, NULL, true, au_group, buf, NULL);
+ did_aucmd |= apply_autocmds_group(event_nr, pattern, NULL, true, au_group, buf, NULL, data);
})
if (did_aucmd && modeline) {
diff --git a/src/nvim/api/keysets.lua b/src/nvim/api/keysets.lua
index 27228204e0..6924e2ef8f 100644
--- a/src/nvim/api/keysets.lua
+++ b/src/nvim/api/keysets.lua
@@ -146,6 +146,7 @@ return {
"group";
"modeline";
"pattern";
+ "data";
};
get_autocmds = {
"event";
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 6c7950fdd1..b87c7886e3 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -1220,7 +1220,7 @@ int do_doautocmd(char *arg_start, bool do_msg, bool *did_something)
// Loop over the events.
while (*arg && !ends_excmd(*arg) && !ascii_iswhite(*arg)) {
if (apply_autocmds_group(event_name2nr(arg, &arg), fname, NULL, true, group,
- curbuf, NULL)) {
+ curbuf, NULL, NULL)) {
nothing_done = false;
}
}
@@ -1505,7 +1505,7 @@ win_found:
/// @return true if some commands were executed.
bool apply_autocmds(event_T event, char *fname, char *fname_io, bool force, buf_T *buf)
{
- return apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf, NULL);
+ return apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf, NULL, NULL);
}
/// Like apply_autocmds(), but with extra "eap" argument. This takes care of
@@ -1522,7 +1522,7 @@ bool apply_autocmds(event_T event, char *fname, char *fname_io, bool force, buf_
bool apply_autocmds_exarg(event_T event, char *fname, char *fname_io, bool force, buf_T *buf,
exarg_T *eap)
{
- return apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf, eap);
+ return apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf, eap, NULL);
}
/// Like apply_autocmds(), but handles the caller's retval. If the script
@@ -1546,7 +1546,7 @@ bool apply_autocmds_retval(event_T event, char *fname, char *fname_io, bool forc
}
bool did_cmd = apply_autocmds_group(event, fname, fname_io, force,
- AUGROUP_ALL, buf, NULL);
+ AUGROUP_ALL, buf, NULL, NULL);
if (did_cmd && aborting()) {
*retval = FAIL;
}
@@ -1595,7 +1595,7 @@ bool trigger_cursorhold(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
///
/// @return true if some commands were executed.
bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force, int group,
- buf_T *buf, exarg_T *eap)
+ buf_T *buf, exarg_T *eap, Object *data)
{
char *sfname = NULL; // short file name
bool retval = false;
@@ -1811,6 +1811,9 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
patcmd.next = active_apc_list;
active_apc_list = &patcmd;
+ // Attach data to command
+ patcmd.data = data;
+
// set v:cmdarg (only when there is a matching pattern)
save_cmdbang = (long)get_vim_var_nr(VV_CMDBANG);
if (eap != NULL) {
@@ -2026,6 +2029,10 @@ static bool call_autocmd_callback(const AutoCmd *ac, const AutoPatCmd *apc)
PUT(data, "file", CSTR_TO_OBJ((char *)autocmd_fname));
PUT(data, "buf", INTEGER_OBJ(autocmd_bufnr));
+ if (apc->data) {
+ PUT(data, "data", copy_object(*apc->data));
+ }
+
int group = apc->curpat->group;
switch (group) {
case AUGROUP_ERROR:
diff --git a/src/nvim/autocmd.h b/src/nvim/autocmd.h
index d3503672fd..47f583ae13 100644
--- a/src/nvim/autocmd.h
+++ b/src/nvim/autocmd.h
@@ -57,6 +57,7 @@ typedef struct AutoPatCmd {
char *tail; // tail of fname
event_T event; // current event
int arg_bufnr; // initially equal to <abuf>, set to zero when buf is deleted
+ Object *data; // arbitrary data
struct AutoPatCmd *next; // chain of active apc-s for auto-invalidation
} AutoPatCmd;
diff --git a/test/functional/api/autocmd_spec.lua b/test/functional/api/autocmd_spec.lua
index 41de308a2c..c08c411de1 100644
--- a/test/functional/api/autocmd_spec.lua
+++ b/test/functional/api/autocmd_spec.lua
@@ -230,6 +230,34 @@ describe('autocmd api', function()
}, meths.get_var("autocmd_args"))
end)
+
+ it('can receive arbitrary data', function()
+ local function test(data)
+ eq(data, exec_lua([[
+ local input = ...
+ local output
+ vim.api.nvim_create_autocmd("User", {
+ pattern = "Test",
+ callback = function(args)
+ output = args.data
+ end,
+ })
+
+ vim.api.nvim_exec_autocmds("User", {
+ pattern = "Test",
+ data = input,
+ })
+
+ return output
+ ]], data))
+ end
+
+ test("Hello")
+ test(42)
+ test(true)
+ test({ "list" })
+ test({ foo = "bar" })
+ end)
end)
describe('nvim_get_autocmds', function()