aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/api.txt25
-rw-r--r--src/nvim/api/autocmd.c16
-rw-r--r--src/nvim/autocmd.c55
-rw-r--r--test/functional/api/autocmd_spec.lua48
4 files changed, 129 insertions, 15 deletions
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index b383c5eaef..095f74b65d 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -3240,7 +3240,7 @@ nvim_create_autocmd({event}, {*opts}) *nvim_create_autocmd()*
<
Parameters: ~
- {event} (String|Array) The event or events to register
+ {event} (string|array) The event or events to register
this autocommand
{opts} Dictionary of autocommand options:
• group (string|integer) optional: the
@@ -3252,9 +3252,26 @@ nvim_create_autocmd({event}, {*opts}) *nvim_create_autocmd()*
Cannot be used with {pattern}.
• desc (string) optional: description of the
autocommand.
- • callback (function|string) optional: Lua
- function or Vim function (as string) to execute
- on event. Cannot be used with {command}
+ • callback (function|string) optional: if a
+ string, the name of a Vimscript function to
+ call when this autocommand is triggered.
+ Otherwise, a Lua function which is called when
+ this autocommand is triggered. Cannot be used
+ with {command}. Lua callbacks can return true
+ to delete the autocommand; in addition, they
+ accept a single table argument with the
+ following keys:
+ • id: (number) the autocommand id
+ • event: (string) the name of the event that
+ triggered the autocommand |autocmd-events|
+ • group: (number|nil) the autocommand group id,
+ if it exists
+ • match: (string) the expanded value of
+ |<amatch>|
+ • buf: (number) the expanded value of |<abuf>|
+ • file: (string) the expanded value of
+ |<afile>|
+
• command (string) optional: Vim command to
execute on event. Cannot be used with
{callback}
diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c
index 57f392f98e..ccf4ae3d02 100644
--- a/src/nvim/api/autocmd.c
+++ b/src/nvim/api/autocmd.c
@@ -366,7 +366,7 @@ cleanup:
/// {"CursorHold", "BufPreWrite", "BufPostWrite"}
/// </pre>
///
-/// @param event (String|Array) The event or events to register this autocommand
+/// @param event (string|array) The event or events to register this autocommand
/// @param opts Dictionary of autocommand options:
/// - group (string|integer) optional: the autocommand group name or
/// id to match against.
@@ -375,8 +375,18 @@ cleanup:
/// - buffer (integer) optional: buffer number for buffer local autocommands
/// |autocmd-buflocal|. Cannot be used with {pattern}.
/// - desc (string) optional: description of the autocommand.
-/// - callback (function|string) optional: Lua function or Vim function (as string) to
-/// execute on event. Cannot be used with {command}
+/// - callback (function|string) optional: if a string, the name of a Vimscript function
+/// to call when this autocommand is triggered. Otherwise, a Lua function which is
+/// called when this autocommand is triggered. Cannot be used with {command}. Lua
+/// callbacks can return true to delete the autocommand; in addition, they accept a
+/// single table argument with the following keys:
+/// - id: (number) the autocommand id
+/// - event: (string) the name of the event that triggered the autocommand
+/// |autocmd-events|
+/// - group: (number|nil) the autocommand group id, if it exists
+/// - match: (string) the expanded value of |<amatch>|
+/// - buf: (number) the expanded value of |<abuf>|
+/// - file: (string) the expanded value of |<afile>|
/// - command (string) optional: Vim command to execute on event. Cannot be used with
/// {callback}
/// - once (boolean) optional: defaults to false. Run the autocommand
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 5fc36a8412..48c1bb740d 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -2005,6 +2005,50 @@ void auto_next_pat(AutoPatCmd *apc, int stop_at_last)
}
}
+static bool call_autocmd_callback(const AutoCmd *ac, const AutoPatCmd *apc)
+{
+ bool ret = false;
+ Callback callback = ac->exec.callable.cb;
+ if (callback.type == kCallbackLua) {
+ Dictionary data = ARRAY_DICT_INIT;
+ PUT(data, "id", INTEGER_OBJ(ac->id));
+ PUT(data, "event", CSTR_TO_OBJ(event_nr2name(apc->event)));
+ PUT(data, "match", CSTR_TO_OBJ((char *)autocmd_match));
+ PUT(data, "file", CSTR_TO_OBJ((char *)autocmd_fname));
+ PUT(data, "buf", INTEGER_OBJ(autocmd_bufnr));
+
+ int group = apc->curpat->group;
+ switch (group) {
+ case AUGROUP_ERROR:
+ abort(); // unreachable
+ case AUGROUP_DEFAULT:
+ case AUGROUP_ALL:
+ case AUGROUP_DELETED:
+ // omit group in these cases
+ break;
+ default:
+ PUT(data, "group", INTEGER_OBJ(group));
+ break;
+ }
+
+ FIXED_TEMP_ARRAY(args, 1);
+ args.items[0] = DICTIONARY_OBJ(data);
+
+ Object result = nlua_call_ref(callback.data.luaref, NULL, args, true, NULL);
+ if (result.type == kObjectTypeBoolean) {
+ ret = result.data.boolean;
+ }
+ api_free_dictionary(data);
+ api_free_object(result);
+ } else {
+ typval_T argsin = TV_INITIAL_VALUE;
+ typval_T rettv = TV_INITIAL_VALUE;
+ callback_call(&callback, 0, &argsin, &rettv);
+ }
+
+ return ret;
+}
+
/// Get next autocommand command.
/// Called by do_cmdline() to get the next line for ":if".
/// @return allocated string, or NULL for end of autocommands.
@@ -2069,16 +2113,11 @@ char_u *getnextac(int c, void *cookie, int indent, bool do_concat)
current_sctx = ac->script_ctx;
if (ac->exec.type == CALLABLE_CB) {
- typval_T argsin = TV_INITIAL_VALUE;
- typval_T rettv = TV_INITIAL_VALUE;
- if (callback_call(&ac->exec.callable.cb, 0, &argsin, &rettv)) {
- if (ac->exec.callable.cb.type == kCallbackLua) {
- // If a Lua callback returns 'true' then the autocommand is removed
- oneshot = true;
- }
+ if (call_autocmd_callback(ac, acp)) {
+ // If an autocommand callback returns true, delete the autocommand
+ oneshot = true;
}
-
// TODO(tjdevries):
//
// Major Hack Alert:
diff --git a/test/functional/api/autocmd_spec.lua b/test/functional/api/autocmd_spec.lua
index b4a9a4f01f..377b4fecf0 100644
--- a/test/functional/api/autocmd_spec.lua
+++ b/test/functional/api/autocmd_spec.lua
@@ -182,6 +182,54 @@ describe('autocmd api', function()
meths.exec_autocmds("User", {pattern = "Test"})
eq({}, meths.get_autocmds({event = "User", pattern = "Test"}))
end)
+
+ it('receives an args table', function()
+ local res = exec_lua [[
+ local group_id = vim.api.nvim_create_augroup("TestGroup", {})
+ local autocmd_id = vim.api.nvim_create_autocmd("User", {
+ group = "TestGroup",
+ pattern = "Te*",
+ callback = function(args)
+ vim.g.autocmd_args = args
+ end,
+ })
+
+ return {group_id, autocmd_id}
+ ]]
+
+ meths.exec_autocmds("User", {pattern = "Test pattern"})
+ eq({
+ id = res[2],
+ group = res[1],
+ event = "User",
+ match = "Test pattern",
+ file = "Test pattern",
+ buf = 1,
+ }, meths.get_var("autocmd_args"))
+
+ -- Test without a group
+ res = exec_lua [[
+ local autocmd_id = vim.api.nvim_create_autocmd("User", {
+ pattern = "*",
+ callback = function(args)
+ vim.g.autocmd_args = args
+ end,
+ })
+
+ return {autocmd_id}
+ ]]
+
+ meths.exec_autocmds("User", {pattern = "some_pat"})
+ eq({
+ id = res[1],
+ group = nil,
+ event = "User",
+ match = "some_pat",
+ file = "some_pat",
+ buf = 1,
+ }, meths.get_var("autocmd_args"))
+
+ end)
end)
describe('nvim_get_autocmds', function()