aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2024-03-09 14:57:57 -0700
committerJosh Rahm <joshuarahm@gmail.com>2024-03-09 14:57:57 -0700
commitc324271b99eee4c621463f368914d57cd729bd9c (patch)
tree5d979d333a2d5f9c080991d5482fd5916f8579c6 /src/nvim/api
parent931bffbda3668ddc609fc1da8f9eb576b170aa52 (diff)
parentade1b12f49c3b3914c74847d791eb90ea90b56b7 (diff)
downloadrneovim-c324271b99eee4c621463f368914d57cd729bd9c.tar.gz
rneovim-c324271b99eee4c621463f368914d57cd729bd9c.tar.bz2
rneovim-c324271b99eee4c621463f368914d57cd729bd9c.zip
Merge remote-tracking branch 'upstream/master' into userreg
Diffstat (limited to 'src/nvim/api')
-rw-r--r--src/nvim/api/autocmd.c252
-rw-r--r--src/nvim/api/buffer.c347
-rw-r--r--src/nvim/api/buffer.h3
-rw-r--r--src/nvim/api/command.c218
-rw-r--r--src/nvim/api/deprecated.c114
-rw-r--r--src/nvim/api/deprecated.h1
-rw-r--r--src/nvim/api/dispatch_deprecated.lua132
-rw-r--r--src/nvim/api/extmark.c360
-rw-r--r--src/nvim/api/keysets_defs.h76
-rw-r--r--src/nvim/api/options.c344
-rw-r--r--src/nvim/api/private/converter.c121
-rw-r--r--src/nvim/api/private/defs.h10
-rw-r--r--src/nvim/api/private/dispatch.h16
-rw-r--r--src/nvim/api/private/helpers.c282
-rw-r--r--src/nvim/api/private/helpers.h30
-rw-r--r--src/nvim/api/private/validate.h2
-rw-r--r--src/nvim/api/tabpage.c54
-rw-r--r--src/nvim/api/ui.c499
-rw-r--r--src/nvim/api/ui.h19
-rw-r--r--src/nvim/api/ui_events.in.h2
-rw-r--r--src/nvim/api/vim.c600
-rw-r--r--src/nvim/api/vimscript.c285
-rw-r--r--src/nvim/api/win_config.c630
-rw-r--r--src/nvim/api/window.c45
24 files changed, 2248 insertions, 2194 deletions
diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c
index 08d9d8e117..d71bcc4bcf 100644
--- a/src/nvim/api/autocmd.c
+++ b/src/nvim/api/autocmd.c
@@ -14,13 +14,17 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/validate.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds_defs.h"
-#include "nvim/func_attr.h"
#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"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -30,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
@@ -71,7 +75,7 @@ static int64_t next_autocmd_id = 1;
/// - buffer: Buffer number or list of buffer numbers for buffer local autocommands
/// |autocmd-buflocal|. Cannot be used with {pattern}
/// @return Array of autocommands matching the criteria, with each item
-/// containing the following fields:
+/// containing the following fields:
/// - id (number): the autocommand id (only when defined with the API).
/// - group (integer): the autocommand group id.
/// - group_name (string): the autocommand group name.
@@ -79,20 +83,20 @@ static int64_t next_autocmd_id = 1;
/// - event (string): the autocommand event.
/// - command (string): the autocommand command. Note: this will be empty if a callback is set.
/// - callback (function|string|nil): Lua function or name of a Vim script function
-/// which is executed when this autocommand is triggered.
+/// which is executed when this autocommand is triggered.
/// - once (boolean): whether the autocommand is only run once.
/// - pattern (string): the autocommand pattern.
-/// If the autocommand is buffer local |autocmd-buffer-local|:
+/// 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;
@@ -128,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, {
@@ -136,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 {
@@ -184,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)",
@@ -193,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), {
@@ -204,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), {
@@ -247,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));
@@ -264,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)));
+ 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
@@ -325,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
@@ -375,15 +380,16 @@ cleanup:
/// |autocmd-buflocal|. Cannot be used with {pattern}.
/// - desc (string) optional: description (for documentation and troubleshooting).
/// - callback (function|string) optional: Lua function (or Vimscript function name, if
-/// string) called when the event(s) is triggered. Lua callback can return true to
-/// delete the autocommand, and receives a table argument with these keys:
+/// string) called when the event(s) is triggered. Lua callback can return a truthy
+/// value (not `false` or `nil`) to delete the autocommand. Receives a table argument
+/// with these keys:
/// - id: (number) autocommand id
/// - event: (string) name of the triggered event |autocmd-events|
/// - group: (number|nil) autocommand group id, if any
-/// - match: (string) expanded value of |<amatch>|
-/// - buf: (number) expanded value of |<abuf>|
-/// - file: (string) expanded value of |<afile>|
-/// - data: (any) arbitrary data passed from |nvim_exec_autocmds()|
+/// - match: (string) expanded value of [<amatch>]
+/// - buf: (number) expanded value of [<abuf>]
+/// - file: (string) expanded value of [<afile>]
+/// - data: (any) arbitrary data passed from [nvim_exec_autocmds()]
/// - command (string) optional: Vim command to execute on event. Cannot be used with
/// {callback}
/// - once (boolean) optional: defaults to false. Run the autocommand
@@ -395,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;
}
@@ -428,7 +433,8 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
});
cb.type = kCallbackLua;
- cb.data.luaref = api_new_luaref(callback->data.luaref);
+ cb.data.luaref = callback->data.luaref;
+ callback->data.luaref = LUA_NOREF;
break;
case kObjectTypeString:
cb.type = kCallbackFuncref;
@@ -464,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;
}
@@ -472,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;
@@ -509,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;
}
@@ -534,9 +536,9 @@ void nvim_del_autocmd(Integer id, Error *err)
/// @param opts Parameters
/// - event: (string|table)
/// Examples:
-/// - event: "pat1"
-/// - event: { "pat1" }
-/// - event: { "pat1", "pat2", "pat3" }
+/// - event: "pat1"
+/// - event: { "pat1" }
+/// - event: { "pat1", "pat2", "pat3" }
/// - pattern: (string|table)
/// - pattern or patterns to match exactly.
/// - For example, if you have `*.py` as that pattern for the autocmd,
@@ -550,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:
@@ -559,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.
@@ -594,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|.
@@ -700,11 +694,11 @@ void nvim_del_augroup_by_name(String name, Error *err)
/// - buffer (integer) optional: buffer number |autocmd-buflocal|. Cannot be used with
/// {pattern}.
/// - modeline (bool) optional: defaults to true. Process the
-/// modeline after the autocommands |<nomodeline>|.
+/// modeline after the autocommands [<nomodeline>].
/// - 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;
@@ -712,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) {
@@ -727,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;
});
}
@@ -747,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)) {
@@ -774,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;
@@ -785,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}
@@ -838,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)
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 0df231868d..7f195de959 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -12,10 +12,12 @@
#include "nvim/api/buffer.h"
#include "nvim/api/keysets_defs.h"
#include "nvim/api/private/defs.h"
+#include "nvim/api/private/dispatch.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/validate.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/buffer_updates.h"
@@ -24,28 +26,32 @@
#include "nvim/drawscreen.h"
#include "nvim/ex_cmds.h"
#include "nvim/extmark.h"
-#include "nvim/func_attr.h"
+#include "nvim/extmark_defs.h"
#include "nvim/globals.h"
#include "nvim/lua/executor.h"
#include "nvim/mapping.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
+#include "nvim/marktree_defs.h"
#include "nvim/memline.h"
+#include "nvim/memline_defs.h"
#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/move.h"
#include "nvim/ops.h"
#include "nvim/pos_defs.h"
#include "nvim/state_defs.h"
#include "nvim/types_defs.h"
#include "nvim/undo.h"
+#include "nvim/undo_defs.h"
#include "nvim/vim_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/buffer.c.generated.h"
#endif
-/// \defgroup api-buffer
-///
-/// \brief For more information on buffers, see |buffers|
+/// @brief <pre>help
+/// For more information on buffers, see |buffers|.
///
/// Unloaded Buffers: ~
///
@@ -57,6 +63,7 @@
///
/// You can use |nvim_buf_is_loaded()| or |nvim_buf_line_count()| to check
/// whether a buffer is loaded.
+/// </pre>
/// Returns the number of lines in the given buffer.
///
@@ -105,7 +112,7 @@ Integer nvim_buf_line_count(Buffer buffer, Error *err)
/// Not for Lua callbacks.
/// @param opts Optional parameters.
/// - on_lines: Lua callback invoked on change.
-/// Return `true` to detach. Args:
+/// Return a truthy value (not `false` or `nil`) to detach. Args:
/// - the string "lines"
/// - buffer handle
/// - b:changedtick
@@ -118,8 +125,7 @@ Integer nvim_buf_line_count(Buffer buffer, Error *err)
/// - on_bytes: Lua callback invoked on change.
/// This callback receives more granular information about the
/// change compared to on_lines.
-/// Return `true` to detach.
-/// Args:
+/// Return a truthy value (not `false` or `nil`) to detach. Args:
/// - the string "bytes"
/// - buffer handle
/// - b:changedtick
@@ -127,11 +133,13 @@ Integer nvim_buf_line_count(Buffer buffer, Error *err)
/// - start column of the changed text
/// - byte offset of the changed text (from the start of
/// the buffer)
-/// - old end row of the changed text
+/// - old end row of the changed text (offset from start row)
/// - old end column of the changed text
+/// (if old end row = 0, offset from start column)
/// - old end byte length of the changed text
-/// - new end row of the changed text
+/// - new end row of the changed text (offset from start row)
/// - new end column of the changed text
+/// (if new end row = 0, offset from start column)
/// - new end byte length of the changed text
/// - on_changedtick: Lua callback invoked on changedtick
/// increment without text change. Args:
@@ -153,7 +161,7 @@ Integer nvim_buf_line_count(Buffer buffer, Error *err)
/// @return False if attach failed (invalid parameter, or buffer isn't loaded);
/// otherwise True. TODO: LUA_API_NO_EVAL
Boolean nvim_buf_attach(uint64_t channel_id, Buffer buffer, Boolean send_buffer,
- DictionaryOf(LuaRef) opts, Error *err)
+ Dict(buf_attach) *opts, Error *err)
FUNC_API_SINCE(4)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -162,64 +170,40 @@ Boolean nvim_buf_attach(uint64_t channel_id, Buffer buffer, Boolean send_buffer,
return false;
}
- bool is_lua = (channel_id == LUA_INTERNAL_CALL);
BufUpdateCallbacks cb = BUF_UPDATE_CALLBACKS_INIT;
- struct {
- const char *name;
- LuaRef *dest;
- } cbs[] = {
- { "on_lines", &cb.on_lines },
- { "on_bytes", &cb.on_bytes },
- { "on_changedtick", &cb.on_changedtick },
- { "on_detach", &cb.on_detach },
- { "on_reload", &cb.on_reload },
- { NULL, NULL },
- };
-
- for (size_t i = 0; i < opts.size; i++) {
- String k = opts.items[i].key;
- Object *v = &opts.items[i].value;
- bool key_used = false;
- if (is_lua) {
- for (size_t j = 0; cbs[j].name; j++) {
- if (strequal(cbs[j].name, k.data)) {
- VALIDATE_T(cbs[j].name, kObjectTypeLuaRef, v->type, {
- goto error;
- });
- *(cbs[j].dest) = v->data.luaref;
- v->data.luaref = LUA_NOREF;
- key_used = true;
- break;
- }
- }
- if (key_used) {
- continue;
- } else if (strequal("utf_sizes", k.data)) {
- VALIDATE_T("utf_sizes", kObjectTypeBoolean, v->type, {
- goto error;
- });
- cb.utf_sizes = v->data.boolean;
- key_used = true;
- } else if (strequal("preview", k.data)) {
- VALIDATE_T("preview", kObjectTypeBoolean, v->type, {
-