mirror of
https://github.com/neovim/neovim.git
synced 2025-09-23 03:28:33 +00:00
feat(api): add 'buffer' argument to nvim_get_autocmds (#17594)
This enables retrieving autocommands defined in the given buffers. Under the hood this simply translates the buffer numbers into '<buffer=%d>' patterns.
This commit is contained in:
@@ -3226,7 +3226,11 @@ nvim_get_autocmds({*opts}) *nvim_get_autocmds()*
|
|||||||
against
|
against
|
||||||
• group (string): Name of group to match against
|
• group (string): Name of group to match against
|
||||||
• pattern: Pattern or list of patterns to match
|
• pattern: Pattern or list of patterns to match
|
||||||
against
|
against. Cannot be used with {buffer}
|
||||||
|
• buffer: Buffer number or list of buffer numbers
|
||||||
|
for buffer local autocommands
|
||||||
|
|autocmd-buflocal|. Cannot be used with
|
||||||
|
{pattern}
|
||||||
|
|
||||||
Return: ~
|
Return: ~
|
||||||
A list of autocmds that match
|
A list of autocmds that match
|
||||||
|
@@ -41,7 +41,9 @@ static int64_t next_autocmd_id = 1;
|
|||||||
/// @param opts Optional Parameters:
|
/// @param opts Optional Parameters:
|
||||||
/// - event : Name or list of name of events to match against
|
/// - event : Name or list of name of events to match against
|
||||||
/// - group (string): Name of group to match against
|
/// - group (string): Name of group to match against
|
||||||
/// - pattern: Pattern or list of patterns to match against
|
/// - pattern: Pattern or list of patterns to match against. Cannot be used with {buffer}
|
||||||
|
/// - buffer: Buffer number or list of buffer numbers for buffer local autocommands
|
||||||
|
/// |autocmd-buflocal|. Cannot be used with {pattern}
|
||||||
///
|
///
|
||||||
/// @return A list of autocmds that match
|
/// @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)
|
||||||
@@ -53,6 +55,8 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
|
|||||||
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];
|
||||||
|
|
||||||
|
Array buffers = ARRAY_DICT_INIT;
|
||||||
|
|
||||||
bool event_set[NUM_EVENTS] = { false };
|
bool event_set[NUM_EVENTS] = { false };
|
||||||
bool check_event = false;
|
bool check_event = false;
|
||||||
|
|
||||||
@@ -100,6 +104,12 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opts->pattern.type != kObjectTypeNil && opts->buffer.type != kObjectTypeNil) {
|
||||||
|
api_set_error(err, kErrorTypeValidation,
|
||||||
|
"Cannot use both 'pattern' and 'buffer'");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
int pattern_filter_count = 0;
|
int pattern_filter_count = 0;
|
||||||
if (opts->pattern.type != kObjectTypeNil) {
|
if (opts->pattern.type != kObjectTypeNil) {
|
||||||
Object v = opts->pattern;
|
Object v = opts->pattern;
|
||||||
@@ -107,25 +117,70 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
|
|||||||
pattern_filters[pattern_filter_count] = (char_u *)v.data.string.data;
|
pattern_filters[pattern_filter_count] = (char_u *)v.data.string.data;
|
||||||
pattern_filter_count += 1;
|
pattern_filter_count += 1;
|
||||||
} else if (v.type == kObjectTypeArray) {
|
} else if (v.type == kObjectTypeArray) {
|
||||||
|
if (v.data.array.size > AUCMD_MAX_PATTERNS) {
|
||||||
|
api_set_error(err, kErrorTypeValidation,
|
||||||
|
"Too many patterns. Please limit yourself to %d or fewer",
|
||||||
|
AUCMD_MAX_PATTERNS);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
FOREACH_ITEM(v.data.array, item, {
|
FOREACH_ITEM(v.data.array, item, {
|
||||||
|
if (item.type != kObjectTypeString) {
|
||||||
|
api_set_error(err, kErrorTypeValidation, "Invalid value for 'pattern': must be a string");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
pattern_filters[pattern_filter_count] = (char_u *)item.data.string.data;
|
pattern_filters[pattern_filter_count] = (char_u *)item.data.string.data;
|
||||||
pattern_filter_count += 1;
|
pattern_filter_count += 1;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
api_set_error(err,
|
api_set_error(err, kErrorTypeValidation,
|
||||||
kErrorTypeValidation,
|
|
||||||
"Not a valid 'pattern' value. Must be a string or an array");
|
"Not a valid 'pattern' value. Must be a string or an array");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (pattern_filter_count >= AUCMD_MAX_PATTERNS) {
|
if (opts->buffer.type == kObjectTypeInteger || opts->buffer.type == kObjectTypeBuffer) {
|
||||||
api_set_error(err,
|
buf_T *buf = find_buffer_by_handle((Buffer)opts->buffer.data.integer, err);
|
||||||
kErrorTypeValidation,
|
if (ERROR_SET(err)) {
|
||||||
"Too many patterns. Please limit yourself to less");
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snprintf((char *)pattern_buflocal, BUFLOCAL_PAT_LEN, "<buffer=%d>", (int)buf->handle);
|
||||||
|
ADD(buffers, CSTR_TO_OBJ((char *)pattern_buflocal));
|
||||||
|
} else if (opts->buffer.type == kObjectTypeArray) {
|
||||||
|
if (opts->buffer.data.array.size > AUCMD_MAX_PATTERNS) {
|
||||||
|
api_set_error(err,
|
||||||
|
kErrorTypeValidation,
|
||||||
|
"Too many buffers. Please limit yourself to %d or fewer", AUCMD_MAX_PATTERNS);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
FOREACH_ITEM(opts->buffer.data.array, bufnr, {
|
||||||
|
if (bufnr.type != kObjectTypeInteger && bufnr.type != kObjectTypeBuffer) {
|
||||||
|
api_set_error(err, kErrorTypeValidation, "Invalid value for 'buffer': must be an integer");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf_T *buf = find_buffer_by_handle((Buffer)bufnr.data.integer, err);
|
||||||
|
if (ERROR_SET(err)) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf((char *)pattern_buflocal, BUFLOCAL_PAT_LEN, "<buffer=%d>", (int)buf->handle);
|
||||||
|
ADD(buffers, CSTR_TO_OBJ((char *)pattern_buflocal));
|
||||||
|
});
|
||||||
|
} else if (opts->buffer.type != kObjectTypeNil) {
|
||||||
|
api_set_error(err, kErrorTypeValidation,
|
||||||
|
"Invalid value for 'buffer': must be an integer or array of integers");
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FOREACH_ITEM(buffers, bufnr, {
|
||||||
|
pattern_filters[pattern_filter_count] = (char_u *)bufnr.data.string.data;
|
||||||
|
pattern_filter_count += 1;
|
||||||
|
});
|
||||||
|
|
||||||
FOR_ALL_AUEVENTS(event) {
|
FOR_ALL_AUEVENTS(event) {
|
||||||
if (check_event && !event_set[event]) {
|
if (check_event && !event_set[event]) {
|
||||||
continue;
|
continue;
|
||||||
@@ -234,6 +289,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
api_free_array(buffers);
|
||||||
return autocmd_list;
|
return autocmd_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -142,6 +142,7 @@ return {
|
|||||||
"event";
|
"event";
|
||||||
"group";
|
"group";
|
||||||
"pattern";
|
"pattern";
|
||||||
|
"buffer";
|
||||||
};
|
};
|
||||||
create_augroup = {
|
create_augroup = {
|
||||||
"clear";
|
"clear";
|
||||||
|
@@ -8,6 +8,7 @@ local exec_lua = helpers.exec_lua
|
|||||||
local matches = helpers.matches
|
local matches = helpers.matches
|
||||||
local meths = helpers.meths
|
local meths = helpers.meths
|
||||||
local source = helpers.source
|
local source = helpers.source
|
||||||
|
local pcall_err = helpers.pcall_err
|
||||||
|
|
||||||
before_each(clear)
|
before_each(clear)
|
||||||
|
|
||||||
@@ -225,6 +226,61 @@ describe('autocmd api', function()
|
|||||||
local aus = meths.get_autocmds { event = "InsertEnter" }
|
local aus = meths.get_autocmds { event = "InsertEnter" }
|
||||||
eq({ { buflocal = false, command = ':echo "1"', event = "InsertEnter", once = false, pattern = "*" } }, aus)
|
eq({ { buflocal = false, command = ':echo "1"', event = "InsertEnter", once = false, pattern = "*" } }, aus)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('should work with buffer numbers', function()
|
||||||
|
command [[new]]
|
||||||
|
command [[au! InsertEnter]]
|
||||||
|
command [[au InsertEnter <buffer=1> :echo "1"]]
|
||||||
|
command [[au InsertEnter <buffer=2> :echo "2"]]
|
||||||
|
|
||||||
|
local aus = meths.get_autocmds { event = "InsertEnter", buffer = 0 }
|
||||||
|
eq({{
|
||||||
|
buffer = 2,
|
||||||
|
buflocal = true,
|
||||||
|
command = ':echo "2"',
|
||||||
|
event = 'InsertEnter',
|
||||||
|
once = false,
|
||||||
|
pattern = '<buffer=2>',
|
||||||
|
}}, aus)
|
||||||
|
|
||||||
|
aus = meths.get_autocmds { event = "InsertEnter", buffer = 1 }
|
||||||
|
eq({{
|
||||||
|
buffer = 1,
|
||||||
|
buflocal = true,
|
||||||
|
command = ':echo "1"',
|
||||||
|
event = "InsertEnter",
|
||||||
|
once = false,
|
||||||
|
pattern = "<buffer=1>",
|
||||||
|
}}, aus)
|
||||||
|
|
||||||
|
aus = meths.get_autocmds { event = "InsertEnter", buffer = { 1, 2 } }
|
||||||
|
eq({{
|
||||||
|
buffer = 1,
|
||||||
|
buflocal = true,
|
||||||
|
command = ':echo "1"',
|
||||||
|
event = "InsertEnter",
|
||||||
|
once = false,
|
||||||
|
pattern = "<buffer=1>",
|
||||||
|
}, {
|
||||||
|
buffer = 2,
|
||||||
|
buflocal = true,
|
||||||
|
command = ':echo "2"',
|
||||||
|
event = "InsertEnter",
|
||||||
|
once = false,
|
||||||
|
pattern = "<buffer=2>",
|
||||||
|
}}, aus)
|
||||||
|
|
||||||
|
eq("Invalid value for 'buffer': must be an integer or array of integers", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = "foo" }))
|
||||||
|
eq("Invalid value for 'buffer': must be an integer", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = { "foo", 42 } }))
|
||||||
|
eq("Invalid buffer id: 42", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = { 42 } }))
|
||||||
|
|
||||||
|
local bufs = {}
|
||||||
|
for _ = 1, 257 do
|
||||||
|
table.insert(bufs, meths.create_buf(true, false))
|
||||||
|
end
|
||||||
|
|
||||||
|
eq("Too many buffers. Please limit yourself to 256 or fewer", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = bufs }))
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('groups', function()
|
describe('groups', function()
|
||||||
|
Reference in New Issue
Block a user