diff options
Diffstat (limited to 'src/nvim/api/autocmd.c')
-rw-r--r-- | src/nvim/api/autocmd.c | 178 |
1 files changed, 128 insertions, 50 deletions
diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c index 0ad7b320d0..5ede0e5265 100644 --- a/src/nvim/api/autocmd.c +++ b/src/nvim/api/autocmd.c @@ -40,8 +40,10 @@ static int64_t next_autocmd_id = 1; /// /// @param 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 +/// - group (string|int): Name or id of group 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 Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) @@ -53,24 +55,34 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) char_u *pattern_filters[AUCMD_MAX_PATTERNS]; char_u pattern_buflocal[BUFLOCAL_PAT_LEN]; + Array buffers = ARRAY_DICT_INIT; + bool event_set[NUM_EVENTS] = { false }; bool check_event = false; int group = 0; - if (opts->group.type != kObjectTypeNil) { - Object v = opts->group; - if (v.type != kObjectTypeString) { - api_set_error(err, kErrorTypeValidation, "group must be a string."); - goto cleanup; - } - - group = augroup_find(v.data.string.data); - - if (group < 0) { - api_set_error(err, kErrorTypeValidation, "invalid augroup passed."); + switch (opts->group.type) { + case kObjectTypeNil: + break; + case kObjectTypeString: + group = augroup_find(opts->group.data.string.data); + if (group < 0) { + api_set_error(err, kErrorTypeValidation, "invalid augroup passed."); + goto cleanup; + } + break; + case kObjectTypeInteger: + group = (int)opts->group.data.integer; + char *name = augroup_name(group); + if (!augroup_exists(name)) { + api_set_error(err, kErrorTypeValidation, "invalid augroup passed."); + goto cleanup; + } + break; + default: + api_set_error(err, kErrorTypeValidation, "group must be a string or an integer."); goto cleanup; - } } if (opts->event.type != kObjectTypeNil) { @@ -100,6 +112,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; if (opts->pattern.type != kObjectTypeNil) { Object v = opts->pattern; @@ -107,25 +125,70 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) pattern_filters[pattern_filter_count] = (char_u *)v.data.string.data; pattern_filter_count += 1; } 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, { + 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_filter_count += 1; }); } else { - api_set_error(err, - kErrorTypeValidation, + api_set_error(err, kErrorTypeValidation, "Not a valid 'pattern' value. Must be a string or an array"); goto cleanup; } + } + + if (opts->buffer.type == kObjectTypeInteger || opts->buffer.type == kObjectTypeBuffer) { + buf_T *buf = find_buffer_by_handle((Buffer)opts->buffer.data.integer, err); + if (ERROR_SET(err)) { + goto cleanup; + } - if (pattern_filter_count >= AUCMD_MAX_PATTERNS) { + 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 patterns. Please limit yourself to less"); + "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) { if (check_event && !event_set[event]) { continue; @@ -234,6 +297,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) } cleanup: + api_free_array(buffers); return autocmd_list; } @@ -265,7 +329,7 @@ cleanup: /// - buffer: (bufnr) /// - create a |autocmd-buflocal| autocmd. /// - NOTE: Cannot be used with {pattern} -/// - group: (string) The augroup name +/// - group: (string|int) The augroup name or id /// - once: (boolean) - See |autocmd-once| /// - nested: (boolean) - See |autocmd-nested| /// - desc: (string) - Description of the autocmd @@ -350,23 +414,29 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc bool is_once = api_object_to_bool(opts->once, "once", false, err); bool is_nested = api_object_to_bool(opts->nested, "nested", false, err); - // TODO(tjdevries): accept number for namespace instead - if (opts->group.type != kObjectTypeNil) { - Object *v = &opts->group; - if (v->type != kObjectTypeString) { - api_set_error(err, kErrorTypeValidation, "'group' must be a string"); - goto cleanup; - } - - au_group = augroup_find(v->data.string.data); - - if (au_group == AUGROUP_ERROR) { - api_set_error(err, - kErrorTypeException, - "invalid augroup: %s", v->data.string.data); - + switch (opts->group.type) { + case kObjectTypeNil: + break; + case kObjectTypeString: + au_group = augroup_find(opts->group.data.string.data); + if (au_group == AUGROUP_ERROR) { + api_set_error(err, + kErrorTypeValidation, + "invalid augroup: %s", opts->group.data.string.data); + goto cleanup; + } + break; + case kObjectTypeInteger: + au_group = (int)opts->group.data.integer; + char *name = augroup_name(au_group); + if (!augroup_exists(name)) { + api_set_error(err, kErrorTypeValidation, "invalid augroup: %d", au_group); + goto cleanup; + } + break; + default: + api_set_error(err, kErrorTypeValidation, "'group' must be a string or an integer."); goto cleanup; - } } if (opts->pattern.type != kObjectTypeNil && opts->buffer.type != kObjectTypeNil) { @@ -568,7 +638,7 @@ void nvim_del_augroup_by_name(String name) /// - NOTE: Cannot be used with {pattern} /// - pattern (string|table) - optional, defaults to "*". /// - NOTE: Cannot be used with {buffer} -/// - group (string) - autocmd group name +/// - group (string|int) - autocmd group name or id /// - modeline (boolean) - Default true, see |<nomodeline>| void nvim_do_autocmd(Object event, Dict(do_autocmd) *opts, Error *err) FUNC_API_SINCE(9) @@ -588,21 +658,29 @@ void nvim_do_autocmd(Object event, Dict(do_autocmd) *opts, Error *err) goto cleanup; } - if (opts->group.type != kObjectTypeNil) { - if (opts->group.type != kObjectTypeString) { - api_set_error(err, kErrorTypeValidation, "'group' must be a string"); - goto cleanup; - } - - au_group = augroup_find(opts->group.data.string.data); - - if (au_group == AUGROUP_ERROR) { - api_set_error(err, - kErrorTypeException, - "invalid augroup: %s", opts->group.data.string.data); - + switch (opts->group.type) { + case kObjectTypeNil: + break; + case kObjectTypeString: + au_group = augroup_find(opts->group.data.string.data); + if (au_group == AUGROUP_ERROR) { + api_set_error(err, + kErrorTypeValidation, + "invalid augroup: %s", opts->group.data.string.data); + goto cleanup; + } + break; + case kObjectTypeInteger: + au_group = (int)opts->group.data.integer; + char *name = augroup_name(au_group); + if (!augroup_exists(name)) { + api_set_error(err, kErrorTypeValidation, "invalid augroup: %d", au_group); + goto cleanup; + } + break; + default: + api_set_error(err, kErrorTypeValidation, "'group' must be a string or an integer."); goto cleanup; - } } if (opts->buffer.type != kObjectTypeNil) { |