feat(lua): add missing changes to autocmds lost in the rebase

Note: some of these changes are breaking, like change of API signatures
This commit is contained in:
TJ DeVries 2021-05-28 15:45:34 -04:00 committed by bfredl
parent 6732cd9e57
commit 0f613482b3
10 changed files with 389 additions and 229 deletions

View File

@ -3108,6 +3108,130 @@ nvim_tabpage_set_var({tabpage}, {name}, {value})
{value} Variable value {value} Variable value
==============================================================================
Autocmd Functions *api-autocmd*
nvim_create_augroup({name}, {*opts}) *nvim_create_augroup()*
Create or get an augroup.
To get an existing augroup ID, do: >
local id = vim.api.nvim_create_augroup(name, {
clear = false
})
<
Parameters: ~
{name} String: The name of the augroup to create
{opts} Parameters
• clear (bool): Whether to clear existing commands
or not. Defaults to true. See |autocmd-groups|
Return: ~
opaque value to use with nvim_del_augroup_by_id
nvim_create_autocmd({event}, {*opts}) *nvim_create_autocmd()*
Create an autocmd.
Examples:
• event: "pat1,pat2,pat3",
• event: "pat1"
• event: { "pat1" }
• event: { "pat1", "pat2", "pat3" }
Parameters: ~
{event} The event or events to register this autocmd
Required keys: event: string | ArrayOf(string)
Parameters: ~
{opts} Optional Parameters:
• callback: (string|function)
• (string): The name of the viml function to
execute when triggering this autocmd
• (function): The lua function to execute when
triggering this autocmd
• NOTE: Cannot be used with {command}
• command: (string) command
• vimscript command
• NOTE: Cannot be used with {callback} Eg.
command = "let g:value_set = v:true"
• pattern: (string|table)
• pattern or patterns to match against
• defaults to "*".
• NOTE: Cannot be used with {buffer}
• buffer: (bufnr)
• create a |autocmd-buflocal| autocmd.
• NOTE: Cannot be used with {pattern}
• group: (string) The augroup name
• once: (boolean) - See |autocmd-once|
• nested: (boolean) - See |autocmd-nested|
• desc: (string) - Description of the autocmd
Return: ~
opaque value to use with nvim_del_autocmd
nvim_del_augroup_by_id({id}) *nvim_del_augroup_by_id()*
Delete an augroup by {id}. {id} can only be returned when
augroup was created with |nvim_create_augroup|.
NOTE: behavior differs from augroup-delete.
When deleting an augroup, autocmds contained by this augroup
will also be deleted and cleared. This augroup will no longer
exist
nvim_del_augroup_by_name({name}) *nvim_del_augroup_by_name()*
Delete an augroup by {name}.
NOTE: behavior differs from augroup-delete.
When deleting an augroup, autocmds contained by this augroup
will also be deleted and cleared. This augroup will no longer
exist
nvim_del_autocmd({id}) *nvim_del_autocmd()*
Delete an autocmd by {id}. Autocmds only return IDs when
created via the API. Will not error if called and no autocmds
match the {id}.
Parameters: ~
{id} Integer The ID returned by nvim_create_autocmd
nvim_do_autocmd({event}, {*opts}) *nvim_do_autocmd()*
Do one autocmd.
Parameters: ~
{event} The event or events to execute
{opts} Optional Parameters:
• buffer (number) - buffer number
• NOTE: Cannot be used with {pattern}
• pattern (string|table) - optional, defaults to
"*".
• NOTE: Cannot be used with {buffer}
• group (string) - autocmd group name
• modeline (boolean) - Default true, see
|<nomodeline>|
nvim_get_autocmds({*opts}) *nvim_get_autocmds()*
Get autocmds that match the requirements passed to {opts}.
Parameters: ~
{opts} Optional Parameters:
• event : Name or list of name of events to match
against
• group (string): Name of group to match against
• pattern: Pattern or list of patterns to match
against
Return: ~
A list of autocmds that match
============================================================================== ==============================================================================
UI Functions *api-ui* UI Functions *api-ui*

View File

