mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
refactor(api): use arena for autocmds
This commit is contained in:
parent
146333ca12
commit
97531be1f7
@ -23,6 +23,7 @@
|
||||
#include "nvim/globals.h"
|
||||
#include "nvim/lua/executor.h"
|
||||
#include "nvim/memory.h"
|
||||
#include "nvim/strings.h"
|
||||
#include "nvim/types_defs.h"
|
||||
#include "nvim/vim_defs.h"
|
||||
|
||||
@ -33,12 +34,12 @@
|
||||
#define AUCMD_MAX_PATTERNS 256
|
||||
|
||||
// Copy string or array of strings into an empty array.
|
||||
// Get the event number, unless it is an error. Then goto `goto_name`.
|
||||
#define GET_ONE_EVENT(event_nr, event_str, goto_name) \
|
||||
// Get the event number, unless it is an error. Then do `or_else`.
|
||||
#define GET_ONE_EVENT(event_nr, event_str, or_else) \
|
||||
event_T event_nr = \
|
||||
event_name2nr_str(event_str.data.string); \
|
||||
VALIDATE_S((event_nr < NUM_EVENTS), "event", event_str.data.string.data, { \
|
||||
goto goto_name; \
|
||||
or_else; \
|
||||
});
|
||||
|
||||
// ID for associating autocmds created via nvim_create_autocmd
|
||||
@ -88,14 +89,14 @@ static int64_t next_autocmd_id = 1;
|
||||
/// If the autocommand is buffer local |autocmd-buffer-local|:
|
||||
/// - buflocal (boolean): true if the autocommand is buffer local.
|
||||
/// - buffer (number): the buffer number.
|
||||
Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
|
||||
Array nvim_get_autocmds(Dict(get_autocmds) *opts, Arena *arena, Error *err)
|
||||
FUNC_API_SINCE(9)
|
||||
{
|
||||
// TODO(tjdevries): Would be cool to add nvim_get_autocmds({ id = ... })
|
||||
|
||||
Array autocmd_list = ARRAY_DICT_INIT;
|
||||
ArrayBuilder autocmd_list = KV_INITIAL_VALUE;
|
||||
kvi_init(autocmd_list);
|
||||
char *pattern_filters[AUCMD_MAX_PATTERNS];
|
||||
char pattern_buflocal[BUFLOCAL_PAT_LEN];
|
||||
|
||||
Array buffers = ARRAY_DICT_INIT;
|
||||
|
||||
@ -131,7 +132,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
|
||||
|
||||
Object v = opts->event;
|
||||
if (v.type == kObjectTypeString) {
|
||||
GET_ONE_EVENT(event_nr, v, cleanup);
|
||||
GET_ONE_EVENT(event_nr, v, goto cleanup);
|
||||
event_set[event_nr] = true;
|
||||
} else if (v.type == kObjectTypeArray) {
|
||||
FOREACH_ITEM(v.data.array, event_v, {
|
||||
@ -139,7 +140,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
|
||||
goto cleanup;
|
||||
});
|
||||
|
||||
GET_ONE_EVENT(event_nr, event_v, cleanup);
|
||||
GET_ONE_EVENT(event_nr, event_v, goto cleanup);
|
||||
event_set[event_nr] = true;
|
||||
})
|
||||
} else {
|
||||
@ -187,8 +188,9 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
snprintf(pattern_buflocal, BUFLOCAL_PAT_LEN, "<buffer=%d>", (int)buf->handle);
|
||||
ADD(buffers, CSTR_TO_OBJ(pattern_buflocal));
|
||||
String pat = arena_printf(arena, "<buffer=%d>", (int)buf->handle);
|
||||
buffers = arena_array(arena, 1);
|
||||
ADD_C(buffers, STRING_OBJ(pat));
|
||||
} else if (opts->buffer.type == kObjectTypeArray) {
|
||||
if (opts->buffer.data.array.size > AUCMD_MAX_PATTERNS) {
|
||||
api_set_error(err, kErrorTypeValidation, "Too many buffers (maximum of %d)",
|
||||
@ -196,6 +198,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
buffers = arena_array(arena, kv_size(opts->buffer.data.array));
|
||||
FOREACH_ITEM(opts->buffer.data.array, bufnr, {
|
||||
VALIDATE_EXP((bufnr.type == kObjectTypeInteger || bufnr.type == kObjectTypeBuffer),
|
||||
"buffer", "Integer", api_typename(bufnr.type), {
|
||||
@ -207,8 +210,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
snprintf(pattern_buflocal, BUFLOCAL_PAT_LEN, "<buffer=%d>", (int)buf->handle);
|
||||
ADD(buffers, CSTR_TO_OBJ(pattern_buflocal));
|
||||
ADD_C(buffers, STRING_OBJ(arena_printf(arena, "<buffer=%d>", (int)buf->handle)));
|
||||
});
|
||||
} else if (HAS_KEY(opts, get_autocmds, buffer)) {
|
||||
VALIDATE_EXP(false, "buffer", "Integer or Array", api_typename(opts->buffer.type), {
|
||||
@ -250,6 +252,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
|
||||
char *pat = pattern_filters[j];
|
||||
int patlen = (int)strlen(pat);
|
||||
|
||||
char pattern_buflocal[BUFLOCAL_PAT_LEN];
|
||||
if (aupat_is_buflocal(pat, patlen)) {
|
||||
aupat_normalize_buflocal_pat(pattern_buflocal, pat, patlen,
|
||||
aupat_get_buflocal_nr(pat, patlen));
|
||||
@ -267,51 +270,51 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary autocmd_info = ARRAY_DICT_INIT;
|
||||
Dictionary autocmd_info = arena_dict(arena, 11);
|
||||
|
||||
if (ap->group != AUGROUP_DEFAULT) {
|
||||
PUT(autocmd_info, "group", INTEGER_OBJ(ap->group));
|
||||
PUT(autocmd_info, "group_name", CSTR_TO_OBJ(augroup_name(ap->group)));
|
||||
PUT_C(autocmd_info, "group", INTEGER_OBJ(ap->group));
|
||||
PUT_C(autocmd_info, "group_name", CSTR_AS_OBJ(augroup_name(ap->group)));
|
||||
}
|
||||
|
||||
if (ac->id > 0) {
|
||||
PUT(autocmd_info, "id", INTEGER_OBJ(ac->id));
|
||||
PUT_C(autocmd_info, "id", INTEGER_OBJ(ac->id));
|
||||
}
|
||||
|
||||
if (ac->desc != NULL) {
|
||||
PUT(autocmd_info, "desc", CSTR_TO_OBJ(ac->desc));
|
||||
PUT_C(autocmd_info, "desc", CSTR_AS_OBJ(ac->desc));
|
||||
}
|
||||
|
||||
if (ac->exec.type == CALLABLE_CB) {
|
||||
PUT(autocmd_info, "command", STRING_OBJ(STRING_INIT));
|
||||
PUT_C(autocmd_info, "command", STRING_OBJ(STRING_INIT));
|
||||
|
||||
Callback *cb = &ac->exec.callable.cb;
|
||||
switch (cb->type) {
|
||||
case kCallbackLua:
|
||||
if (nlua_ref_is_function(cb->data.luaref)) {
|
||||
PUT(autocmd_info, "callback", LUAREF_OBJ(api_new_luaref(cb->data.luaref)));
|
||||
PUT_C(autocmd_info, "callback", LUAREF_OBJ(api_new_luaref(cb->data.luaref)));
|
||||
}
|
||||
break;
|
||||
case kCallbackFuncref:
|
||||
case kCallbackPartial:
|
||||
PUT(autocmd_info, "callback", CSTR_AS_OBJ(callback_to_string(cb, NULL)));
|
||||
PUT_C(autocmd_info, "callback", CSTR_AS_OBJ(callback_to_string(cb, arena)));
|
||||
break;
|
||||
case kCallbackNone:
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
PUT(autocmd_info, "command", CSTR_TO_OBJ(ac->exec.callable.cmd));
|
||||
PUT_C(autocmd_info, "command", CSTR_AS_OBJ(ac->exec.callable.cmd));
|
||||
}
|
||||
|
||||
PUT(autocmd_info, "pattern", CSTR_TO_OBJ(ap->pat));
|
||||
PUT(autocmd_info, "event", CSTR_TO_OBJ(event_nr2name(event)));
|
||||
PUT(autocmd_info, "once", BOOLEAN_OBJ(ac->once));
|
||||
PUT_C(autocmd_info, "pattern", CSTR_AS_OBJ(ap->pat));
|
||||
PUT_C(autocmd_info, "event", CSTR_AS_OBJ(event_nr2name(event)));
|
||||
PUT_C(autocmd_info, "once", BOOLEAN_OBJ(ac->once));
|
||||
|
||||
if (ap->buflocal_nr) {
|
||||
PUT(autocmd_info, "buflocal", BOOLEAN_OBJ(true));
|
||||
PUT(autocmd_info, "buffer", INTEGER_OBJ(ap->buflocal_nr));
|
||||
PUT_C(autocmd_info, "buflocal", BOOLEAN_OBJ(true));
|
||||
PUT_C(autocmd_info, "buffer", INTEGER_OBJ(ap->buflocal_nr));
|
||||
} else {
|
||||
PUT(autocmd_info, "buflocal", BOOLEAN_OBJ(false));
|
||||
PUT_C(autocmd_info, "buflocal", BOOLEAN_OBJ(false));
|
||||
}
|
||||
|
||||
// TODO(sctx): It would be good to unify script_ctx to actually work with lua
|
||||
@ -328,16 +331,15 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
|
||||
// Once we do that, we can put these into the autocmd_info, but I don't think it's
|
||||
// useful to do that at this time.
|
||||
//
|
||||
// PUT(autocmd_info, "sid", INTEGER_OBJ(ac->script_ctx.sc_sid));
|
||||
// PUT(autocmd_info, "lnum", INTEGER_OBJ(ac->script_ctx.sc_lnum));
|
||||
// PUT_C(autocmd_info, "sid", INTEGER_OBJ(ac->script_ctx.sc_sid));
|
||||
// PUT_C(autocmd_info, "lnum", INTEGER_OBJ(ac->script_ctx.sc_lnum));
|
||||
|
||||
ADD(autocmd_list, DICTIONARY_OBJ(autocmd_info));
|
||||
kvi_push(autocmd_list, DICTIONARY_OBJ(autocmd_info));
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
api_free_array(buffers);
|
||||
return autocmd_list;
|
||||
return arena_take_arraybuilder(arena, &autocmd_list);
|
||||
}
|
||||
|
||||
/// Creates an |autocommand| event handler, defined by `callback` (Lua function or Vimscript
|
||||
@ -399,17 +401,16 @@ cleanup:
|
||||
/// @see |autocommand|
|
||||
/// @see |nvim_del_autocmd()|
|
||||
Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autocmd) *opts,
|
||||
Error *err)
|
||||
Arena *arena, Error *err)
|
||||
FUNC_API_SINCE(9)
|
||||
{
|
||||
int64_t autocmd_id = -1;
|
||||
char *desc = NULL;
|
||||
Array patterns = ARRAY_DICT_INIT;
|
||||
Array event_array = ARRAY_DICT_INIT;
|
||||
AucmdExecutable aucmd = AUCMD_EXECUTABLE_INIT;
|
||||
Callback cb = CALLBACK_NONE;
|
||||
|
||||
if (!unpack_string_or_array(&event_array, &event, "event", true, err)) {
|
||||
Array event_array = unpack_string_or_array(event, "event", true, arena, err);
|
||||
if (ERROR_SET(err)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -469,7 +470,9 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
|
||||
goto cleanup;
|
||||
});
|
||||
|
||||
if (!get_patterns_from_pattern_or_buf(&patterns, opts->pattern, has_buffer, opts->buffer, err)) {
|
||||
Array patterns = get_patterns_from_pattern_or_buf(opts->pattern, has_buffer, opts->buffer, "*",
|
||||
arena, err);
|
||||
if (ERROR_SET(err)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -477,17 +480,13 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
|
||||
desc = opts->desc.data;
|
||||
}
|
||||
|
||||
if (patterns.size == 0) {
|
||||
ADD(patterns, STATIC_CSTR_TO_OBJ("*"));
|
||||
}
|
||||
|
||||
VALIDATE_R((event_array.size > 0), "event", {
|
||||
goto cleanup;
|
||||
});
|
||||
|
||||
autocmd_id = next_autocmd_id++;
|
||||
FOREACH_ITEM(event_array, event_str, {
|
||||
GET_ONE_EVENT(event_nr, event_str, cleanup);
|
||||
GET_ONE_EVENT(event_nr, event_str, goto cleanup);
|
||||
|
||||
int retval;
|
||||
|
||||
@ -514,8 +513,6 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
|
||||
|
||||
cleanup:
|
||||
aucmd_exec_free(&aucmd);
|
||||
api_free_array(event_array);
|
||||
api_free_array(patterns);
|
||||
|
||||
return autocmd_id;
|
||||
}
|
||||
@ -555,7 +552,7 @@ void nvim_del_autocmd(Integer id, Error *err)
|
||||
/// - group: (string|int) The augroup name or id.
|
||||
/// - NOTE: If not passed, will only delete autocmds *not* in any group.
|
||||
///
|
||||
void nvim_clear_autocmds(Dict(clear_autocmds) *opts, Error *err)
|
||||
void nvim_clear_autocmds(Dict(clear_autocmds) *opts, Arena *arena, Error *err)
|
||||
FUNC_API_SINCE(9)
|
||||
{
|
||||
// TODO(tjdevries): Future improvements:
|
||||
@ -564,33 +561,29 @@ void nvim_clear_autocmds(Dict(clear_autocmds) *opts, Error *err)
|
||||
// - group: Allow passing "*" or true or something like that to force doing all
|
||||
// autocmds, regardless of their group.
|
||||
|
||||
Array patterns = ARRAY_DICT_INIT;
|
||||
Array event_array = ARRAY_DICT_INIT;
|
||||
|
||||
if (!unpack_string_or_array(&event_array, &opts->event, "event", false, err)) {
|
||||
goto cleanup;
|
||||
Array event_array = unpack_string_or_array(opts->event, "event", false, arena, err);
|
||||
if (ERROR_SET(err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool has_buffer = HAS_KEY(opts, clear_autocmds, buffer);
|
||||
|
||||
VALIDATE((!HAS_KEY(opts, clear_autocmds, pattern) || !has_buffer),
|
||||
"%s", "Cannot use both 'pattern' and 'buffer'", {
|
||||
goto cleanup;
|
||||
return;
|
||||
});
|
||||
|
||||
int au_group = get_augroup_from_object(opts->group, err);
|
||||
if (au_group == AUGROUP_ERROR) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!get_patterns_from_pattern_or_buf(&patterns, opts->pattern, has_buffer, opts->buffer, err)) {
|
||||
goto cleanup;
|
||||
return;
|
||||
}
|
||||
|
||||
// When we create the autocmds, we want to say that they are all matched, so that's *
|
||||
// but when we clear them, we want to say that we didn't pass a pattern, so that's NUL
|
||||
if (patterns.size == 0) {
|
||||
ADD(patterns, STATIC_CSTR_TO_OBJ(""));
|
||||
Array patterns = get_patterns_from_pattern_or_buf(opts->pattern, has_buffer, opts->buffer, "",
|
||||
arena, err);
|
||||
if (ERROR_SET(err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we didn't pass any events, that means clear all events.
|
||||
@ -599,26 +592,22 @@ void nvim_clear_autocmds(Dict(clear_autocmds) *opts, Error *err)
|
||||
FOREACH_ITEM(patterns, pat_object, {
|
||||
char *pat = pat_object.data.string.data;
|
||||
if (!clear_autocmd(event, pat, au_group, err)) {
|
||||
goto cleanup;
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
FOREACH_ITEM(event_array, event_str, {
|
||||
GET_ONE_EVENT(event_nr, event_str, cleanup);
|
||||
GET_ONE_EVENT(event_nr, event_str, return );
|
||||
|
||||
FOREACH_ITEM(patterns, pat_object, {
|
||||
char *pat = pat_object.data.string.data;
|
||||
if (!clear_autocmd(event_nr, pat, au_group, err)) {
|
||||
goto cleanup;
|
||||
return;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
cleanup:
|
||||
api_free_array(event_array);
|
||||
api_free_array(patterns);
|
||||
}
|
||||
|
||||
/// Create or get an autocommand group |autocmd-groups|.
|
||||
@ -709,7 +698,7 @@ void nvim_del_augroup_by_name(String name, Error *err)
|
||||
/// - data (any): arbitrary data to send to the autocommand callback. See
|
||||
/// |nvim_create_autocmd()| for details.
|
||||
/// @see |:doautocmd|
|
||||
void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
|
||||
void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Arena *arena, Error *err)
|
||||
FUNC_API_SINCE(9)
|
||||
{
|
||||
int au_group = AUGROUP_ALL;
|
||||
@ -717,13 +706,11 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
|
||||
|
||||
buf_T *buf = curbuf;
|
||||
|
||||
Array patterns = ARRAY_DICT_INIT;
|
||||
Array event_array = ARRAY_DICT_INIT;
|
||||
|
||||
Object *data = NULL;
|
||||
|
||||
if (!unpack_string_or_array(&event_array, &event, "event", true, err)) {
|
||||
goto cleanup;
|
||||
Array event_array = unpack_string_or_array(event, "event", true, arena, err);
|
||||
if (ERROR_SET(err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (opts->group.type) {
|
||||
@ -732,19 +719,19 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
|
||||
case kObjectTypeString:
|
||||
au_group = augroup_find(opts->group.data.string.data);
|
||||
VALIDATE_S((au_group != AUGROUP_ERROR), "group", opts->group.data.string.data, {
|
||||
goto cleanup;
|
||||
return;
|
||||
});
|
||||
break;
|
||||
case kObjectTypeInteger:
|
||||
au_group = (int)opts->group.data.integer;
|
||||
char *name = au_group == 0 ? NULL : augroup_name(au_group);
|
||||
VALIDATE_INT(augroup_exists(name), "group", (int64_t)au_group, {
|
||||
goto cleanup;
|
||||
return;
|
||||
});
|
||||
break;
|
||||
default:
|
||||
VALIDATE_EXP(false, "group", "String or Integer", api_typename(opts->group.type), {
|
||||
goto cleanup;
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
@ -752,23 +739,21 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
|
||||
if (HAS_KEY(opts, exec_autocmds, buffer)) {
|
||||
VALIDATE((!HAS_KEY(opts, exec_autocmds, pattern)),
|
||||
"%s", "Cannot use both 'pattern' and 'buffer' for the same autocmd", {
|
||||
goto cleanup;
|
||||
return;
|
||||
});
|
||||
|
||||
has_buffer = true;
|
||||
buf = find_buffer_by_handle(opts->buffer, err);
|
||||
|
||||
if (ERROR_SET(err)) {
|
||||
goto cleanup;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!get_patterns_from_pattern_or_buf(&patterns, opts->pattern, has_buffer, opts->buffer, err)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (patterns.size == 0) {
|
||||
ADD(patterns, STATIC_CSTR_TO_OBJ(""));
|
||||
Array patterns = get_patterns_from_pattern_or_buf(opts->pattern, has_buffer, opts->buffer, "",
|
||||
arena, err);
|
||||
if (ERROR_SET(err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (HAS_KEY(opts, exec_autocmds, data)) {
|
||||
@ -779,7 +764,7 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
|
||||
|
||||
bool did_aucmd = false;
|
||||
FOREACH_ITEM(event_array, event_str, {
|
||||
GET_ONE_EVENT(event_nr, event_str, cleanup)
|
||||
GET_ONE_EVENT(event_nr, event_str, return )
|
||||
|
||||
FOREACH_ITEM(patterns, pat, {
|
||||
char *fname = !has_buffer ? pat.data.string.data : NULL;
|
||||
@ -790,28 +775,26 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
|
||||
if (did_aucmd && modeline) {
|
||||
do_modelines(0);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
api_free_array(event_array);
|
||||
api_free_array(patterns);
|
||||
}
|
||||
|
||||
static bool unpack_string_or_array(Array *array, Object *v, char *k, bool required, Error *err)
|
||||
static Array unpack_string_or_array(Object v, char *k, bool required, Arena *arena, Error *err)
|
||||
{
|
||||
if (v->type == kObjectTypeString) {
|
||||
ADD(*array, copy_object(*v, NULL));
|
||||
} else if (v->type == kObjectTypeArray) {
|
||||
if (!check_string_array(v->data.array, k, true, err)) {
|
||||
return false;
|
||||
if (v.type == kObjectTypeString) {
|
||||
Array arr = arena_array(arena, 1);
|
||||
ADD_C(arr, v);
|
||||
return arr;
|
||||
} else if (v.type == kObjectTypeArray) {
|
||||
if (!check_string_array(v.data.array, k, true, err)) {
|
||||
return (Array)ARRAY_DICT_INIT;
|
||||
}
|
||||
*array = copy_array(v->data.array, NULL);
|
||||
return v.data.array;
|
||||
} else {
|
||||
VALIDATE_EXP(!required, k, "Array or String", api_typename(v->type), {
|
||||
return false;
|
||||
VALIDATE_EXP(!required, k, "Array or String", api_typename(v.type), {
|
||||
return (Array)ARRAY_DICT_INIT;
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
return (Array)ARRAY_DICT_INIT;
|
||||
}
|
||||
|
||||
// Returns AUGROUP_ERROR if there was a problem with {group}
|
||||
@ -843,55 +826,57 @@ static int get_augroup_from_object(Object group, Error *err)
|
||||
}
|
||||
}
|
||||
|
||||
static bool get_patterns_from_pattern_or_buf(Array *patterns, Object pattern, bool has_buffer,
|
||||
Buffer buffer, Error *err)
|
||||
static Array get_patterns_from_pattern_or_buf(Object pattern, bool has_buffer, Buffer buffer,
|
||||
char *fallback, Arena *arena, Error *err)
|
||||
{
|
||||
const char pattern_buflocal[BUFLOCAL_PAT_LEN];
|
||||
ArrayBuilder patterns = ARRAY_DICT_INIT;
|
||||
kvi_init(patterns);
|
||||
|
||||
if (pattern.type != kObjectTypeNil) {
|
||||
Object *v = &pattern;
|
||||
|
||||
if (v->type == kObjectTypeString) {
|
||||
const char *pat = v->data.string.data;
|
||||
if (pattern.type == kObjectTypeString) {
|
||||
const char *pat = pattern.data.string.data;
|
||||
size_t patlen = aucmd_pattern_length(pat);
|
||||
while (patlen) {
|
||||
ADD(*patterns, STRING_OBJ(cbuf_to_string(pat, patlen)));
|
||||
kvi_push(patterns, CBUF_TO_ARENA_OBJ(arena, pat, patlen));
|
||||
|
||||
pat = aucmd_next_pattern(pat, patlen);
|
||||
patlen = aucmd_pattern_length(pat);
|
||||
}
|
||||
} else if (v->type == kObjectTypeArray) {
|
||||
if (!check_string_array(v->data.array, "pattern", true, err)) {
|
||||
return false;
|
||||
} else if (pattern.type == kObjectTypeArray) {
|
||||
if (!check_string_array(pattern.data.array, "pattern", true, err)) {
|
||||
return (Array)ARRAY_DICT_INIT;
|
||||
}
|
||||
|
||||
Array array = v->data.array;
|
||||
Array array = pattern.data.array;
|
||||
FOREACH_ITEM(array, entry, {
|
||||
const char *pat = entry.data.string.data;
|
||||
size_t patlen = aucmd_pattern_length(pat);
|
||||
while (patlen) {
|
||||
ADD(*patterns, STRING_OBJ(cbuf_to_string(pat, patlen)));
|
||||
kvi_push(patterns, CBUF_TO_ARENA_OBJ(arena, pat, patlen));
|
||||
|
||||
pat = aucmd_next_pattern(pat, patlen);
|
||||
patlen = aucmd_pattern_length(pat);
|
||||
}
|
||||
})
|
||||
} else {
|
||||
VALIDATE_EXP(false, "pattern", "String or Table", api_typename(v->type), {
|
||||
return false;
|
||||
VALIDATE_EXP(false, "pattern", "String or Table", api_typename(pattern.type), {
|
||||
return (Array)ARRAY_DICT_INIT;
|
||||
});
|
||||
}
|
||||
} else if (has_buffer) {
|
||||
buf_T *buf = find_buffer_by_handle(buffer, err);
|
||||
if (ERROR_SET(err)) {
|
||||
return false;
|
||||
return (Array)ARRAY_DICT_INIT;
|
||||
}
|
||||
|
||||
snprintf((char *)pattern_buflocal, BUFLOCAL_PAT_LEN, "<buffer=%d>", (int)buf->handle);
|
||||
ADD(*patterns, CSTR_TO_OBJ(pattern_buflocal));
|
||||
kvi_push(patterns, STRING_OBJ(arena_printf(arena, "<buffer=%d>", (int)buf->handle)));
|
||||
}
|
||||
|
||||
return true;
|
||||
if (kv_size(patterns) == 0 && fallback) {
|
||||
kvi_push(patterns, CSTR_AS_OBJ(fallback));
|
||||
}
|
||||
|
||||
return arena_take_arraybuilder(arena, &patterns);
|
||||
}
|
||||
|
||||
static bool clear_autocmd(event_T event, char *pat, int au_group, Error *err)
|
||||
|
@ -585,7 +585,7 @@ Array arena_take_arraybuilder(Arena *arena, ArrayBuilder *arr)
|
||||
{
|
||||
Array ret = arena_array(arena, kv_size(*arr));
|
||||
ret.size = kv_size(*arr);
|
||||
memcpy((ret).items, (*arr).items, sizeof((ret).items[0]) * (ret).size);
|
||||
memcpy(ret.items, arr->items, sizeof(ret.items[0]) * ret.size);
|
||||
kvi_destroy(*arr);
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user