mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
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.
This commit is contained in:
parent
d7dd600716
commit
8a9ab88945
@ -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|
|
||||
|
@ -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) {
|
||||
|
@ -146,6 +146,7 @@ return {
|
||||
"group";
|
||||
"modeline";
|
||||
"pattern";
|
||||
"data";
|
||||
};
|
||||
get_autocmds = {
|
||||
"event";
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user