@ -17,34 +17,7 @@
#define AUCMD_MAX_PATTERNS 256 #define AUCMD_MAX_PATTERNS 256
// Check whether every item in the array is a kObjectTypeString
#define CHECK_STRING_ARRAY(__array, k, v, goto_name) \
for (size_t j = 0; j < __array.size; j++) { \
Object item = __array.items[j]; \
if (item.type != kObjectTypeString) { \
api_set_error(err, \
kErrorTypeValidation, \
"All entries in '%s' must be strings", \
k); \
goto goto_name; \
} \
}
// Copy string or array of strings into an empty array. // Copy string or array of strings into an empty array.
#define UNPACK_STRING_OR_ARRAY(__array, k, v, goto_name) \
if (v->type == kObjectTypeString) { \
ADD(__array, copy_object(*v)); \
} else if (v->type == kObjectTypeArray) { \
CHECK_STRING_ARRAY(__array, k, v, goto_name); \
__array = copy_array(v->data.array); \
} else { \
api_set_error(err, \
kErrorTypeValidation, \
"'%s' must be an array or a string.", \
k); \
goto goto_name; \
}
// Get the event number, unless it is an error. Then goto `goto_name`. // Get the event number, unless it is an error. Then goto `goto_name`.
#define GET_ONE_EVENT(event_nr, event_str, goto_name) \ #define GET_ONE_EVENT(event_nr, event_str, goto_name) \
char_u *__next_ev; \ char_u *__next_ev; \
@ -61,16 +34,18 @@
static int64_t next_autocmd_id = 1; static int64_t next_autocmd_id = 1;
/// Get autocmds that match the requirements passed to {opts}. /// Get autocmds that match the requirements passed to {opts}.
/// group
/// event
/// pattern
/// ///
/// -- @param {string} event - event or events to match against /// @param opts Optional Parameters:
/// vim.api.nvim_get_autocmds({ event = "FileType" }) /// - event : Name or list of name of events to match against
/// - group (string): Name of group to match against
/// - pattern: Pattern or list of patterns to match against
/// ///
/// @return A list of autocmds that match
Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
FUNC_API_SINCE(9) FUNC_API_SINCE(9)
{ {
// TODO(tjdevries): Would be cool to add nvim_get_autocmds({ id = ... })
Array autocmd_list = ARRAY_DICT_INIT; Array autocmd_list = ARRAY_DICT_INIT;
char_u *pattern_filters[AUCMD_MAX_PATTERNS]; char_u *pattern_filters[AUCMD_MAX_PATTERNS];
char_u pattern_buflocal[BUFLOCAL_PAT_LEN]; char_u pattern_buflocal[BUFLOCAL_PAT_LEN];
@ -199,6 +174,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
if (aucmd_exec_is_deleted(ac->exec)) { if (aucmd_exec_is_deleted(ac->exec)) {
continue; continue;
} }
Dictionary autocmd_info = ARRAY_DICT_INIT; Dictionary autocmd_info = ARRAY_DICT_INIT;
if (ap->group != AUGROUP_DEFAULT) { if (ap->group != AUGROUP_DEFAULT) {
@ -256,40 +232,42 @@ cleanup:
return autocmd_list; return autocmd_list;
} }
/// Define an autocmd. /// Create an autocmd.
/// @param opts Dictionary ///
/// @param event The event or events to register this autocmd
/// Required keys: /// Required keys:
/// event: string | ArrayOf(string) /// event: string | ArrayOf(string)
/// event = "pat1,pat2,pat3",
/// event = "pat1"
/// event = {"pat1"}
/// event = {"pat1", "pat2", "pat3"}
/// ///
/// Examples:
/// - event: "pat1,pat2,pat3",
/// - event: "pat1"
/// - event: { "pat1" }
/// - event: { "pat1", "pat2", "pat3" }
/// ///
/// -- @param {string} name - augroup name /// @param opts Optional Parameters:
/// -- @param {string | table} event - event or events to match against /// - callback: (string|function)
/// -- @param {string | table} pattern - pattern or patterns to match against /// - (string): The name of the viml function to execute when triggering this autocmd
/// -- @param {string | function} callback - function or string to execute on autocmd /// - (function): The lua function to execute when triggering this autocmd
/// -- @param {string} command - optional, vimscript command /// - NOTE: Cannot be used with {command}
/// Eg. command = "let g:value_set = v:true" /// - command: (string) command
/// -- @param {boolean} once - optional, defaults to false /// - vimscript command
/// - NOTE: Cannot be used with {callback}
/// Eg. command = "let g:value_set = v:true"
/// - pattern: (string|table)
/// - pattern or patterns to match against
/// - defaults to "*".
/// - NOTE: Cannot be used with {buffer}
/// - buffer: (bufnr)
/// - create a |autocmd-buflocal| autocmd.
/// - NOTE: Cannot be used with {pattern}
/// - group: (string) The augroup name
/// - once: (boolean) - See |autocmd-once|
/// - nested: (boolean) - See |autocmd-nested|
/// - desc: (string) - Description of the autocmd
/// ///
/// -- pattern = comma delimited list of patterns | pattern | { pattern, ... } /// @returns opaque value to use with nvim_del_autocmd
/// Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autocmd) *opts,
/// pattern = "*.py,*.pyi" Error *err)
/// pattern = "*.py"
/// pattern = {"*.py"}
/// pattern = { "*.py", "*.pyi" }
///
/// -- not supported
/// pattern = {"*.py,*.pyi"}
///
/// -- event = string | string[]
/// event = "FileType,CursorHold"
/// event = "BufPreWrite"
/// event = {"BufPostWrite"}
/// event = {"CursorHold", "BufPreWrite", "BufPostWrite"}
Integer nvim_create_autocmd(uint64_t channel_id, Dict(create_autocmd) *opts, Error *err)
FUNC_API_SINCE(9) FUNC_API_SINCE(9)
{ {
int64_t autocmd_id = -1; int64_t autocmd_id = -1;
@ -304,6 +282,11 @@ Integer nvim_create_autocmd(uint64_t channel_id, Dict(create_autocmd) *opts, Err
AucmdExecutable aucmd = AUCMD_EXECUTABLE_INIT; AucmdExecutable aucmd = AUCMD_EXECUTABLE_INIT;
Callback cb = CALLBACK_NONE; Callback cb = CALLBACK_NONE;
if (!unpack_string_or_array(&event_array, &event, "event", err)) {
goto cleanup;
}
if (opts->callback.type != kObjectTypeNil && opts->command.type != kObjectTypeNil) { if (opts->callback.type != kObjectTypeNil && opts->command.type != kObjectTypeNil) {
api_set_error(err, kErrorTypeValidation, api_set_error(err, kErrorTypeValidation,
"cannot pass both: 'callback' and 'command' for the same autocmd"); "cannot pass both: 'callback' and 'command' for the same autocmd");
@ -359,14 +342,10 @@ Integer nvim_create_autocmd(uint64_t channel_id, Dict(create_autocmd) *opts, Err
goto cleanup; goto cleanup;
} }
if (opts->event.type != kObjectTypeNil) {
UNPACK_STRING_OR_ARRAY(event_array, "event", (&opts->event), cleanup)
}
bool is_once = api_object_to_bool(opts->once, "once", false, err); bool is_once = api_object_to_bool(opts->once, "once", false, err);
bool is_nested = api_object_to_bool(opts->nested, "nested", false, err); bool is_nested = api_object_to_bool(opts->nested, "nested", false, err);
// TOOD: accept number for namespace instead // TODO(tjdevries): accept number for namespace instead
if (opts->group.type != kObjectTypeNil) { if (opts->group.type != kObjectTypeNil) {
Object *v = &opts->group; Object *v = &opts->group;
if (v->type != kObjectTypeString) { if (v->type != kObjectTypeString) {
@ -402,7 +381,9 @@ Integer nvim_create_autocmd(uint64_t channel_id, Dict(create_autocmd) *opts, Err
patlen = aucmd_pattern_length(pat); patlen = aucmd_pattern_length(pat);
} }
} else if (v->type == kObjectTypeArray) { } else if (v->type == kObjectTypeArray) {
CHECK_STRING_ARRAY(patterns, "pattern", v, cleanup); if (!check_autocmd_string_array(patterns, "pattern", err)) {
goto cleanup;
}
Array array = v->data.array; Array array = v->data.array;
for (size_t i = 0; i < array.size; i++) { for (size_t i = 0; i < array.size; i++) {
@ -503,8 +484,9 @@ cleanup:
return autocmd_id; return autocmd_id;
} }
/// Delete an autocmd by ID. Autocmds only return IDs when created /// Delete an autocmd by {id}. Autocmds only return IDs when created
/// via the API. /// via the API. Will not error if called and no autocmds match
/// the {id}.
/// ///
/// @param id Integer The ID returned by nvim_create_autocmd /// @param id Integer The ID returned by nvim_create_autocmd
void nvim_del_autocmd(Integer id) void nvim_del_autocmd(Integer id)
@ -517,28 +499,28 @@ void nvim_del_autocmd(Integer id)
/// ///
/// To get an existing augroup ID, do: /// To get an existing augroup ID, do:
/// <pre> /// <pre>
/// local id = vim.api.nvim_create_augroup({ name = name, clear = false }); /// local id = vim.api.nvim_create_augroup(name, {
/// clear = false
/// })
/// </pre> /// </pre>
/// ///
/// @param name String: The name of the augroup to create
/// @param opts Parameters /// @param opts Parameters
/// - name (string): The name of the augroup
/// - clear (bool): Whether to clear existing commands or not. /// - clear (bool): Whether to clear existing commands or not.
// Defaults to true. /// Defaults to true.
/// See |autocmd-groups| /// See |autocmd-groups|
Integer nvim_create_augroup(uint64_t channel_id, Dict(create_augroup) *opts, Error *err) ///
/// @returns opaque value to use with nvim_del_augroup_by_id
Integer nvim_create_augroup(uint64_t channel_id, String name, Dict(create_augroup) *opts,
Error *err)
FUNC_API_SINCE(9) FUNC_API_SINCE(9)
{ {
char *augroup_name = name.data;
bool clear_autocmds = api_object_to_bool(opts->clear, "clear", true, err); bool clear_autocmds = api_object_to_bool(opts->clear, "clear", true, err);
if (opts->name.type != kObjectTypeString) {
api_set_error(err, kErrorTypeValidation, "'name' is required and must be a string");
return -1;
}
char *name = opts->name.data.string.data;
int augroup = -1; int augroup = -1;
WITH_SCRIPT_CONTEXT(channel_id, { WITH_SCRIPT_CONTEXT(channel_id, {
augroup = augroup_add(name); augroup = augroup_add(augroup_name);
if (augroup == AUGROUP_ERROR) { if (augroup == AUGROUP_ERROR) {
api_set_error(err, kErrorTypeException, "Failed to set augroup"); api_set_error(err, kErrorTypeException, "Failed to set augroup");
return -1; return -1;
@ -554,7 +536,11 @@ Integer nvim_create_augroup(uint64_t channel_id, Dict(create_augroup) *opts, Err
return augroup; return augroup;
} }
/// Delete an augroup by {id}. {id} can only be returned when augroup was
/// created with |nvim_create_augroup|.
///
/// NOTE: behavior differs from augroup-delete. /// NOTE: behavior differs from augroup-delete.
///
/// When deleting an augroup, autocmds contained by this augroup will also be deleted and cleared. /// When deleting an augroup, autocmds contained by this augroup will also be deleted and cleared.
/// This augroup will no longer exist /// This augroup will no longer exist
void nvim_del_augroup_by_id(Integer id) void nvim_del_augroup_by_id(Integer id)
@ -564,7 +550,10 @@ void nvim_del_augroup_by_id(Integer id)
augroup_del(name, false); augroup_del(name, false);
} }
/// Delete an augroup by {name}.
///
/// NOTE: behavior differs from augroup-delete. /// NOTE: behavior differs from augroup-delete.
///
/// When deleting an augroup, autocmds contained by this augroup will also be deleted and cleared. /// When deleting an augroup, autocmds contained by this augroup will also be deleted and cleared.
/// This augroup will no longer exist /// This augroup will no longer exist
void nvim_del_augroup_by_name(String name) void nvim_del_augroup_by_name(String name)
@ -573,12 +562,17 @@ void nvim_del_augroup_by_name(String name)
augroup_del(name.data, false); augroup_del(name.data, false);
} }
/// -- @param {string} group - autocmd group name /// Do one autocmd.
/// -- @param {number} buffer - buffer number ///
/// -- @param {string | table} event - event or events to match against /// @param event The event or events to execute
/// -- @param {string | table} pattern - optional, defaults to "*". /// @param opts Optional Parameters:
/// vim.api.nvim_do_autcmd({ group, buffer, pattern, event, modeline }) /// - buffer (number) - buffer number
void nvim_do_autocmd(Dict(do_autocmd) *opts, Error *err) /// - NOTE: Cannot be used with {pattern}
/// - pattern (string|table) - optional, defaults to "*".
/// - NOTE: Cannot be used with {buffer}
/// - group (string) - autocmd group name
/// - modeline (boolean) - Default true, see |<nomodeline>|
void nvim_do_autocmd(Object event, Dict(do_autocmd) *opts, Error *err)
FUNC_API_SINCE(9) FUNC_API_SINCE(9)
{ {
int au_group = AUGROUP_ALL; int au_group = AUGROUP_ALL;
@ -592,6 +586,10 @@ void nvim_do_autocmd(Dict(do_autocmd) *opts, Error *err)
Array event_array = ARRAY_DICT_INIT; Array event_array = ARRAY_DICT_INIT;
if (!unpack_string_or_array(&event_array, &event, "event", err)) {
goto cleanup;
}
if (opts->group.type != kObjectTypeNil) { if (opts->group.type != kObjectTypeNil) {
if (opts->group.type != kObjectTypeString) { if (opts->group.type != kObjectTypeString) {
api_set_error(err, kErrorTypeValidation, "'group' must be a string"); api_set_error(err, kErrorTypeValidation, "'group' must be a string");
@ -634,13 +632,7 @@ void nvim_do_autocmd(Dict(do_autocmd) *opts, Error *err)
set_pattern = true; set_pattern = true;
} }
if (opts->event.type != kObjectTypeNil) { modeline = api_object_to_bool(opts->modeline, "modeline", true, err);
UNPACK_STRING_OR_ARRAY(event_array, "event", (&opts->event), cleanup)
}
if (opts->modeline.type != kObjectTypeNil) {
modeline = api_object_to_bool(opts->modeline, "modeline", true, err);
}
if (set_pattern && set_buf) { if (set_pattern && set_buf) {
api_set_error(err, kErrorTypeValidation, "must not set 'buffer' and 'pattern'"); api_set_error(err, kErrorTypeValidation, "must not set 'buffer' and 'pattern'");
@ -663,7 +655,46 @@ cleanup:
XFREE_CLEAR(pattern); XFREE_CLEAR(pattern);
} }
static bool check_autocmd_string_array(Array arr, char *k, Error *err)
{
for (size_t i = 0; i < arr.size; i++) {
if (arr.items[i].type != kObjectTypeString) {
api_set_error(err,
kErrorTypeValidation,
"All entries in '%s' must be strings",
k);
return false;
}
// Disallow newlines in the middle of the line.
const String l = arr.items[i].data.string;
if (memchr(l.data, NL, l.size)) {
api_set_error(err, kErrorTypeValidation,
"String cannot contain newlines");
return false;
}
}
return true;
}
static bool unpack_string_or_array(Array *array, Object *v, char *k, Error *err)
{
if (v->type == kObjectTypeString) {
ADD(*array, copy_object(*v));
} else if (v->type == kObjectTypeArray) {
if (!check_autocmd_string_array(v->data.array, k, err)) {
return false;
}
*array = copy_array(v->data.array);
} else {
api_set_error(err,
kErrorTypeValidation,
"'%s' must be an array or a string.",
k);
return false;
}
return true;
}
#undef UNPACK_STRING_OR_ARRAY
#undef CHECK_STRING_ARRAY
#undef GET_ONE_EVENT #undef GET_ONE_EVENT

View File

@ -116,7 +116,6 @@ return {
"callback"; "callback";
"command"; "command";
"desc"; "desc";
"event";
"group"; "group";
"once"; "once";
"nested"; "nested";
@ -124,7 +123,6 @@ return {
}; };
do_autocmd = { do_autocmd = {
"buffer"; "buffer";
"event";
"group"; "group";
"modeline"; "modeline";
"pattern"; "pattern";
@ -132,12 +130,10 @@ return {
get_autocmds = { get_autocmds = {
"event"; "event";
"group"; "group";
"id";
"pattern"; "pattern";
}; };
create_augroup = { create_augroup = {
"clear"; "clear";
"name";
}; };
} }

View File

@ -406,6 +406,7 @@ void set_option_to(uint64_t channel_id, void *to, int type, String name, Object
}); });
} }
buf_T *find_buffer_by_handle(Buffer buffer, Error *err) buf_T *find_buffer_by_handle(Buffer buffer, Error *err)
{ {
if (buffer == 0) { if (buffer == 0) {
@ -1614,8 +1615,8 @@ int find_sid(uint64_t channel_id)
{ {
switch (channel_id) { switch (channel_id) {
case VIML_INTERNAL_CALL: case VIML_INTERNAL_CALL:
// TODO(autocmd): Figure out what this should be // TODO(autocmd): Figure out what this should be
// return SID_API_CLIENT; // return SID_API_CLIENT;
case LUA_INTERNAL_CALL: case LUA_INTERNAL_CALL:
return SID_LUA; return SID_LUA;
default: default:

View File

@ -152,13 +152,15 @@ typedef struct {
#endif #endif
#define WITH_SCRIPT_CONTEXT(channel_id, code) \ #define WITH_SCRIPT_CONTEXT(channel_id, code) \
const sctx_T save_current_sctx = current_sctx; \ do { \
current_sctx.sc_sid = \ const sctx_T save_current_sctx = current_sctx; \
(channel_id) == LUA_INTERNAL_CALL ? SID_LUA : SID_API_CLIENT; \ current_sctx.sc_sid = \
current_sctx.sc_lnum = 0; \ (channel_id) == LUA_INTERNAL_CALL ? SID_LUA : SID_API_CLIENT; \
current_channel_id = channel_id; \ current_sctx.sc_lnum = 0; \
code; \ current_channel_id = channel_id; \
current_sctx = save_current_sctx; code; \
current_sctx = save_current_sctx; \
} while (0);
#endif // NVIM_API_PRIVATE_HELPERS_H #endif // NVIM_API_PRIVATE_HELPERS_H

View File

@ -4,13 +4,10 @@
// autocmd.c: Autocommand related functions // autocmd.c: Autocommand related functions
#include <signal.h> #include <signal.h>
#include "nvim/autocmd.h"
// #include "nvim/api/private/handle.h"
#include "lauxlib.h" #include "lauxlib.h"
#include "nvim/api/private/helpers.h" #include "nvim/api/private/helpers.h"
#include "nvim/ascii.h" #include "nvim/ascii.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h" #include "nvim/buffer.h"
#include "nvim/charset.h" #include "nvim/charset.h"
#include "nvim/cursor.h" #include "nvim/cursor.h"
@ -108,17 +105,6 @@ static char_u *old_termresponse = NULL;
#define FOR_ALL_AUPATS_IN_EVENT(event, ap) \ #define FOR_ALL_AUPATS_IN_EVENT(event, ap) \
for (AutoPat *ap = first_autopat[event]; ap != NULL; ap = ap->next) // NOLINT for (AutoPat *ap = first_autopat[event]; ap != NULL; ap = ap->next) // NOLINT
/// Handles grabbing arguments from `:autocmd` such as ++once and ++nested
#define ARG_GET_FLAG(errored, cmd, flag, pattern, len) \
if (STRNCMP(cmd, pattern, len) == 0 && ascii_iswhite((cmd)[len])) { \
if (flag) { \
semsg(_(e_duparg2), pattern); \
(errored) = true; \
} \
(flag) = true; \
(cmd) = skipwhite((cmd) + (len)); \
}
// Map of autocmd group names. // Map of autocmd group names.
// name -> ID // name -> ID
static Map(String, int) augroup_map = MAP_INIT; static Map(String, int) augroup_map = MAP_INIT;
@ -408,6 +394,16 @@ int augroup_add(char *name)
} }
/// Delete the augroup that matches name. /// Delete the augroup that matches name.
/// @param stupid_legacy_mode bool: This paremeter determines whether to run the augroup
/// deletion in the same fashion as `:augroup! {name}` where if there are any remaining
/// autocmds left in the augroup, it will change the name of the augroup to `--- DELETED ---`
/// but leave the autocmds existing. These are _separate_ augroups, so if you do this for
/// multiple augroups, you will have a bunch of `--- DELETED ---` augroups at the same time.
/// There is no way, as far as I could tell, how to actually delete them at this point as a user
///
/// I did not consider this good behavior, so now when NOT in stupid_legacy_mode, we actually
/// delete these groups and their commands, like you would expect (and don't leave hanging
/// `--- DELETED ---` groups around)
void augroup_del(char *name, bool stupid_legacy_mode) void augroup_del(char *name, bool stupid_legacy_mode)
{ {
int i = augroup_find(name); int i = augroup_find(name);
@ -723,7 +719,7 @@ void do_autocmd(char_u *arg_in, int forceit)
char_u *envpat = NULL; char_u *envpat = NULL;
char_u *cmd; char_u *cmd;
int need_free = false; int need_free = false;
int nested = false; bool nested = false;
bool once = false; bool once = false;
int group; int group;
@ -778,11 +774,11 @@ void do_autocmd(char_u *arg_in, int forceit)
bool invalid_flags = false; bool invalid_flags = false;
for (size_t i = 0; i < 2; i++) { for (size_t i = 0; i < 2; i++) {
if (*cmd != NUL) { if (*cmd != NUL) {
ARG_GET_FLAG(invalid_flags, cmd, once, "++once", 6); invalid_flags |= arg_autocmd_flag_get(&once, &cmd, "++once", 6);
ARG_GET_FLAG(invalid_flags, cmd, nested, "++nested", 8); invalid_flags |= arg_autocmd_flag_get(&nested, &cmd, "++nested", 8);
// Check the deprecated "nested" flag. // Check the deprecated "nested" flag.
ARG_GET_FLAG(invalid_flags, cmd, nested, "nested", 6); invalid_flags |= arg_autocmd_flag_get(&nested, &cmd, "nested", 6);
} }
} }
@ -2050,6 +2046,8 @@ char_u *getnextac(int c, void *cookie, int indent, bool do_concat)
typval_T rettv = TV_INITIAL_VALUE; typval_T rettv = TV_INITIAL_VALUE;
callback_call(&ac->exec.callable.cb, 0, &argsin, &rettv); callback_call(&ac->exec.callable.cb, 0, &argsin, &rettv);
// TODO(tjdevries):
//
// Major Hack Alert: // Major Hack Alert:
// We just return "not-null" and continue going. // We just return "not-null" and continue going.
// This would be a good candidate for a refactor. You would need to refactor: // This would be a good candidate for a refactor. You would need to refactor:
@ -2057,7 +2055,7 @@ char_u *getnextac(int c, void *cookie, int indent, bool do_concat)
// OR // OR
// 2. make where we call do_cmdline for autocmds not have to return anything, // 2. make where we call do_cmdline for autocmds not have to return anything,
// and instead we loop over all the matches and just execute one-by-one. // and instead we loop over all the matches and just execute one-by-one.
// However, my expectation woudl be that could be expensive. // However, my expectation would be that could be expensive.
retval = vim_strsave((char_u *)""); retval = vim_strsave((char_u *)"");
} else { } else {
retval = vim_strsave(ac->exec.callable.cmd); retval = vim_strsave(ac->exec.callable.cmd);
@ -2544,6 +2542,22 @@ static int arg_augroup_get(char_u **argp)
return group; return group;
} }
/// Handles grabbing arguments from `:autocmd` such as ++once and ++nested
static bool arg_autocmd_flag_get(bool *flag, char_u **cmd_ptr, char *pattern, int len)
{
if (STRNCMP(*cmd_ptr, pattern, len) == 0 && ascii_iswhite((*cmd_ptr)[len])) {
if (*flag) {
semsg(_(e_duparg2), pattern);
return true;
}
*flag = true;
*cmd_ptr = skipwhite((*cmd_ptr) + len);
}
return false;
}
// UI Enter // UI Enter
void do_autocmd_uienter(uint64_t chanid, bool attached) void do_autocmd_uienter(uint64_t chanid, bool attached)

View File

@ -27,7 +27,7 @@ typedef struct AutoCmd {
bool once; // "One shot": removed after execution bool once; // "One shot": removed after execution
bool nested; // If autocommands nest here bool nested; // If autocommands nest here
bool last; // last command in list bool last; // last command in list
int64_t id; // TODO(tjdevries): Explain int64_t id; // ID used for uniquely tracking an autocmd.
sctx_T script_ctx; // script context where defined sctx_T script_ctx; // script context where defined
char *desc; // Description for the autocmd. char *desc; // Description for the autocmd.
struct AutoCmd *next; // Next AutoCmd in list struct AutoCmd *next; // Next AutoCmd in list

View File

@ -8,6 +8,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "lauxlib.h"
#include "nvim/ascii.h" #include "nvim/ascii.h"
#include "nvim/assert.h" #include "nvim/assert.h"
#include "nvim/charset.h" #include "nvim/charset.h"
@ -1157,7 +1158,22 @@ void callback_free(Callback *callback)
/// Check if callback is freed /// Check if callback is freed
bool callback_is_freed(Callback callback) bool callback_is_freed(Callback callback)
{ {
return false; switch (callback.type) {
case kCallbackFuncref:
return false;
break;
case kCallbackPartial:
return false;
break;
case kCallbackLua:
return callback.data.luaref == LUA_NOREF;
break;
case kCallbackNone:
return true;
break;
}
return true;
} }
/// Copy a callback into a typval_T. /// Copy a callback into a typval_T.
@ -1176,8 +1192,10 @@ void callback_put(Callback *cb, typval_T *tv)
func_ref(cb->data.funcref); func_ref(cb->data.funcref);
break; break;
case kCallbackLua: case kCallbackLua:
// TODO(tjdevries): I'm not even sure if this is strictly necessary? // TODO(tjdevries): Unified Callback.
abort(); // At this point this isn't possible, but it'd be nice to put
// these handled more neatly in one place.
// So instead, we just do the default and put nil
default: default:
tv->v_type = VAR_SPECIAL; tv->v_type = VAR_SPECIAL;
tv->vval.v_special = kSpecialVarNull; tv->vval.v_special = kSpecialVarNull;

View File

@ -1354,6 +1354,9 @@ bool nlua_ref_is_function(LuaRef ref)
{ {
lua_State *const lstate = global_lstate; lua_State *const lstate = global_lstate;
nlua_pushref(lstate, ref); nlua_pushref(lstate, ref);
// TODO(tjdevries): This should probably check for callable tables as well.
// We should put some work maybe into simplifying how all of that works
bool is_function = (lua_type(lstate, -1) == LUA_TFUNCTION); bool is_function = (lua_type(lstate, -1) == LUA_TFUNCTION);
lua_pop(lstate, 1); lua_pop(lstate, 1);

View File

@ -14,8 +14,7 @@ before_each(clear)
describe('autocmd api', function() describe('autocmd api', function()
describe('nvim_create_autocmd', function() describe('nvim_create_autocmd', function()
it('does not allow "command" and "callback" in the same autocmd', function() it('does not allow "command" and "callback" in the same autocmd', function()
local ok, _ = pcall(meths.create_autocmd, { local ok, _ = pcall(meths.create_autocmd, "BufReadPost", {
event = "BufReadPost",
pattern = "*.py,*.pyi", pattern = "*.py,*.pyi",
command = "echo 'Should Have Errored", command = "echo 'Should Have Errored",
callback = "not allowed", callback = "not allowed",
@ -28,12 +27,11 @@ describe('autocmd api', function()
eq(1, exec_lua([[ eq(1, exec_lua([[
local count = 0 local count = 0
vim.api.nvim_create_autocmd { vim.api.nvim_create_autocmd("FileType", {
event = "FileType",
pattern = "*", pattern = "*",
callback = function() count = count + 1 end, callback = function() count = count + 1 end,
once = true once = true
} })
vim.cmd "set filetype=txt" vim.cmd "set filetype=txt"
vim.cmd "set filetype=python" vim.cmd "set filetype=python"
@ -45,11 +43,10 @@ describe('autocmd api', function()
it('allows passing buffer by key', function() it('allows passing buffer by key', function()
meths.set_var('called', 0) meths.set_var('called', 0)
meths.create_autocmd { meths.create_autocmd("FileType", {
event = "Filetype",
command = "let g:called = g:called + 1", command = "let g:called = g:called + 1",
buffer = 0, buffer = 0,
} })
meths.command "set filetype=txt" meths.command "set filetype=txt"
eq(1, meths.get_var('called')) eq(1, meths.get_var('called'))
@ -62,8 +59,7 @@ describe('autocmd api', function()
end) end)
it('does not allow passing buffer and patterns', function() it('does not allow passing buffer and patterns', function()
local ok = pcall(meths.create_autocmd, { local ok = pcall(meths.create_autocmd, "Filetype", {
event = "Filetype",
command = "let g:called = g:called + 1", command = "let g:called = g:called + 1",
buffer = 0, buffer = 0,
pattern = "*.py", pattern = "*.py",
@ -73,8 +69,7 @@ describe('autocmd api', function()
end) end)
it('does not allow passing invalid buffers', function() it('does not allow passing invalid buffers', function()
local ok, msg = pcall(meths.create_autocmd, { local ok, msg = pcall(meths.create_autocmd, "Filetype", {
event = "Filetype",
command = "let g:called = g:called + 1", command = "let g:called = g:called + 1",
buffer = -1, buffer = -1,
}) })
@ -85,17 +80,15 @@ describe('autocmd api', function()
it('errors on non-functions for cb', function() it('errors on non-functions for cb', function()
eq(false, pcall(exec_lua, [[ eq(false, pcall(exec_lua, [[
vim.api.nvim_create_autocmd { vim.api.nvim_create_autocmd("BufReadPost", {
event = "BufReadPost",
pattern = "*.py,*.pyi", pattern = "*.py,*.pyi",
callback = 5, callback = 5,
} })
]])) ]]))
end) end)
it('allow passing pattern and <buffer> in same pattern', function() it('allow passing pattern and <buffer> in same pattern', function()
local ok = pcall(meths.create_autocmd, { local ok = pcall(meths.create_autocmd, "BufReadPost", {
event = "BufReadPost",
pattern = "*.py,<buffer>", pattern = "*.py,<buffer>",
command = "echo 'Should Not Error'" command = "echo 'Should Not Error'"
}) })
@ -104,22 +97,20 @@ describe('autocmd api', function()
end) end)
it('should handle multiple values as comma separated list', function() it('should handle multiple values as comma separated list', function()
meths.create_autocmd { meths.create_autocmd("BufReadPost", {
event = "BufReadPost",
pattern = "*.py,*.pyi", pattern = "*.py,*.pyi",
command = "echo 'Should Not Have Errored'" command = "echo 'Should Not Have Errored'"
} })
-- We should have one autocmd for *.py and one for *.pyi -- We should have one autocmd for *.py and one for *.pyi
eq(2, #meths.get_autocmds { event = "BufReadPost" }) eq(2, #meths.get_autocmds { event = "BufReadPost" })
end) end)
it('should handle multiple values as array', function() it('should handle multiple values as array', function()
meths.create_autocmd { meths.create_autocmd("BufReadPost", {
event = "BufReadPost",
pattern = { "*.py", "*.pyi", }, pattern = { "*.py", "*.pyi", },
command = "echo 'Should Not Have Errored'" command = "echo 'Should Not Have Errored'"
} })
-- We should have one autocmd for *.py and one for *.pyi -- We should have one autocmd for *.py and one for *.pyi
eq(2, #meths.get_autocmds { event = "BufReadPost" }) eq(2, #meths.get_autocmds { event = "BufReadPost" })
@ -127,23 +118,21 @@ describe('autocmd api', function()
describe('desc', function() describe('desc', function()
it('can add description to one autocmd', function() it('can add description to one autocmd', function()
meths.create_autocmd { meths.create_autocmd("BufReadPost", {
event = "BufReadPost",
pattern = "*.py", pattern = "*.py",
command = "echo 'Should Not Have Errored'", command = "echo 'Should Not Have Errored'",
desc = "Can show description", desc = "Can show description",
} })
eq("Can show description", meths.get_autocmds { event = "BufReadPost" }[1].desc) eq("Can show description", meths.get_autocmds { event = "BufReadPost" }[1].desc)
end) end)
it('can add description to multiple autocmd', function() it('can add description to multiple autocmd', function()
meths.create_autocmd { meths.create_autocmd("BufReadPost", {
event = "BufReadPost",
pattern = {"*.py", "*.pyi"}, pattern = {"*.py", "*.pyi"},
command = "echo 'Should Not Have Errored'", command = "echo 'Should Not Have Errored'",
desc = "Can show description", desc = "Can show description",
} })
local aus = meths.get_autocmds { event = "BufReadPost" } local aus = meths.get_autocmds { event = "BufReadPost" }
eq(2, #aus) eq(2, #aus)
@ -154,12 +143,11 @@ describe('autocmd api', function()
pending('script and verbose settings', function() pending('script and verbose settings', function()
it('marks API client', function() it('marks API client', function()
meths.create_autocmd { meths.create_autocmd("BufReadPost", {
event = "BufReadPost",
pattern = "*.py", pattern = "*.py",
command = "echo 'Should Not Have Errored'", command = "echo 'Should Not Have Errored'",
desc = "Can show description", desc = "Can show description",
} })
local aus = meths.get_autocmds { event = "BufReadPost" } local aus = meths.get_autocmds { event = "BufReadPost" }
eq(1, #aus, aus) eq(1, #aus, aus)
@ -211,8 +199,7 @@ describe('autocmd api', function()
command [[au! InsertLeave]] command [[au! InsertLeave]]
command [[au InsertEnter * :echo "1"]] command [[au InsertEnter * :echo "1"]]
source [[ source [[
call nvim_create_autocmd(#{ call nvim_create_autocmd("InsertLeave", #{
\ event: "InsertLeave",
\ command: ":echo 2", \ command: ":echo 2",
\ }) \ })
]] ]]
@ -283,12 +270,11 @@ describe('autocmd api', function()
it('raises error for undefined augroup', function() it('raises error for undefined augroup', function()
local success, code = unpack(meths.exec_lua([[ local success, code = unpack(meths.exec_lua([[
return {pcall(function() return {pcall(function()
vim.api.nvim_create_autocmd { vim.api.nvim_create_autocmd("FileType", {
event = "FileType",
pattern = "*", pattern = "*",
group = "NotDefined", group = "NotDefined",
command = "echo 'hello'", command = "echo 'hello'",
} })
end)} end)}
]], {})) ]], {}))
@ -358,14 +344,13 @@ describe('autocmd api', function()
it("can trigger builtin autocmds", function() it("can trigger builtin autocmds", function()
meths.set_var("autocmd_executed", false) meths.set_var("autocmd_executed", false)
meths.create_autocmd { meths.create_autocmd("BufReadPost", {
event = "BufReadPost",
pattern = "*", pattern = "*",
command = "let g:autocmd_executed = v:true", command = "let g:autocmd_executed = v:true",
} })
eq(false, meths.get_var("autocmd_executed")) eq(false, meths.get_var("autocmd_executed"))
meths.do_autocmd { event = "BufReadPost" } meths.do_autocmd("BufReadPost", {})
eq(true, meths.get_var("autocmd_executed")) eq(true, meths.get_var("autocmd_executed"))
end) end)
@ -373,17 +358,16 @@ describe('autocmd api', function()
meths.set_var("buffer_executed", -1) meths.set_var("buffer_executed", -1)
eq(-1, meths.get_var("buffer_executed")) eq(-1, meths.get_var("buffer_executed"))
meths.create_autocmd { meths.create_autocmd("BufLeave", {
event = "BufLeave",
pattern = "*", pattern = "*",
command = 'let g:buffer_executed = +expand("<abuf>")', command = 'let g:buffer_executed = +expand("<abuf>")',
} })
-- Doesn't execute for other non-matching events -- Doesn't execute for other non-matching events
meths.do_autocmd { event = "CursorHold", buffer = 1 } meths.do_autocmd("CursorHold", { buffer = 1 })
eq(-1, meths.get_var("buffer_executed")) eq(-1, meths.get_var("buffer_executed"))
meths.do_autocmd { event = "BufLeave", buffer = 1 } meths.do_autocmd("BufLeave", { buffer = 1 })
eq(1, meths.get_var("buffer_executed")) eq(1, meths.get_var("buffer_executed"))
end) end)
@ -391,14 +375,13 @@ describe('autocmd api', function()
meths.set_var("filename_executed", 'none') meths.set_var("filename_executed", 'none')
eq('none', meths.get_var("filename_executed")) eq('none', meths.get_var("filename_executed"))
meths.create_autocmd { meths.create_autocmd("BufEnter", {
event = "BufEnter",
pattern = "*.py", pattern = "*.py",
command = 'let g:filename_executed = expand("<afile>")', command = 'let g:filename_executed = expand("<afile>")',
} })
-- Doesn't execute for other non-matching events -- Doesn't execute for other non-matching events
meths.do_autocmd { event = "CursorHold", buffer = 1 } meths.do_autocmd("CursorHold", { buffer = 1 })
eq('none', meths.get_var("filename_executed")) eq('none', meths.get_var("filename_executed"))
meths.command('edit __init__.py') meths.command('edit __init__.py')
@ -406,7 +389,7 @@ describe('autocmd api', function()
end) end)
it('cannot pass buf and fname', function() it('cannot pass buf and fname', function()
local ok = pcall(meths.do_autocmd, { pattern = "literally_cannot_error.rs", buffer = 1 }) local ok = pcall(meths.do_autocmd, "BufReadPre", { pattern = "literally_cannot_error.rs", buffer = 1 })
eq(false, ok) eq(false, ok)
end) end)
@ -418,38 +401,36 @@ describe('autocmd api', function()
meths.command('edit __init__.py') meths.command('edit __init__.py')
eq('none', meths.get_var("filename_executed")) eq('none', meths.get_var("filename_executed"))
meths.create_autocmd { meths.create_autocmd("CursorHoldI", {
event = "CursorHoldI",
pattern = "__init__.py", pattern = "__init__.py",
command = 'let g:filename_executed = expand("<afile>")', command = 'let g:filename_executed = expand("<afile>")',
} })
-- Doesn't execute for other non-matching events -- Doesn't execute for other non-matching events
meths.do_autocmd { event = "CursorHoldI", buffer = 1 } meths.do_autocmd("CursorHoldI", { buffer = 1 })
eq('none', meths.get_var("filename_executed")) eq('none', meths.get_var("filename_executed"))
meths.do_autocmd { event = "CursorHoldI", buffer = tonumber(meths.get_current_buf()) } meths.do_autocmd("CursorHoldI", { buffer = tonumber(meths.get_current_buf()) })
eq('__init__.py', meths.get_var("filename_executed")) eq('__init__.py', meths.get_var("filename_executed"))
-- Reset filename -- Reset filename
meths.set_var("filename_executed", 'none') meths.set_var("filename_executed", 'none')
meths.do_autocmd { event = "CursorHoldI", pattern = '__init__.py' } meths.do_autocmd("CursorHoldI", { pattern = '__init__.py' })
eq('__init__.py', meths.get_var("filename_executed")) eq('__init__.py', meths.get_var("filename_executed"))
end) end)
it("works with user autocmds", function() it("works with user autocmds", function()
meths.set_var("matched", 'none') meths.set_var("matched", 'none')
meths.create_autocmd { meths.create_autocmd("User", {
event = "User",
pattern = "TestCommand", pattern = "TestCommand",
command = 'let g:matched = "matched"' command = 'let g:matched = "matched"'
} })
meths.do_autocmd { event = "User", pattern = "OtherCommand" } meths.do_autocmd("User", { pattern = "OtherCommand" })
eq('none', meths.get_var('matched')) eq('none', meths.get_var('matched'))
meths.do_autocmd { event = "User", pattern = "TestCommand" } meths.do_autocmd("User", { pattern = "TestCommand" })
eq('matched', meths.get_var('matched')) eq('matched', meths.get_var('matched'))
end) end)
end) end)
@ -465,7 +446,6 @@ describe('autocmd api', function()
opts = opts or {} opts = opts or {}
local resulting = { local resulting = {
event = "FileType",
pattern = "*", pattern = "*",
command = "let g:executed = g:executed + 1", command = "let g:executed = g:executed + 1",
} }
@ -473,7 +453,7 @@ describe('autocmd api', function()
resulting.group = opts.group resulting.group = opts.group
resulting.once = opts.once resulting.once = opts.once
meths.create_autocmd(resulting) meths.create_autocmd("FileType", resulting)
end end
local set_ft = function(ft) local set_ft = function(ft)
@ -487,7 +467,7 @@ describe('autocmd api', function()
it('can be added in a group', function() it('can be added in a group', function()
local augroup = "TestGroup" local augroup = "TestGroup"
meths.create_augroup({ name = augroup, clear = true }) meths.create_augroup(augroup, { clear = true })
make_counting_autocmd { group = augroup } make_counting_autocmd { group = augroup }
set_ft("txt") set_ft("txt")
@ -516,8 +496,7 @@ describe('autocmd api', function()
end) end)
it('errors on unexpected keys', function() it('errors on unexpected keys', function()
local success, code = pcall(meths.create_autocmd, { local success, code = pcall(meths.create_autocmd, "FileType", {
event = "FileType",
pattern = "*", pattern = "*",
not_a_valid_key = "NotDefined", not_a_valid_key = "NotDefined",
}) })
@ -530,11 +509,10 @@ describe('autocmd api', function()
exec_lua([[ exec_lua([[
vim.g.executed = false vim.g.executed = false
vim.api.nvim_create_autocmd { vim.api.nvim_create_autocmd("FileType", {
event = "FileType",
pattern = "*", pattern = "*",
callback = function() vim.g.executed = true end, callback = function() vim.g.executed = true end,
} })
]], {}) ]], {})
@ -551,17 +529,15 @@ describe('autocmd api', function()
count = count + 1 count = count + 1
end end
vim.api.nvim_create_autocmd { vim.api.nvim_create_autocmd("FileType", {
event = "FileType",
pattern = "*", pattern = "*",
callback = counter, callback = counter,
} })
vim.api.nvim_create_autocmd { vim.api.nvim_create_autocmd("FileType", {
event = "FileType",
pattern = "*", pattern = "*",
callback = counter, callback = counter,
} })
vim.cmd "set filetype=txt" vim.cmd "set filetype=txt"
vim.cmd "set filetype=txt" vim.cmd "set filetype=txt"
@ -579,15 +555,14 @@ describe('autocmd api', function()
MyVal = {} MyVal = {}
WeakTable[MyVal] = true WeakTable[MyVal] = true
vim.api.nvim_create_autocmd { vim.api.nvim_create_autocmd("FileType", {
event = "FileType",
pattern = "*", pattern = "*",
callback = function() callback = function()
OnceCount = OnceCount + 1 OnceCount = OnceCount + 1
MyVal = {} MyVal = {}
end, end,
once = true once = true
} })
]]) ]])
command [[set filetype=txt]] command [[set filetype=txt]]
@ -610,10 +585,9 @@ describe('autocmd api', function()
it('groups can be cleared', function() it('groups can be cleared', function()
local augroup = "TestGroup" local augroup = "TestGroup"
meths.create_augroup({ name = augroup, clear = true }) meths.create_augroup(augroup, { clear = true })
meths.create_autocmd({ meths.create_autocmd("FileType", {
group = augroup, group = augroup,
event = "FileType",
command = "let g:executed = g:executed + 1" command = "let g:executed = g:executed + 1"
}) })
@ -621,7 +595,7 @@ describe('autocmd api', function()
set_ft("txt") set_ft("txt")
eq(2, get_executed_count(), "should only count twice") eq(2, get_executed_count(), "should only count twice")
meths.create_augroup({ name = augroup, clear = true }) meths.create_augroup(augroup, { clear = true })
eq({}, meths.get_autocmds { group = augroup }) eq({}, meths.get_autocmds { group = augroup })
set_ft("txt") set_ft("txt")
@ -632,7 +606,7 @@ describe('autocmd api', function()
it('groups work with once', function() it('groups work with once', function()
local augroup = "TestGroup" local augroup = "TestGroup"
meths.create_augroup({ name = augroup, clear = true }) meths.create_augroup(augroup, { clear = true })
make_counting_autocmd { group = augroup, once = true } make_counting_autocmd { group = augroup, once = true }
set_ft("txt") set_ft("txt")
@ -644,7 +618,7 @@ describe('autocmd api', function()
it('autocmds can be registered multiple times.', function() it('autocmds can be registered multiple times.', function()
local augroup = "TestGroup" local augroup = "TestGroup"
meths.create_augroup({ name = augroup, clear = true }) meths.create_augroup(augroup, { clear = true })
make_counting_autocmd { group = augroup, once = false } make_counting_autocmd { group = augroup, once = false }
make_counting_autocmd { group = augroup, once = false } make_counting_autocmd { group = augroup, once = false }
make_counting_autocmd { group = augroup, once = false } make_counting_autocmd { group = augroup, once = false }
@ -658,15 +632,14 @@ describe('autocmd api', function()
it('can be deleted', function() it('can be deleted', function()
local augroup = "WillBeDeleted" local augroup = "WillBeDeleted"
meths.create_augroup({ name = augroup, clear = true }) meths.create_augroup(augroup, { clear = true })
meths.create_autocmd { meths.create_autocmd({"Filetype"}, {
event = {"Filetype"},
pattern = "*", pattern = "*",
command = "echo 'does not matter'", command = "echo 'does not matter'",
} })
-- Clears the augroup from before, which erases the autocmd -- Clears the augroup from before, which erases the autocmd
meths.create_augroup({ name = augroup, clear = true }) meths.create_augroup(augroup, { clear = true })
local result = #meths.get_autocmds { group = augroup } local result = #meths.get_autocmds { group = augroup }
@ -678,12 +651,11 @@ describe('autocmd api', function()
meths.set_var("value_set", false) meths.set_var("value_set", false)
meths.create_augroup({ name = augroup, clear = true }) meths.create_augroup(augroup, { clear = true })
meths.create_autocmd { meths.create_autocmd("Filetype", {
event = "Filetype",
pattern = "<buffer>", pattern = "<buffer>",
command = "let g:value_set = v:true", command = "let g:value_set = v:true",
} })
command "new" command "new"
command "set filetype=python" command "set filetype=python"
@ -699,8 +671,7 @@ describe('autocmd api', function()
let g:vimscript_executed = g:vimscript_executed + 1 let g:vimscript_executed = g:vimscript_executed + 1
endfunction endfunction
call nvim_create_autocmd(#{ call nvim_create_autocmd("FileType", #{
\ event: "Filetype",
\ pattern: ["python", "javascript"], \ pattern: ["python", "javascript"],
\ callback: "MyVimscriptFunction", \ callback: "MyVimscriptFunction",
\ }) \ })
@ -773,7 +744,7 @@ describe('autocmd api', function()
command('autocmd! BufReadPost *.py :echo "Hello"') command('autocmd! BufReadPost *.py :echo "Hello"')
command('augroup END') command('augroup END')
local augroup_id = meths.create_augroup { name = "TEMP_ABCD", clear = false } local augroup_id = meths.create_augroup("TEMP_ABCD", { clear = false })
meths.del_augroup_by_id(augroup_id) meths.del_augroup_by_id(augroup_id)
-- For good reason, we kill all the autocmds from del_augroup, -- For good reason, we kill all the autocmds from del_augroup,