aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/vim.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/api/vim.c')
-rw-r--r--src/nvim/api/vim.c600
1 files changed, 322 insertions, 278 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index d631b10af9..84a2f24dbc 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -21,21 +21,26 @@
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/channel.h"
+#include "nvim/channel_defs.h"
#include "nvim/context.h"
#include "nvim/cursor.h"
#include "nvim/decoration.h"
#include "nvim/drawscreen.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/getchar.h"
+#include "nvim/getchar_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
+#include "nvim/grid_defs.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/keycodes.h"
#include "nvim/log.h"
@@ -43,25 +48,33 @@
#include "nvim/macros_defs.h"
#include "nvim/mapping.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/message.h"
+#include "nvim/message_defs.h"
#include "nvim/move.h"
#include "nvim/msgpack_rpc/channel.h"
+#include "nvim/msgpack_rpc/channel_defs.h"
#include "nvim/msgpack_rpc/unpacker.h"
#include "nvim/ops.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/optionstr.h"
#include "nvim/os/input.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/process.h"
#include "nvim/popupmenu.h"
#include "nvim/pos_defs.h"
#include "nvim/runtime.h"
-#include "nvim/sign.h"
+#include "nvim/sign_defs.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
#include "nvim/statusline.h"
+#include "nvim/statusline_defs.h"
#include "nvim/strings.h"
#include "nvim/terminal.h"
#include "nvim/types_defs.h"
@@ -110,7 +123,7 @@ Dictionary nvim_get_hl(Integer ns_id, Dict(get_highlight) *opts, Arena *arena, E
///
/// @note Unlike the `:highlight` command which can update a highlight group,
/// this function completely replaces the definition. For example:
-/// ``nvim_set_hl(0, 'Visual', {})`` will clear the highlight group
+/// `nvim_set_hl(0, 'Visual', {})` will clear the highlight group
/// 'Visual'.
///
/// @note The fg and bg keys also accept the string values `"fg"` or `"bg"`
@@ -128,9 +141,9 @@ Dictionary nvim_get_hl(Integer ns_id, Dict(get_highlight) *opts, Arena *arena, E
/// |nvim_set_hl_ns()| or |nvim_win_set_hl_ns()| to activate them.
/// @param name Highlight group name, e.g. "ErrorMsg"
/// @param val Highlight definition map, accepts the following keys:
-/// - fg (or foreground): color name or "#RRGGBB", see note.
-/// - bg (or background): color name or "#RRGGBB", see note.
-/// - sp (or special): color name or "#RRGGBB"
+/// - fg: color name or "#RRGGBB", see note.
+/// - bg: color name or "#RRGGBB", see note.
+/// - sp: color name or "#RRGGBB"
/// - blend: integer between 0 and 100
/// - bold: boolean
/// - standout: boolean
@@ -163,6 +176,12 @@ void nvim_set_hl(Integer ns_id, String name, Dict(highlight) *val, Error *err)
});
int link_id = -1;
+ // Setting URLs directly through highlight attributes is not supported
+ if (HAS_KEY(val, highlight, url)) {
+ api_free_string(val->url);
+ val->url = NULL_STRING;
+ }
+
HlAttrs attrs = dict2hlattrs(val, true, &link_id, err);
if (!ERROR_SET(err)) {
ns_hl_def((NS)ns_id, hl_id, attrs, link_id, val);
@@ -230,7 +249,7 @@ void nvim_set_hl_ns_fast(Integer ns_id, Error *err)
///
/// On execution error: does not fail, but updates v:errmsg.
///
-/// To input sequences like <C-o> use |nvim_replace_termcodes()| (typically
+/// To input sequences like [<C-o>] use |nvim_replace_termcodes()| (typically
/// with escape_ks=false) to replace |keycodes|, then pass the result to
/// nvim_feedkeys().
///
@@ -318,11 +337,11 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_ks)
///
/// On execution error: does not fail, but updates v:errmsg.
///
-/// @note |keycodes| like <CR> are translated, so "<" is special.
-/// To input a literal "<", send <LT>.
+/// @note |keycodes| like [<CR>] are translated, so "<" is special.
+/// To input a literal "<", send [<LT>].
///
/// @note For mouse events use |nvim_input_mouse()|. The pseudokey form
-/// "<LeftMouse><col,row>" is deprecated since |api-level| 6.
+/// `<LeftMouse><col,row>` is deprecated since |api-level| 6.
///
/// @param keys to be typed
/// @return Number of bytes actually written (can be fewer than
@@ -343,9 +362,10 @@ Integer nvim_input(String keys)
/// by calling it multiple times in a loop: the intermediate mouse
/// positions will be ignored. It should be used to implement real-time
/// mouse input in a GUI. The deprecated pseudokey form
-/// ("<LeftMouse><col,row>") of |nvim_input()| has the same limitation.
+/// (`<LeftMouse><col,row>`) of |nvim_input()| has the same limitation.
///
-/// @param button Mouse button: one of "left", "right", "middle", "wheel", "move".
+/// @param button Mouse button: one of "left", "right", "middle", "wheel", "move",
+/// "x1", "x2".
/// @param action For ordinary buttons, one of "press", "drag", "release".
/// For the wheel, one of "up", "down", "left", "right". Ignored for "move".
/// @param modifier String of modifiers each represented by a single char.
@@ -376,6 +396,10 @@ void nvim_input_mouse(String button, String action, String modifier, Integer gri
code = KE_RIGHTMOUSE;
} else if (strequal(button.data, "wheel")) {
code = KE_MOUSEDOWN;
+ } else if (strequal(button.data, "x1")) {
+ code = KE_X1MOUSE;
+ } else if (strequal(button.data, "x2")) {
+ code = KE_X2MOUSE;
} else if (strequal(button.data, "move")) {
code = KE_MOUSEMOVE;
} else {
@@ -427,17 +451,17 @@ error:
"invalid button or action");
}
-/// Replaces terminal codes and |keycodes| (<CR>, <Esc>, ...) in a string with
+/// Replaces terminal codes and |keycodes| ([<CR>], [<Esc>], ...) in a string with
/// the internal representation.
///
/// @param str String to be converted.
/// @param from_part Legacy Vim parameter. Usually true.
-/// @param do_lt Also translate <lt>. Ignored if `special` is false.
-/// @param special Replace |keycodes|, e.g. <CR> becomes a "\r" char.
+/// @param do_lt Also translate [<lt>]. Ignored if `special` is false.
+/// @param special Replace |keycodes|, e.g. [<CR>] becomes a "\r" char.
/// @see replace_termcodes
/// @see cpoptions
String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Boolean special)
- FUNC_API_SINCE(1)
+ FUNC_API_SINCE(1) FUNC_API_RET_ALLOC
{
if (str.size == 0) {
// Empty string
@@ -456,7 +480,7 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Bool
}
char *ptr = NULL;
- replace_termcodes(str.data, str.size, &ptr, 0, flags, NULL, CPO_TO_CPO_FLAGS);
+ replace_termcodes(str.data, str.size, &ptr, 0, flags, NULL, p_cpo);
return cstr_as_string(ptr);
}
@@ -472,11 +496,12 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Bool
/// or executing the Lua code.
///
/// @return Return value of Lua code if present or NIL.
-Object nvim_exec_lua(String code, Array args, Error *err)
+Object nvim_exec_lua(String code, Array args, Arena *arena, Error *err)
FUNC_API_SINCE(7)
FUNC_API_REMOTE_ONLY
{
- return nlua_exec(code, args, err);
+ // TODO(bfredl): convert directly from msgpack to lua and then back again
+ return nlua_exec(code, args, kRetObject, arena, err);
}
/// Notify the user with a message
@@ -488,7 +513,7 @@ Object nvim_exec_lua(String code, Array args, Error *err)
/// @param log_level The log level
/// @param opts Reserved for future use.
/// @param[out] err Error details, if any
-Object nvim_notify(String msg, Integer log_level, Dictionary opts, Error *err)
+Object nvim_notify(String msg, Integer log_level, Dictionary opts, Arena *arena, Error *err)
FUNC_API_SINCE(7)
{
MAXSIZE_TEMP_ARRAY(args, 3);
@@ -496,11 +521,11 @@ Object nvim_notify(String msg, Integer log_level, Dictionary opts, Error *err)
ADD_C(args, INTEGER_OBJ(log_level));
ADD_C(args, DICTIONARY_OBJ(opts));
- return NLUA_EXEC_STATIC("return vim.notify(...)", args, err);
+ return NLUA_EXEC_STATIC("return vim.notify(...)", args, kRetObject, arena, err);
}
/// Calculates the number of display cells occupied by `text`.
-/// Control characters including <Tab> count as one cell.
+/// Control characters including [<Tab>] count as one cell.
///
/// @param text Some text
/// @param[out] err Error details, if any
@@ -518,17 +543,23 @@ Integer nvim_strwidth(String text, Error *err)
/// Gets the paths contained in |runtime-search-path|.
///
/// @return List of paths
-ArrayOf(String) nvim_list_runtime_paths(Error *err)
+ArrayOf(String) nvim_list_runtime_paths(Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
- return nvim_get_runtime_file(NULL_STRING, true, err);
+ return nvim_get_runtime_file(NULL_STRING, true, arena, err);
}
-Array nvim__runtime_inspect(void)
+/// @nodoc
+Array nvim__runtime_inspect(Arena *arena)
{
- return runtime_inspect();
+ return runtime_inspect(arena);
}
+typedef struct {
+ ArrayBuilder rv;
+ Arena *arena;
+} RuntimeCookie;
+
/// Find files in runtime directories
///
/// "name" can contain wildcards. For example
@@ -541,25 +572,27 @@ Array nvim__runtime_inspect(void)
/// @param name pattern of files to search for
/// @param all whether to return all matches or only the first
/// @return list of absolute paths to the found files
-ArrayOf(String) nvim_get_runtime_file(String name, Boolean all, Error *err)
+ArrayOf(String) nvim_get_runtime_file(String name, Boolean all, Arena *arena, Error *err)
FUNC_API_SINCE(7)
FUNC_API_FAST
{
- Array rv = ARRAY_DICT_INIT;
+ RuntimeCookie cookie = { .rv = ARRAY_DICT_INIT, .arena = arena, };
+ kvi_init(cookie.rv);
int flags = DIP_DIRFILE | (all ? DIP_ALL : 0);
TRY_WRAP(err, {
- do_in_runtimepath((name.size ? name.data : ""), flags, find_runtime_cb, &rv);
+ do_in_runtimepath((name.size ? name.data : ""), flags, find_runtime_cb, &cookie);
});
- return rv;
+ return arena_take_arraybuilder(arena, &cookie.rv);
}
-static bool find_runtime_cb(int num_fnames, char **fnames, bool all, void *cookie)
+static bool find_runtime_cb(int num_fnames, char **fnames, bool all, void *c)
{
- Array *rv = (Array *)cookie;
+ RuntimeCookie *cookie = (RuntimeCookie *)c;
for (int i = 0; i < num_fnames; i++) {
- ADD(*rv, CSTR_TO_OBJ(fnames[i]));
+ // TODO(bfredl): consider memory management of gen_expand_wildcards() itself
+ kvi_push(cookie->rv, CSTR_TO_ARENA_OBJ(cookie->arena, fnames[i]));
if (!all) {
return true;
}
@@ -568,7 +601,9 @@ static bool find_runtime_cb(int num_fnames, char **fnames, bool all, void *cooki
return num_fnames > 0;
}
+/// @nodoc
String nvim__get_lib_dir(void)
+ FUNC_API_RET_ALLOC
{
return cstr_as_string(get_lib_dir());
}
@@ -579,7 +614,8 @@ String nvim__get_lib_dir(void)
/// @param all whether to return all matches or only the first
/// @param opts is_lua: only search Lua subdirs
/// @return list of absolute paths to the found files
-ArrayOf(String) nvim__get_runtime(Array pat, Boolean all, Dict(runtime) *opts, Error *err)
+ArrayOf(String) nvim__get_runtime(Array pat, Boolean all, Dict(runtime) *opts, Arena *arena,
+ Error *err)
FUNC_API_SINCE(8)
FUNC_API_FAST
{
@@ -589,12 +625,12 @@ ArrayOf(String) nvim__get_runtime(Array pat, Boolean all, Dict(runtime) *opts, E
return (Array)ARRAY_DICT_INIT;
}
- ArrayOf(String) res = runtime_get_named(opts->is_lua, pat, all);
+ ArrayOf(String) res = runtime_get_named(opts->is_lua, pat, all, arena);
if (opts->do_source) {
for (size_t i = 0; i < res.size; i++) {
String name = res.items[i].data.string;
- (void)do_source(name.data, false, DOSO_NONE, NULL);
+ do_source(name.data, false, DOSO_NONE, NULL);
}
}
@@ -632,31 +668,31 @@ void nvim_set_current_dir(String dir, Error *err)
///
/// @param[out] err Error details, if any
/// @return Current line string
-String nvim_get_current_line(Error *err)
+String nvim_get_current_line(Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
- return buffer_get_line(curbuf->handle, curwin->w_cursor.lnum - 1, err);
+ return buffer_get_line(curbuf->handle, curwin->w_cursor.lnum - 1, arena, err);
}
/// Sets the current line.
///
/// @param line Line contents
/// @param[out] err Error details, if any
-void nvim_set_current_line(String line, Error *err)
+void nvim_set_current_line(String line, Arena *arena, Error *err)
FUNC_API_SINCE(1)
FUNC_API_TEXTLOCK_ALLOW_CMDWIN
{
- buffer_set_line(curbuf->handle, curwin->w_cursor.lnum - 1, line, err);
+ buffer_set_line(curbuf->handle, curwin->w_cursor.lnum - 1, line, arena, err);
}
/// Deletes the current line.
///
/// @param[out] err Error details, if any
-void nvim_del_current_line(Error *err)
+void nvim_del_current_line(Arena *arena, Error *err)
FUNC_API_SINCE(1)
FUNC_API_TEXTLOCK_ALLOW_CMDWIN
{
- buffer_del_line(curbuf->handle, curwin->w_cursor.lnum - 1, err);
+ buffer_del_line(curbuf->handle, curwin->w_cursor.lnum - 1, arena, err);
}
/// Gets a global (g:) variable.
@@ -664,7 +700,7 @@ void nvim_del_current_line(Error *err)
/// @param name Variable name
/// @param[out] err Error details, if any
/// @return Variable value
-Object nvim_get_var(String name, Error *err)
+Object nvim_get_var(String name, Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
dictitem_T *di = tv_dict_find(&globvardict, name.data, (ptrdiff_t)name.size);
@@ -678,7 +714,7 @@ Object nvim_get_var(String name, Error *err)
VALIDATE((di != NULL), "Key not found: %s", name.data, {
return (Object)OBJECT_INIT;
});
- return vim_to_object(&di->di_tv);
+ return vim_to_object(&di->di_tv, arena, true);
}
/// Sets a global (g:) variable.
@@ -689,7 +725,7 @@ Object nvim_get_var(String name, Error *err)
void nvim_set_var(String name, Object value, Error *err)
FUNC_API_SINCE(1)
{
- dict_set_var(&globvardict, name, value, false, false, err);
+ dict_set_var(&globvardict, name, value, false, false, NULL, err);
}
/// Removes a global (g:) variable.
@@ -699,7 +735,7 @@ void nvim_set_var(String name, Object value, Error *err)
void nvim_del_var(String name, Error *err)
FUNC_API_SINCE(1)
{
- dict_set_var(&globvardict, name, NIL, true, false, err);
+ dict_set_var(&globvardict, name, NIL, true, false, NULL, err);
}
/// Gets a v: variable.
@@ -707,10 +743,10 @@ void nvim_del_var(String name, Error *err)
/// @param name Variable name
/// @param[out] err Error details, if any
/// @return Variable value
-Object nvim_get_vvar(String name, Error *err)
+Object nvim_get_vvar(String name, Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
- return dict_get_value(&vimvardict, name, err);
+ return dict_get_value(&vimvardict, name, arena, err);
}
/// Sets a v: variable, if it is not readonly.
@@ -721,12 +757,12 @@ Object nvim_get_vvar(String name, Error *err)
void nvim_set_vvar(String name, Object value, Error *err)
FUNC_API_SINCE(6)
{
- dict_set_var(&vimvardict, name, value, false, false, err);
+ dict_set_var(&vimvardict, name, value, false, false, NULL, err);
}
/// Echo a message.
///
-/// @param chunks A list of [text, hl_group] arrays, each representing a
+/// @param chunks A list of `[text, hl_group]` arrays, each representing a
/// text chunk with specified highlight. `hl_group` element
/// can be omitted for no highlight.
/// @param history if true, add to |message-history|.
@@ -799,20 +835,19 @@ void nvim_err_writeln(String str)
/// Use |nvim_buf_is_loaded()| to check if a buffer is loaded.
///
/// @return List of buffer handles
-ArrayOf(Buffer) nvim_list_bufs(void)
+ArrayOf(Buffer) nvim_list_bufs(Arena *arena)
FUNC_API_SINCE(1)
{
- Array rv = ARRAY_DICT_INIT;
+ size_t n = 0;
FOR_ALL_BUFFERS(b) {
- rv.size++;
+ n++;
}
- rv.items = xmalloc(sizeof(Object) * rv.size);
- size_t i = 0;
+ Array rv = arena_array(arena, n);
FOR_ALL_BUFFERS(b) {
- rv.items[i++] = BUFFER_OBJ(b->handle);
+ ADD_C(rv, BUFFER_OBJ(b->handle));
}
return rv;
@@ -854,20 +889,19 @@ void nvim_set_current_buf(Buffer buffer, Error *err)
/// Gets the current list of window handles.
///
/// @return List of window handles
-ArrayOf(Window) nvim_list_wins(void)
+ArrayOf(Window) nvim_list_wins(Arena *arena)
FUNC_API_SINCE(1)
{
- Array rv = ARRAY_DICT_INIT;
+ size_t n = 0;
FOR_ALL_TAB_WINDOWS(tp, wp) {
- rv.size++;
+ n++;
}
- rv.items = xmalloc(sizeof(Object) * rv.size);
- size_t i = 0;
+ Array rv = arena_array(arena, n);
FOR_ALL_TAB_WINDOWS(tp, wp) {
- rv.items[i++] = WINDOW_OBJ(wp->handle);
+ ADD_C(rv, WINDOW_OBJ(wp->handle));
}
return rv;
@@ -949,8 +983,8 @@ Buffer nvim_create_buf(Boolean listed, Boolean scratch, Error *err)
buf_copy_options(buf, BCO_ENTER | BCO_NOHELP);
if (scratch) {
- set_string_option_direct_in_buf(buf, "bufhidden", -1, "hide", OPT_LOCAL, 0);
- set_string_option_direct_in_buf(buf, "buftype", -1, "nofile", OPT_LOCAL, 0);
+ set_string_option_direct_in_buf(buf, kOptBufhidden, "hide", OPT_LOCAL, 0);
+ set_string_option_direct_in_buf(buf, kOptBuftype, "nofile", OPT_LOCAL, 0);
assert(buf->b_ml.ml_mfp->mf_fd < 0); // ml_open() should not have opened swapfile already
buf->b_p_swf = false;
buf->b_p_ml = false;
@@ -985,10 +1019,11 @@ fail:
/// master end. For instance, a carriage return is sent
/// as a "\r", not as a "\n". |textlock| applies. It is possible
/// to call |nvim_chan_send()| directly in the callback however.
-/// ["input", term, bufnr, data]
+/// `["input", term, bufnr, data]`
+/// - force_crlf: (boolean, default true) Convert "\n" to "\r\n".
/// @param[out] err Error details, if any
/// @return Channel id, or 0 on error
-Integer nvim_open_term(Buffer buffer, DictionaryOf(LuaRef) opts, Error *err)
+Integer nvim_open_term(Buffer buffer, Dict(open_term) *opts, Error *err)
FUNC_API_SINCE(7)
FUNC_API_TEXTLOCK_ALLOW_CMDWIN
{
@@ -997,39 +1032,31 @@ Integer nvim_open_term(Buffer buffer, DictionaryOf(LuaRef) opts, Error *err)
return 0;
}
- if (cmdwin_type != 0 && buf == curbuf) {
+ if (buf == cmdwin_buf) {
api_set_error(err, kErrorTypeException, "%s", e_cmdwin);
return 0;
}
LuaRef cb = LUA_NOREF;
- for (size_t i = 0; i < opts.size; i++) {
- String k = opts.items[i].key;
- Object *v = &opts.items[i].value;
- if (strequal("on_input", k.data)) {
- VALIDATE_T("on_input", kObjectTypeLuaRef, v->type, {
- return 0;
- });
- cb = v->data.luaref;
- v->data.luaref = LUA_NOREF;
- break;
- } else {
- VALIDATE_S(false, "'opts' key", k.data, {});
- }
+ if (HAS_KEY(opts, open_term, on_input)) {
+ cb = opts->on_input;
+ opts->on_input = LUA_NOREF;
}
- TerminalOptions topts;
Channel *chan = channel_alloc(kChannelStreamInternal);
chan->stream.internal.cb = cb;
chan->stream.internal.closed = false;
- topts.data = chan;
- // NB: overridden in terminal_check_size if a window is already
- // displaying the buffer
- topts.width = (uint16_t)MAX(curwin->w_width_inner - win_col_off(curwin), 0);
- topts.height = (uint16_t)curwin->w_height_inner;
- topts.write_cb = term_write;
- topts.resize_cb = term_resize;
- topts.close_cb = term_close;
+ TerminalOptions topts = {
+ .data = chan,
+ // NB: overridden in terminal_check_size if a window is already
+ // displaying the buffer
+ .width = (uint16_t)MAX(curwin->w_width_inner - win_col_off(curwin), 0),
+ .height = (uint16_t)curwin->w_height_inner,
+ .write_cb = term_write,
+ .resize_cb = term_resize,
+ .close_cb = term_close,
+ .force_crlf = GET_BOOL_OR_TRUE(opts, open_term, force_crlf),
+ };
channel_incref(chan);
terminal_open(&chan->term, buf, topts);
if (chan->term != NULL) {
@@ -1039,7 +1066,7 @@ Integer nvim_open_term(Buffer buffer, DictionaryOf(LuaRef) opts, Error *err)
return (Integer)chan->id;
}
-static void term_write(char *buf, size_t size, void *data) // NOLINT(readability-non-const-parameter)
+static void term_write(const char *buf, size_t size, void *data)
{
Channel *chan = data;
LuaRef cb = chan->stream.internal.cb;
@@ -1049,9 +1076,9 @@ static void term_write(char *buf, size_t size, void *data) // NOLINT(readabilit
MAXSIZE_TEMP_ARRAY(args, 3);
ADD_C(args, INTEGER_OBJ((Integer)chan->id));
ADD_C(args, BUFFER_OBJ(terminal_buf(chan->term)));
- ADD_C(args, STRING_OBJ(((String){ .data = buf, .size = size })));
+ ADD_C(args, STRING_OBJ(((String){ .data = (char *)buf, .size = size })));
textlock++;
- nlua_call_ref(cb, "input", args, false, NULL);
+ nlua_call_ref(cb, "input", args, kRetNilBool, NULL, NULL);
textlock--;
}
@@ -1098,20 +1125,19 @@ void nvim_chan_send(Integer chan, String data, Error *err)
/// Gets the current list of tabpage handles.
///
/// @return List of tabpage handles
-ArrayOf(Tabpage) nvim_list_tabpages(void)
+ArrayOf(Tabpage) nvim_list_tabpages(Arena *arena)
FUNC_API_SINCE(1)
{
- Array rv = ARRAY_DICT_INIT;
+ size_t n = 0;
FOR_ALL_TABS(tp) {
- rv.size++;
+ n++;
}
- rv.items = xmalloc(sizeof(Object) * rv.size);
- size_t i = 0;
+ Array rv = arena_array(arena, n);
FOR_ALL_TABS(tp) {
- rv.items[i++] = TABPAGE_OBJ(tp->handle);
+ ADD_C(rv, TABPAGE_OBJ(tp->handle));
}
return rv;
@@ -1172,7 +1198,7 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err)
/// @return
/// - true: Client may continue pasting.
/// - false: Client must cancel the paste.
-Boolean nvim_paste(String data, Boolean crlf, Integer phase, Error *err)
+Boolean nvim_paste(String data, Boolean crlf, Integer phase, Arena *arena, Error *err)
FUNC_API_SINCE(6)
FUNC_API_TEXTLOCK_ALLOW_CMDWIN
{
@@ -1182,19 +1208,17 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Error *err)
VALIDATE_INT((phase >= -1 && phase <= 3), "phase", phase, {
return false;
});
- Array args = ARRAY_DICT_INIT;
- Object rv = OBJECT_INIT;
if (phase == -1 || phase == 1) { // Start of paste-stream.
draining = false;
} else if (draining) {
// Skip remaining chunks. Report error only once per "stream".
goto theend;
}
- Array lines = string_to_array(data, crlf);
- ADD(args, ARRAY_OBJ(lines));
- ADD(args, INTEGER_OBJ(phase));
- rv = nvim_exec_lua(STATIC_CSTR_AS_STRING("return vim.paste(...)"), args,
- err);
+ Array lines = string_to_array(data, crlf, arena);
+ MAXSIZE_TEMP_ARRAY(args, 2);
+ ADD_C(args, ARRAY_OBJ(lines));
+ ADD_C(args, INTEGER_OBJ(phase));
+ Object rv = NLUA_EXEC_STATIC("return vim.paste(...)", args, kRetNilBool, arena, err);
if (ERROR_SET(err)) {
draining = true;
goto theend;
@@ -1221,8 +1245,6 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Error *err)
AppendCharToRedobuff(ESC); // Dot-repeat.
}
theend:
- api_free_object(rv);
- api_free_array(args);
if (cancel || phase == -1 || phase == 3) { // End of paste-stream.
draining = false;
}
@@ -1243,24 +1265,27 @@ theend:
/// @param after If true insert after cursor (like |p|), or before (like |P|).
/// @param follow If true place cursor at end of inserted text.
/// @param[out] err Error details, if any
-void nvim_put(ArrayOf(String) lines, String type, Boolean after, Boolean follow, Error *err)
+void nvim_put(ArrayOf(String) lines, String type, Boolean after, Boolean follow, Arena *arena,
+ Error *err)
FUNC_API_SINCE(6)
FUNC_API_TEXTLOCK_ALLOW_CMDWIN
{
- yankreg_T *reg = xcalloc(1, sizeof(yankreg_T));
+ yankreg_T reg[1] = { 0 };
VALIDATE_S((prepare_yankreg_from_object(reg, type, lines.size)), "type", type.data, {
- goto cleanup;
+ return;
});
if (lines.size == 0) {
- goto cleanup; // Nothing to do.
+ return; // Nothing to do.
}
+ reg->y_array = arena_alloc(arena, lines.size * sizeof(uint8_t *), true);
+ reg->y_size = lines.size;
for (size_t i = 0; i < lines.size; i++) {
VALIDATE_T("line", kObjectTypeString, lines.items[i].type, {
- goto cleanup;
+ return;
});
String line = lines.items[i].data.string;
- reg->y_array[i] = xmemdupz(line.data, line.size);
+ reg->y_array[i] = arena_memdupz(arena, line.data, line.size);
memchrsub(reg->y_array[i], NUL, NL, line.size);
}
@@ -1273,10 +1298,6 @@ void nvim_put(ArrayOf(String) lines, String type, Boolean after, Boolean follow,
msg_silent--;
VIsual_active = VIsual_was_active;
});
-
-cleanup:
- free_register(reg);
- xfree(reg);
}
/// Subscribes to event broadcasts.
@@ -1334,14 +1355,13 @@ Integer nvim_get_color_by_name(String name)
/// (e.g. 65535).
///
/// @return Map of color names and RGB values.
-Dictionary nvim_get_color_map(void)
+Dictionary nvim_get_color_map(Arena *arena)
FUNC_API_SINCE(1)
{
- Dictionary colors = ARRAY_DICT_INIT;
+ Dictionary colors = arena_dict(arena, ARRAY_SIZE(color_name_table));
for (int i = 0; color_name_table[i].name != NULL; i++) {
- PUT(colors, color_name_table[i].name,
- INTEGER_OBJ(color_name_table[i].color));
+ PUT_C(colors, color_name_table[i].name, INTEGER_OBJ(color_name_table[i].color));
}
return colors;
}
@@ -1354,7 +1374,7 @@ Dictionary nvim_get_color_map(void)
/// @param[out] err Error details, if any
///
/// @return map of global |context|.
-Dictionary nvim_get_context(Dict(context) *opts, Error *err)
+Dictionary nvim_get_context(Dict(context) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(6)
{
Array types = ARRAY_DICT_INIT;
@@ -1390,7 +1410,7 @@ Dictionary nvim_get_context(Dict(context) *opts, Error *err)
Context ctx = CONTEXT_INIT;
ctx_save(&ctx, int_types);
- Dictionary dict = ctx_to_dict(&ctx);
+ Dictionary dict = ctx_to_dict(&ctx, arena);
ctx_free(&ctx);
return dict;
}
@@ -1421,16 +1441,16 @@ Object nvim_load_context(Dictionary dict, Error *err)
/// "blocking" is true if Nvim is waiting for input.
///
/// @returns Dictionary { "mode": String, "blocking": Boolean }
-Dictionary nvim_get_mode(void)
+Dictionary nvim_get_mode(Arena *arena)
FUNC_API_SINCE(2) FUNC_API_FAST
{
- Dictionary rv = ARRAY_DICT_INIT;
- char modestr[MODE_MAX_LENGTH];
+ Dictionary rv = arena_dict(arena, 2);
+ char *modestr = arena_alloc(arena, MODE_MAX_LENGTH, false);
get_mode(modestr);
bool blocked = input_blocking();
- PUT(rv, "mode", CSTR_TO_OBJ(modestr));
- PUT(rv, "blocking", BOOLEAN_OBJ(blocked));
+ PUT_C(rv, "mode", CSTR_AS_OBJ(modestr));
+ PUT_C(rv, "blocking", BOOLEAN_OBJ(blocked));
return rv;
}
@@ -1440,10 +1460,10 @@ Dictionary nvim_get_mode(void)
/// @param mode Mode short-name ("n", "i", "v", ...)
/// @returns Array of |maparg()|-like dictionaries describing mappings.
/// The "buffer" key is always zero.
-ArrayOf(Dictionary) nvim_get_keymap(String mode)
+ArrayOf(Dictionary) nvim_get_keymap(String mode, Arena *arena)
FUNC_API_SINCE(3)
{
- return keymap_array(mode, NULL);
+ return keymap_array(mode, NULL, arena);
}
/// Sets a global |mapping| for the given mode.
@@ -1451,7 +1471,7 @@ ArrayOf(Dictionary) nvim_get_keymap(String mode)
/// To set a buffer-local mapping, use |nvim_buf_set_keymap()|.
///
/// Unlike |:map|, leading/trailing whitespace is accepted as part of the {lhs} or {rhs}.
-/// Empty {rhs} is |<Nop>|. |keycodes| are replaced as usual.
+/// Empty {rhs} is [<Nop>]. |keycodes| are replaced as usual.
///
/// Example:
///
@@ -1471,7 +1491,7 @@ ArrayOf(Dictionary) nvim_get_keymap(String mode)
/// "ia", "ca" or "!a" for abbreviation in Insert mode, Cmdline mode, or both, respectively
/// @param lhs Left-hand-side |{lhs}| of the mapping.
/// @param rhs Right-hand-side |{rhs}| of the mapping.
-/// @param opts Optional parameters map: Accepts all |:map-arguments| as keys except |<buffer>|,
+/// @param opts Optional parameters map: Accepts all |:map-arguments| as keys except [<buffer>],
/// values are booleans (default false). Also:
/// - "noremap" disables |recursive_mapping|, like |:noremap|
/// - "desc" human-readable description.
@@ -1501,7 +1521,7 @@ void nvim_del_keymap(uint64_t channel_id, String mode, String lhs, Error *err)
/// Returns a 2-tuple (Array), where item 0 is the current channel id and item
/// 1 is the |api-metadata| map (Dictionary).
///
-/// @returns 2-tuple [{channel-id}, {api-metadata}]
+/// @returns 2-tuple `[{channel-id}, {api-metadata}]`
Array nvim_get_api_info(uint64_t channel_id, Arena *arena)
FUNC_API_SINCE(1) FUNC_API_FAST FUNC_API_REMOTE_ONLY
{
@@ -1509,7 +1529,7 @@ Array nvim_get_api_info(uint64_t channel_id, Arena *arena)
assert(channel_id <= INT64_MAX);
ADD_C(rv, INTEGER_OBJ((int64_t)channel_id));
- ADD_C(rv, DICTIONARY_OBJ(api_metadata()));
+ ADD_C(rv, api_metadata());
return rv;
}
@@ -1529,14 +1549,14 @@ Array nvim_get_api_info(uint64_t channel_id, Arena *arena)
/// @param channel_id
/// @param name Short name for the connected client
/// @param version Dictionary describing the version, with these
-/// (optional) keys:
+/// (optional) keys:
/// - "major" major version (defaults to 0 if not set, for no release yet)
/// - "minor" minor version
/// - "patch" patch number
/// - "prerelease" string describing a prerelease, like "dev" or "beta1"
/// - "commit" hash or similar identifier of commit
/// @param type Must be one of the following values. Client libraries should
-/// default to "remote" unless overridden by the user.
+/// default to "remote" unless overridden by the user.
/// - "remote" remote client connected "Nvim flavored" MessagePack-RPC (responses
/// must be in reverse order of requests). |msgpack-rpc|
/// - "msgpack-rpc" remote client connected to Nvim via fully MessagePack-RPC
@@ -1547,12 +1567,12 @@ Array nvim_get_api_info(uint64_t channel_id, Arena *arena)
/// - "host" plugin host, typically started by nvim
/// - "plugin" single plugin, started by nvim
/// @param methods Builtin methods in the client. For a host, this does not
-/// include plugin methods which will be discovered later.
-/// The key should be the method name, the values are dicts with
-/// these (optional) keys (more keys may be added in future
-/// versions of Nvim, thus unknown keys are ignored. Clients
-/// must only use keys defined in this or later versions of
-/// Nvim):
+/// include plugin methods which will be discovered later.
+/// The key should be the method name, the values are dicts with
+/// these (optional) keys (more keys may be added in future
+/// versions of Nvim, thus unknown keys are ignored. Clients
+/// must only use keys defined in this or later versions of
+/// Nvim):
/// - "async" if true, send as a notification. If false or unspecified,
/// use a blocking request
/// - "nargs" Number of arguments. Could be a single integer or an array
@@ -1567,13 +1587,12 @@ Array nvim_get_api_info(uint64_t channel_id, Arena *arena)
///
/// @param[out] err Error details, if any
void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version, String type,
- Dictionary methods, Dictionary attributes, Error *err)
+ Dictionary methods, Dictionary attributes, Arena *arena, Error *err)
FUNC_API_SINCE(4) FUNC_API_REMOTE_ONLY
{
- Dictionary info = ARRAY_DICT_INIT;
- PUT(info, "name", copy_object(STRING_OBJ(name), NULL));
+ MAXSIZE_TEMP_DICT(info, 5);
+ PUT_C(info, "name", STRING_OBJ(name));
- version = copy_dictionary(version, NULL);
bool has_major = false;
for (size_t i = 0; i < version.size; i++) {
if (strequal(version.items[i].key.data, "major")) {
@@ -1582,19 +1601,26 @@ void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version,
}
}
if (!has_major) {
- PUT(version, "major", INTEGER_OBJ(0));
+ Dictionary v = arena_dict(arena, version.size + 1);
+ if (version.size) {
+ memcpy(v.items, version.items, version.size * sizeof(v.items[0]));
+ v.size = version.size;
+ }
+ PUT_C(v, "major", INTEGER_OBJ(0));
+ version = v;
}
- PUT(info, "version", DICTIONARY_OBJ(version));
+ PUT_C(info, "version", DICTIONARY_OBJ(version));
- PUT(info, "type", copy_object(STRING_OBJ(type), NULL));
- PUT(info, "methods", DICTIONARY_OBJ(copy_dictionary(methods, NULL)));
- PUT(info, "attributes", DICTIONARY_OBJ(copy_dictionary(attributes, NULL)));
+ PUT_C(info, "type", STRING_OBJ(type));
+ PUT_C(info, "methods", DICTIONARY_OBJ(methods));
+ PUT_C(info, "attributes", DICTIONARY_OBJ(attributes));
- rpc_set_client_info(channel_id, info);
+ rpc_set_client_info(channel_id, copy_dictionary(info, NULL));
}
/// Gets information about a channel.
///
+/// @param chan channel_id, or 0 for current channel
/// @returns Dictionary describing a channel, with these keys:
/// - "id" Channel id.
/// - "argv" (optional) Job arguments list.
@@ -1616,23 +1642,28 @@ void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version,
/// the RPC channel), if provided by it via
/// |nvim_set_client_info()|.
///
-Dictionary nvim_get_chan_info(Integer chan, Error *err)
+Dictionary nvim_get_chan_info(uint64_t channel_id, Integer chan, Arena *arena, Error *err)
FUNC_API_SINCE(4)
{
if (chan < 0) {
return (Dictionary)ARRAY_DICT_INIT;
}
- return channel_info((uint64_t)chan);
+
+ if (chan == 0 && !is_internal_call(channel_id)) {
+ assert(channel_id <= INT64_MAX);
+ chan = (Integer)channel_id;
+ }
+ return channel_info((uint64_t)chan, arena);
}
/// Get information about all open channels.
///
/// @returns Array of Dictionaries, each describing a channel with
/// the format specified at |nvim_get_chan_info()|.
-Array nvim_list_chans(void)
+Array nvim_list_chans(Arena *arena)
FUNC_API_SINCE(4)
{
- return channel_all_info();
+ return channel_all_info(arena);
}
/// Calls many API methods atomically.
@@ -1698,7 +1729,7 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *er
// directly here. But `result` might become invalid when next api function
// is called in the loop.
ADD_C(results, copy_object(result, arena));
- if (!handler.arena_return) {
+ if (handler.ret_alloc) {
api_free_object(result);
}
}
@@ -1778,9 +1809,9 @@ static void write_msg(String message, bool to_err, bool writeln)
/// @param[in] obj Object to return.
///
/// @return its argument.
-Object nvim__id(Object obj)
+Object nvim__id(Object obj, Arena *arena)
{
- return copy_object(obj, NULL);
+ return copy_object(obj, arena);
}
/// Returns array given as argument.
@@ -1791,9 +1822,9 @@ Object nvim__id(Object obj)
/// @param[in] arr Array to return.
///
/// @return its argument.
-Array nvim__id_array(Array arr)
+Array nvim__id_array(Array arr, Arena *arena)
{
- return copy_array(arr, NULL);
+ return copy_array(arr, arena);
}
/// Returns dictionary given as argument.
@@ -1804,9 +1835,9 @@ Array nvim__id_array(Array arr)
/// @param[in] dct Dictionary to return.
///
/// @return its argument.
-Dictionary nvim__id_dictionary(Dictionary dct)
+Dictionary nvim__id_dictionary(Dictionary dct, Arena *arena)
{
- return copy_dictionary(dct, NULL);
+ return copy_dictionary(dct, arena);
}
/// Returns floating-point value given as argument.
@@ -1825,14 +1856,14 @@ Float nvim__id_float(Float flt)
/// Gets internal stats.
///
/// @return Map of various internal stats.
-Dictionary nvim__stats(void)
-{
- Dictionary rv = ARRAY_DICT_INIT;
- PUT(rv, "fsync", INTEGER_OBJ(g_stats.fsync));
- PUT(rv, "log_skip", INTEGER_OBJ(g_stats.log_skip));
- PUT(rv, "lua_refcount", INTEGER_OBJ(nlua_get_global_ref_count()));
- PUT(rv, "redraw", INTEGER_OBJ(g_stats.redraw));
- PUT(rv, "arena_alloc_count", INTEGER_OBJ((Integer)arena_alloc_count));
+Dictionary nvim__stats(Arena *arena)
+{
+ Dictionary rv = arena_dict(arena, 5);
+ PUT_C(rv, "fsync", INTEGER_OBJ(g_stats.fsync));
+ PUT_C(rv, "log_skip", INTEGER_OBJ(g_stats.log_skip));
+ PUT_C(rv, "lua_refcount", INTEGER_OBJ(nlua_get_global_ref_count()));
+ PUT_C(rv, "redraw", INTEGER_OBJ(g_stats.redraw));
+ PUT_C(rv, "arena_alloc_count", INTEGER_OBJ((Integer)arena_alloc_count));
return rv;
}
@@ -1844,16 +1875,16 @@ Dictionary nvim__stats(void)
/// - "rgb" true if the UI uses RGB colors (false implies |cterm-colors|)
/// - "ext_..." Requested UI extensions, see |ui-option|
/// - "chan" |channel-id| of remote UI
-Array nvim_list_uis(void)
+Array nvim_list_uis(Arena *arena)
FUNC_API_SINCE(4)
{
- return ui_array();
+ return ui_array(arena);
}
/// Gets the immediate children of process `pid`.
///
/// @return Array of child process ids, empty if process not found.
-Array nvim_get_proc_children(Integer pid, Error *err)
+Array nvim_get_proc_children(Integer pid, Arena *arena, Error *err)
FUNC_API_SINCE(4)
{
Array rvobj = ARRAY_DICT_INIT;
@@ -1869,8 +1900,8 @@ Array nvim_get_proc_children(Integer pid, Error *err)
// syscall failed (possibly because of kernel options), try shelling out.
DLOG("fallback to vim._os_proc_children()");
MAXSIZE_TEMP_ARRAY(a, 1);
- ADD(a, INTEGER_OBJ(pid));
- Object o = NLUA_EXEC_STATIC("return vim._os_proc_children(...)", a, err);
+ ADD_C(a, INTEGER_OBJ(pid));
+ Object o = NLUA_EXEC_STATIC("return vim._os_proc_children(...)", a, kRetObject, arena, err);
if (o.type == kObjectTypeArray) {
rvobj = o.data.array;
} else if (!ERROR_SET(err)) {
@@ -1878,11 +1909,11 @@ Array nvim_get_proc_children(Integer pid, Error *err)
"Failed to get process children. pid=%" PRId64 " error=%d",
pid, rv);
}
- goto end;
- }
-
- for (size_t i = 0; i < proc_count; i++) {
- ADD(rvobj, INTEGER_OBJ(proc_list[i]));
+ } else {
+ rvobj = arena_array(arena, proc_count);
+ for (size_t i = 0; i < proc_count; i++) {
+ ADD_C(rvobj, INTEGER_OBJ(proc_list[i]));
+ }
}
end:
@@ -1893,19 +1924,17 @@ end:
/// Gets info describing process `pid`.
///
/// @return Map of process properties, or NIL if process not found.
-Object nvim_get_proc(Integer pid, Error *err)
+Object nvim_get_proc(Integer pid, Arena *arena, Error *err)
FUNC_API_SINCE(4)
{
- Object rvobj = OBJECT_INIT;
- rvobj.data.dictionary = (Dictionary)ARRAY_DICT_INIT;
- rvobj.type = kObjectTypeDictionary;
+ Object rvobj = NIL;
VALIDATE_INT((pid > 0 && pid <= INT_MAX), "pid", pid, {
return NIL;
});
#ifdef MSWIN
- rvobj.data.dictionary = os_proc_info((int)pid);
+ rvobj = DICTIONARY_OBJ(os_proc_info((int)pid, arena));
if (rvobj.data.dictionary.size == 0) { // Process not found.
return NIL;
}
@@ -1913,11 +1942,11 @@ Object nvim_get_proc(Integer pid, Error *err)
// Cross-platform process info APIs are miserable, so use `ps` instead.
MAXSIZE_TEMP_ARRAY(a, 1);
ADD(a, INTEGER_OBJ(pid));
- Object o = NLUA_EXEC_STATIC("return vim._os_proc_info(...)", a, err);
+ Object o = NLUA_EXEC_STATIC("return vim._os_proc_info(...)", a, kRetObject, arena, err);
if (o.type == kObjectTypeArray && o.data.array.size == 0) {
return NIL; // Process not found.
} else if (o.type == kObjectTypeDictionary) {
- rvobj.data.dictionary = o.data.dictionary;
+ rvobj = o;
} else if (!ERROR_SET(err)) {
api_set_error(err, kErrorTypeException,
"Failed to get process info. pid=%" PRId64, pid);
@@ -1931,7 +1960,7 @@ Object nvim_get_proc(Integer pid, Error *err)
/// If neither |ins-completion| nor |cmdline-completion| popup menu is active
/// this API call is silently ignored.
/// Useful for an external UI using |ui-popupmenu| to control the popup menu with the mouse.
-/// Can also be used in a mapping; use <Cmd> |:map-cmd| or a Lua mapping to ensure the mapping
+/// Can also be used in a mapping; use [<Cmd>] |:map-cmd| or a Lua mapping to ensure the mapping
/// doesn't end completion mode.
///
/// @param item Index (zero-based) of the item to select. Value of -1 selects nothing
@@ -1941,14 +1970,10 @@ Object nvim_get_proc(Integer pid, Error *err)
/// @param finish Finish the completion and dismiss the popup menu. Implies {insert}.
/// @param opts Optional parameters. Reserved for future use.
/// @param[out] err Error details, if any
-void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish, Dictionary opts,
+void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish, Dict(empty) *opts,
Error *err)
FUNC_API_SINCE(6)
{
- VALIDATE((opts.size == 0), "%s", "opts dict isn't empty", {
- return;
- });
-
if (finish) {
insert = true;
}
@@ -1956,7 +1981,7 @@ void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish, Di
pum_ext_select_item((int)item, insert, finish);
}
-/// NB: if your UI doesn't use hlstate, this will not return hlstate first time
+/// NB: if your UI doesn't use hlstate, this will not return hlstate first time.
Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Arena *arena, Error *err)
{
Array ret = ARRAY_DICT_INIT;
@@ -1987,11 +2012,12 @@ Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Arena *arena, E
ADD_C(ret, DICTIONARY_OBJ(hl_get_attr_by_id(attr, true, arena, err)));
// will not work first time
if (!highlight_use_hlstate()) {
- ADD_C(ret, ARRAY_OBJ(hl_inspect(attr)));
+ ADD_C(ret, ARRAY_OBJ(hl_inspect(attr, arena)));
}
return ret;
}
+/// @nodoc
void nvim__screenshot(String path)
FUNC_API_FAST
{
@@ -2006,10 +2032,11 @@ void nvim__invalidate_glyph_cache(void)
must_redraw = UPD_CLEAR;
}
-Object nvim__unpack(String str, Error *err)
+/// @nodoc
+Object nvim__unpack(String str, Arena *arena, Error *err)
FUNC_API_FAST
{
- return unpack(str.data, str.size, err);
+ return unpack(str.data, str.size, arena, err);
}
/// Deletes an uppercase/file named mark. See |mark-motions|.
@@ -2049,7 +2076,7 @@ Boolean nvim_del_mark(String name, Error *err)
/// not set.
/// @see |nvim_buf_set_mark()|
/// @see |nvim_del_mark()|
-Array nvim_get_mark(String name, Dictionary opts, Error *err)
+Array nvim_get_mark(String name, Dict(empty) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(8)
{
Array rv = ARRAY_DICT_INIT;
@@ -2097,10 +2124,11 @@ Array nvim_get_mark(String name, Dictionary opts, Error *err)
col = pos.col;
}
- ADD(rv, INTEGER_OBJ(row));
- ADD(rv, INTEGER_OBJ(col));
- ADD(rv, INTEGER_OBJ(bufnr));
- ADD(rv, CSTR_TO_OBJ(filename));
+ rv = arena_array(arena, 4);
+ ADD_C(rv, INTEGER_OBJ(row));
+ ADD_C(rv, INTEGER_OBJ(col));
+ ADD_C(rv, INTEGER_OBJ(bufnr));
+ ADD_C(rv, CSTR_TO_ARENA_OBJ(arena, filename));
if (allocated) {
xfree(filename);
@@ -2132,15 +2160,14 @@ Array nvim_get_mark(String name, Dictionary opts, Error *err)
/// |Dictionary| with these keys:
/// - start: (number) Byte index (0-based) of first character that uses the highlight.
/// - group: (string) Name of highlight group.
-Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *err)
+Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(8) FUNC_API_FAST
{
Dictionary result = ARRAY_DICT_INIT;
int maxwidth;
- int fillchar = 0;
+ schar_T fillchar = 0;
int statuscol_lnum = 0;
- Window window = 0;
if (str.size < 2 || memcmp(str.data, "%!", 2) != 0) {
const char *const errmsg = check_stl_option(str.data);
@@ -2149,16 +2176,17 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
});
}
- if (HAS_KEY(opts, eval_statusline, winid)) {
- window = opts->winid;
- }
+ Window window = opts->winid;
+
if (HAS_KEY(opts, eval_statusline, fillchar)) {
VALIDATE_EXP((*opts->fillchar.data != 0
- && ((size_t)utf_ptr2len(opts->fillchar.data) == opts->fillchar.size)),
+ && ((size_t)utfc_ptr2len(opts->fillchar.data) == opts->fillchar.size)),
"fillchar", "single character", NULL, {
return result;
});
- fillchar = utf_ptr2char(opts->fillchar.data);
+ int c;
+ fillchar = utfc_ptr2schar(opts->fillchar.data, &c);
+ // TODO(bfredl): actually check c is single width
}
int use_bools = (int)opts->use_winbar + (int)opts->use_tabline;
@@ -2186,50 +2214,44 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
statuscol_T statuscol = { 0 };
SignTextAttrs sattrs[SIGN_SHOW_MAX] = { 0 };
- if (opts->use_tabline) {
- fillchar = ' ';
- } else {
- if (fillchar == 0) {
- if (opts->use_winbar) {
- fillchar = wp->w_p_fcs_chars.wbr;
- } else {
- int attr;
- fillchar = fillchar_status(&attr, wp);
+ if (statuscol_lnum) {
+ int line_id = 0;
+ int cul_id = 0;
+ int num_id = 0;
+ linenr_T lnum = statuscol_lnum;
+ decor_redraw_signs(wp, wp->w_buffer, lnum - 1, sattrs, &line_id, &cul_id, &num_id);
+
+ statuscol.sattrs = sattrs;
+ statuscol.foldinfo = fold_info(wp, lnum);
+ wp->w_cursorline = win_cursorline_standout(wp) ? wp->w_cursor.lnum : 0;
+
+ if (wp->w_p_cul) {
+ if (statuscol.foldinfo.fi_level != 0 && statuscol.foldinfo.fi_lines > 0) {
+ wp->w_cursorline = statuscol.foldinfo.fi_lnum;
}
+ statuscol.use_cul = lnum == wp->w_cursorline && (wp->w_p_culopt_flags & CULOPT_NBR);
}
- if (statuscol_lnum) {
- int line_id = 0;
- int cul_id = 0;
- int num_id = 0;
- linenr_T lnum = statuscol_lnum;
- wp->w_scwidth = win_signcol_count(wp);
- decor_redraw_signs(wp, wp->w_buffer, lnum - 1, sattrs, &line_id, &cul_id, &num_id);
-
- statuscol.sattrs = sattrs;
- statuscol.foldinfo = fold_info(wp, lnum);
- wp->w_cursorline = win_cursorline_standout(wp) ? wp->w_cursor.lnum : 0;
-
- if (wp->w_p_cul) {
- if (statuscol.foldinfo.fi_level != 0 && statuscol.foldinfo.fi_lines > 0) {
- wp->w_cursorline = statuscol.foldinfo.fi_lnum;
- }
- statuscol.use_cul = lnum == wp->w_cursorline && (wp->w_p_culopt_flags & CULOPT_NBR);
- }
- statuscol.sign_cul_id = statuscol.use_cul ? cul_id : 0;
- if (num_id) {
- stc_hl_id = num_id;
- } else if (statuscol.use_cul) {
- stc_hl_id = HLF_CLN + 1;
- } else if (wp->w_p_rnu) {
- stc_hl_id = (lnum < wp->w_cursor.lnum ? HLF_LNA : HLF_LNB) + 1;
- } else {
- stc_hl_id = HLF_N + 1;
- }
+ statuscol.sign_cul_id = statuscol.use_cul ? cul_id : 0;
+ if (num_id) {
+ stc_hl_id = num_id;
+ } else if (statuscol.use_cul) {
+ stc_hl_id = HLF_CLN + 1;
+ } else if (wp->w_p_rnu) {
+ stc_hl_id = (lnum < wp->w_cursor.lnum ? HLF_LNA : HLF_LNB) + 1;
+ } else {
+ stc_hl_id = HLF_N + 1;
+ }
- set_vim_var_nr(VV_LNUM, lnum);
- set_vim_var_nr(VV_RELNUM, labs(get_cursor_rel_lnum(wp, lnum)));
- set_vim_var_nr(VV_VIRTNUM, 0);
+ set_vim_var_nr(VV_LNUM, lnum);
+ set_vim_var_nr(VV_RELNUM, labs(get_cursor_rel_lnum(wp, lnum)));
+ set_vim_var_nr(VV_VIRTNUM, 0);
+ } else if (fillchar == 0 && !opts->use_tabline) {
+ if (opts->use_winbar) {
+ fillchar = wp->w_p_fcs_chars.wbr;
+ } else {
+ int attr;
+ fillchar = fillchar_status(&attr, wp);
}
}
@@ -2242,70 +2264,66 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
&& global_stl_height() > 0)) ? Columns : wp->w_width;
}
- char buf[MAXPATHL];
+ result = arena_dict(arena, 3);
+ char *buf = arena_alloc(arena, MAXPATHL, false);
stl_hlrec_t *hltab;
+ size_t hltab_len = 0;
// Temporarily reset 'cursorbind' to prevent side effects from moving the cursor away and back.
int p_crb_save = wp->w_p_crb;
wp->w_p_crb = false;
- int width = build_stl_str_hl(wp,
- buf,
- sizeof(buf),
- str.data,
- NULL,
- 0,
- fillchar,
- maxwidth,
- opts->highlights ? &hltab : NULL,
- NULL,
+ int width = build_stl_str_hl(wp, buf, MAXPATHL, str.data, -1, 0, fillchar, maxwidth,
+ opts->highlights ? &hltab : NULL, &hltab_len, NULL,
statuscol_lnum ? &statuscol : NULL);
- PUT(result, "width", INTEGER_OBJ(width));
+ PUT_C(result, "width", INTEGER_OBJ(width));
// Restore original value of 'cursorbind'
wp->w_p_crb = p_crb_save;
if (opts->highlights) {
- Array hl_values = ARRAY_DICT_INIT;
- const char *grpname;
+ Array hl_values = arena_array(arena, hltab_len + 1);
char user_group[15]; // strlen("User") + strlen("2147483647") + NUL
// If first character doesn't have a defined highlight,
// add the default highlight at the beginning of the highlight list
if (hltab->start == NULL || (hltab->start - buf) != 0) {
- Dictionary hl_info = ARRAY_DICT_INIT;
- grpname = get_default_stl_hl(opts->use_tabline ? NULL : wp, opts->use_winbar, stc_hl_id);
+ Dictionary hl_info = arena_dict(arena, 2);
+ const char *grpname = get_default_stl_hl(opts->use_tabline ? NULL : wp,
+ opts->use_winbar, stc_hl_id);
- PUT(hl_info, "start", INTEGER_OBJ(0));
- PUT(hl_info, "group", CSTR_TO_OBJ(grpname));
+ PUT_C(hl_info, "start", INTEGER_OBJ(0));
+ PUT_C(hl_info, "group", CSTR_AS_OBJ(grpname));
- ADD(hl_values, DICTIONARY_OBJ(hl_info));
+ ADD_C(hl_values, DICTIONARY_OBJ(hl_info));
}
for (stl_hlrec_t *sp = hltab; sp->start != NULL; sp++) {
- Dictionary hl_info = ARRAY_DICT_INIT;
+ Dictionary hl_info = arena_dict(arena, 2);
- PUT(hl_info, "start", INTEGER_OBJ(sp->start - buf));
+ PUT_C(hl_info, "start", INTEGER_OBJ(sp->start - buf));
+ const char *grpname;
if (sp->userhl == 0) {
grpname = get_default_stl_hl(opts->use_tabline ? NULL : wp, opts->use_winbar, stc_hl_id);
} else if (sp->userhl < 0) {
grpname = syn_id2name(-sp->userhl);
} else {
snprintf(user_group, sizeof(user_group), "User%d", sp->userhl);
- grpname = user_group;
+ grpname = arena_memdupz(arena, user_group, strlen(user_group));
}
- PUT(hl_info, "group", CSTR_TO_OBJ(grpname));
- ADD(hl_values, DICTIONARY_OBJ(hl_info));
+ PUT_C(hl_info, "group", CSTR_AS_OBJ(grpname));
+ ADD_C(hl_values, DICTIONARY_OBJ(hl_info));
}
- PUT(result, "highlights", ARRAY_OBJ(hl_values));
+ PUT_C(result, "highlights", ARRAY_OBJ(hl_values));
}
- PUT(result, "str", CSTR_TO_OBJ(buf));
+ PUT_C(result, "str", CSTR_AS_OBJ(buf));
return result;
}
+/// @nodoc
void nvim_error_event(uint64_t channel_id, Integer lvl, String data)
FUNC_API_REMOTE_ONLY
{
@@ -2313,3 +2331,29 @@ void nvim_error_event(uint64_t channel_id, Integer lvl, String data)
// if we fork nvim processes as async workers
ELOG("async error on channel %" PRId64 ": %s", channel_id, data.size ? data.data : "");
}
+
+/// Set info for the completion candidate index.
+/// if the info was shown in a window, then the
+/// window and buffer ids are returned for further
+/// customization. If the text was not shown, an
+/// empty dict is returned.
+///
+/// @param index the completion candidate index
+/// @param opts Optional parameters.
+/// - info: (string) info text.
+/// @return Dictionary containing these keys:
+/// - winid: (number) floating window id
+/// - bufnr: (number) buffer id in floating window
+Dictionary nvim_complete_set(Integer index, Dict(complete_set) *opts, Arena *arena)
+ FUNC_API_SINCE(12)
+{
+ Dictionary rv = arena_dict(arena, 2);
+ if (HAS_KEY(opts, complete_set, info)) {
+ win_T *wp = pum_set_info((int)index, opts->info.data);
+ if (wp) {
+ PUT_C(rv, "winid", WINDOW_OBJ(wp->handle));
+ PUT_C(rv, "bufnr", BUFFER_OBJ(wp->w_buffer->handle));
+ }
+ }
+ return rv;
+}