mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
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:
parent
6732cd9e57
commit
0f613482b3
@ -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*
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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";
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user