aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2024-05-24 19:18:11 +0000
committerJosh Rahm <joshuarahm@gmail.com>2024-05-24 19:18:11 +0000
commitff7ed8f586589d620a806c3758fac4a47a8e7e15 (patch)
tree729bbcb92231538fa61dab6c3d890b025484b7f5 /src/nvim/api
parent376914f419eb08fdf4c1a63a77e1f035898a0f10 (diff)
parent28c04948a1c887a1cc0cb64de79fa32631700466 (diff)
downloadrneovim-ff7ed8f586589d620a806c3758fac4a47a8e7e15.tar.gz
rneovim-ff7ed8f586589d620a806c3758fac4a47a8e7e15.tar.bz2
rneovim-ff7ed8f586589d620a806c3758fac4a47a8e7e15.zip
Merge remote-tracking branch 'upstream/master' into mix_20240309
Diffstat (limited to 'src/nvim/api')
-rw-r--r--src/nvim/api/autocmd.c6
-rw-r--r--src/nvim/api/buffer.c68
-rw-r--r--src/nvim/api/deprecated.c109
-rw-r--r--src/nvim/api/extmark.c80
-rw-r--r--src/nvim/api/keysets_defs.h16
-rw-r--r--src/nvim/api/private/converter.c3
-rw-r--r--src/nvim/api/private/helpers.c8
-rw-r--r--src/nvim/api/tabpage.c6
-rw-r--r--src/nvim/api/ui.c61
-rw-r--r--src/nvim/api/ui_events.in.h4
-rw-r--r--src/nvim/api/vim.c355
-rw-r--r--src/nvim/api/win_config.c363
-rw-r--r--src/nvim/api/window.c12
13 files changed, 704 insertions, 387 deletions
diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c
index d71bcc4bcf..ca8367b7ce 100644
--- a/src/nvim/api/autocmd.c
+++ b/src/nvim/api/autocmd.c
@@ -381,15 +381,15 @@ cleanup:
/// - 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 a truthy
-/// value (not `false` or `nil`) to delete the autocommand. Receives a table argument
-/// with these keys:
+/// value (not `false` or `nil`) to delete the autocommand. Receives one argument,
+/// a table with these keys: [event-args]()
/// - 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()]
+/// - data: (any) arbitrary data passed from [nvim_exec_autocmds()] [event-data]()
/// - command (string) optional: Vim command to execute on event. Cannot be used with
/// {callback}
/// - once (boolean) optional: defaults to false. Run the autocommand
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 7f195de959..7e64808709 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -39,6 +39,7 @@
#include "nvim/memory_defs.h"
#include "nvim/move.h"
#include "nvim/ops.h"
+#include "nvim/option_vars.h"
#include "nvim/pos_defs.h"
#include "nvim/state_defs.h"
#include "nvim/types_defs.h"
@@ -229,20 +230,6 @@ Boolean nvim_buf_detach(uint64_t channel_id, Buffer buffer, Error *err)
return true;
}
-/// @nodoc
-void nvim__buf_redraw_range(Buffer buffer, Integer first, Integer last, Error *err)
-{
- buf_T *buf = find_buffer_by_handle(buffer, err);
- if (!buf) {
- return;
- }
- if (last < 0) {
- last = buf->b_ml.ml_line_count;
- }
-
- redraw_buf_range_later(buf, (linenr_T)first + 1, (linenr_T)last);
-}
-
/// Gets a line-range from the buffer.
///
/// Indexing is zero-based, end-exclusive. Negative indices are interpreted
@@ -529,18 +516,18 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In
// Another call to ml_get_buf() may free the lines, so we make copies
char *str_at_start = ml_get_buf(buf, (linenr_T)start_row);
- size_t len_at_start = strlen(str_at_start);
- str_at_start = arena_memdupz(arena, str_at_start, len_at_start);
- start_col = start_col < 0 ? (int64_t)len_at_start + start_col + 1 : start_col;
- VALIDATE_RANGE((start_col >= 0 && (size_t)start_col <= len_at_start), "start_col", {
+ colnr_T len_at_start = ml_get_buf_len(buf, (linenr_T)start_row);
+ str_at_start = arena_memdupz(arena, str_at_start, (size_t)len_at_start);
+ start_col = start_col < 0 ? len_at_start + start_col + 1 : start_col;
+ VALIDATE_RANGE((start_col >= 0 && start_col <= len_at_start), "start_col", {
return;
});
char *str_at_end = ml_get_buf(buf, (linenr_T)end_row);
- size_t len_at_end = strlen(str_at_end);
- str_at_end = arena_memdupz(arena, str_at_end, len_at_end);
- end_col = end_col < 0 ? (int64_t)len_at_end + end_col + 1 : end_col;
- VALIDATE_RANGE((end_col >= 0 && (size_t)end_col <= len_at_end), "end_col", {
+ colnr_T len_at_end = ml_get_buf_len(buf, (linenr_T)end_row);
+ str_at_end = arena_memdupz(arena, str_at_end, (size_t)len_at_end);
+ end_col = end_col < 0 ? len_at_end + end_col + 1 : end_col;
+ VALIDATE_RANGE((end_col >= 0 && end_col <= len_at_end), "end_col", {
return;
});
@@ -563,12 +550,10 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In
if (start_row == end_row) {
old_byte = (bcount_t)end_col - start_col;
} else {
- old_byte += (bcount_t)len_at_start - start_col;
+ old_byte += len_at_start - start_col;
for (int64_t i = 1; i < end_row - start_row; i++) {
int64_t lnum = start_row + i;
-
- const char *bufline = ml_get_buf(buf, (linenr_T)lnum);
- old_byte += (bcount_t)(strlen(bufline)) + 1;
+ old_byte += ml_get_buf_len(buf, (linenr_T)lnum) + 1;
}
old_byte += (bcount_t)end_col + 1;
}
@@ -577,7 +562,7 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In
String last_item = replacement.items[replacement.size - 1].data.string;
size_t firstlen = (size_t)start_col + first_item.size;
- size_t last_part_len = len_at_end - (size_t)end_col;
+ size_t last_part_len = (size_t)len_at_end - (size_t)end_col;
if (replacement.size == 1) {
firstlen += last_part_len;
}
@@ -970,7 +955,7 @@ String nvim_buf_get_name(Buffer buffer, Error *err)
return cstr_as_string(buf->b_ffname);
}
-/// Sets the full file name for a buffer
+/// Sets the full file name for a buffer, like |:file_f|
///
/// @param buffer Buffer handle, or 0 for current buffer
/// @param name Buffer name
@@ -986,12 +971,23 @@ void nvim_buf_set_name(Buffer buffer, String name, Error *err)
try_start();
+ const bool is_curbuf = buf == curbuf;
+ const int save_acd = p_acd;
+ if (!is_curbuf) {
+ // Temporarily disable 'autochdir' when setting file name for another buffer.
+ p_acd = false;
+ }
+
// Using aucmd_*: autocommands will be executed by rename_buffer
aco_save_T aco;
aucmd_prepbuf(&aco, buf);
int ren_ret = rename_buffer(name.data);
aucmd_restbuf(&aco);
+ if (!is_curbuf) {
+ p_acd = save_acd;
+ }
+
if (try_end(err)) {
return;
}
@@ -1271,10 +1267,13 @@ static void fix_cursor(win_T *win, linenr_T lo, linenr_T hi, linenr_T extra)
} else if (extra < 0) {
check_cursor_lnum(win);
}
- check_cursor_col_win(win);
+ check_cursor_col(win);
changed_cline_bef_curs(win);
+ win->w_valid &= ~(VALID_BOTLINE_AP);
+ update_topline(win);
+ } else {
+ invalidate_botline(win);
}
- invalidate_botline(win);
}
/// Fix cursor position after replacing text
@@ -1309,7 +1308,7 @@ static void fix_cursor_cols(win_T *win, linenr_T start_row, colnr_T start_col, l
// it's easier to work with a single value here.
// col and coladd are fixed by a later call
- // to check_cursor_col_win when necessary
+ // to check_cursor_col when necessary
win->w_cursor.col += win->w_cursor.coladd;
win->w_cursor.coladd = 0;
@@ -1324,7 +1323,7 @@ static void fix_cursor_cols(win_T *win, linenr_T start_row, colnr_T start_col, l
// it already (in case virtualedit is active)
// column might be additionally adjusted below
// to keep it inside col range if needed
- colnr_T len = (colnr_T)strlen(ml_get_buf(win->w_buffer, new_end_row));
+ colnr_T len = ml_get_buf_len(win->w_buffer, new_end_row);
if (win->w_cursor.col < len) {
win->w_cursor.col = len;
}
@@ -1345,7 +1344,7 @@ static void fix_cursor_cols(win_T *win, linenr_T start_row, colnr_T start_col, l
}
}
- check_cursor_col_win(win);
+ check_cursor_col(win);
changed_cline_bef_curs(win);
invalidate_botline(win);
}
@@ -1424,6 +1423,7 @@ void buf_collect_lines(buf_T *buf, size_t n, linenr_T start, int start_idx, bool
for (size_t i = 0; i < n; i++) {
linenr_T lnum = start + (linenr_T)i;
char *bufstr = ml_get_buf(buf, lnum);
- push_linestr(lstate, l, bufstr, strlen(bufstr), start_idx + (int)i, replace_nl, arena);
+ size_t bufstrlen = (size_t)ml_get_buf_len(buf, lnum);
+ push_linestr(lstate, l, bufstr, bufstrlen, start_idx + (int)i, replace_nl, arena);
}
}
diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c
index 6254e9fbd8..af3bfe2c03 100644
--- a/src/nvim/api/deprecated.c
+++ b/src/nvim/api/deprecated.c
@@ -20,6 +20,9 @@
#include "nvim/lua/executor.h"
#include "nvim/memory.h"
#include "nvim/memory_defs.h"
+#include "nvim/msgpack_rpc/channel.h"
+#include "nvim/msgpack_rpc/channel_defs.h"
+#include "nvim/msgpack_rpc/unpacker.h"
#include "nvim/option.h"
#include "nvim/option_defs.h"
#include "nvim/pos_defs.h"
@@ -697,3 +700,109 @@ static void set_option_to(uint64_t channel_id, void *to, OptReqScope req_scope,
set_option_value_for(name.data, opt_idx, optval, opt_flags, req_scope, to, err);
});
}
+
+/// @deprecated Use nvim_exec_lua() instead.
+///
+/// Calls many API methods atomically.
+///
+/// This has two main usages:
+/// 1. To perform several requests from an async context atomically, i.e.
+/// without interleaving redraws, RPC requests from other clients, or user
+/// interactions (however API methods may trigger autocommands or event
+/// processing which have such side effects, e.g. |:sleep| may wake timers).
+/// 2. To minimize RPC overhead (roundtrips) of a sequence of many requests.
+///
+/// @param channel_id
+/// @param calls an array of calls, where each call is described by an array
+/// with two elements: the request name, and an array of arguments.
+/// @param[out] err Validation error details (malformed `calls` parameter),
+/// if any. Errors from batched calls are given in the return value.
+///
+/// @return Array of two elements. The first is an array of return
+/// values. The second is NIL if all calls succeeded. If a call resulted in
+/// an error, it is a three-element array with the zero-based index of the call
+/// which resulted in an error, the error type and the error message. If an
+/// error occurred, the values from all preceding calls will still be returned.
+Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *err)
+ FUNC_API_SINCE(1) FUNC_API_DEPRECATED_SINCE(12) FUNC_API_REMOTE_ONLY
+{
+ Array rv = arena_array(arena, 2);
+ Array results = arena_array(arena, calls.size);
+ Error nested_error = ERROR_INIT;
+
+ size_t i; // also used for freeing the variables
+ for (i = 0; i < calls.size; i++) {
+ VALIDATE_T("'calls' item", kObjectTypeArray, calls.items[i].type, {
+ goto theend;
+ });
+ Array call = calls.items[i].data.array;
+ VALIDATE_EXP((call.size == 2), "'calls' item", "2-item Array", NULL, {
+ goto theend;
+ });
+ VALIDATE_T("name", kObjectTypeString, call.items[0].type, {
+ goto theend;
+ });
+ String name = call.items[0].data.string;
+ VALIDATE_T("call args", kObjectTypeArray, call.items[1].type, {
+ goto theend;
+ });
+ Array args = call.items[1].data.array;
+
+ MsgpackRpcRequestHandler handler =
+ msgpack_rpc_get_handler_for(name.data,
+ name.size,
+ &nested_error);
+
+ if (ERROR_SET(&nested_error)) {
+ break;
+ }
+
+ Object result = handler.fn(channel_id, args, arena, &nested_error);
+ if (ERROR_SET(&nested_error)) {
+ // error handled after loop
+ break;
+ }
+ // TODO(bfredl): wasteful copy. It could be avoided to encoding to msgpack
+ // 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.ret_alloc) {
+ api_free_object(result);
+ }
+ }
+
+ ADD_C(rv, ARRAY_OBJ(results));
+ if (ERROR_SET(&nested_error)) {
+ Array errval = arena_array(arena, 3);
+ ADD_C(errval, INTEGER_OBJ((Integer)i));
+ ADD_C(errval, INTEGER_OBJ(nested_error.type));
+ ADD_C(errval, STRING_OBJ(copy_string(cstr_as_string(nested_error.msg), arena)));
+ ADD_C(rv, ARRAY_OBJ(errval));
+ } else {
+ ADD_C(rv, NIL);
+ }
+
+theend:
+ api_clear_error(&nested_error);
+ return rv;
+}
+
+/// @deprecated
+///
+/// @param channel_id Channel id (passed automatically by the dispatcher)
+/// @param event Event type string
+void nvim_subscribe(uint64_t channel_id, String event)
+ FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
+{
+ // Does nothing. `rpcnotify(0,…)` broadcasts to all channels, there are no "subscriptions".
+}
+
+/// @deprecated
+///
+/// @param channel_id Channel id (passed automatically by the dispatcher)
+/// @param event Event type string
+void nvim_unsubscribe(uint64_t channel_id, String event)
+ FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
+{
+ // Does nothing. `rpcnotify(0,…)` broadcasts to all channels, there are no "subscriptions".
+}
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index 1b03a97edb..85cce45560 100644
--- a/src/nvim/api/extmark.c
+++ b/src/nvim/api/extmark.c
@@ -121,7 +121,7 @@ Array virt_text_to_array(VirtText vt, bool hl_name, Arena *arena)
Array hl_array = arena_array(arena, i < j ? j - i + 1 : 0);
for (; i < j; i++) {
int hl_id = kv_A(vt, i).hl_id;
- if (hl_id > 0) {
+ if (hl_id >= 0) {
ADD_C(hl_array, hl_group_name(hl_id, hl_name));
}
}
@@ -131,11 +131,11 @@ Array virt_text_to_array(VirtText vt, bool hl_name, Arena *arena)
Array chunk = arena_array(arena, 2);
ADD_C(chunk, CSTR_AS_OBJ(text));
if (hl_array.size > 0) {
- if (hl_id > 0) {
+ if (hl_id >= 0) {
ADD_C(hl_array, hl_group_name(hl_id, hl_name));
}
ADD_C(chunk, ARRAY_OBJ(hl_array));
- } else if (hl_id > 0) {
+ } else if (hl_id >= 0) {
ADD_C(chunk, hl_group_name(hl_id, hl_name));
}
ADD_C(chunks, ARRAY_OBJ(chunk));
@@ -489,8 +489,8 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
/// used together with virt_text.
/// - url: A URL to associate with this extmark. In the TUI, the OSC 8 control
/// sequence is used to generate a clickable hyperlink to this URL.
-/// - scoped: boolean that indicates that the extmark should only be
-/// displayed in the namespace scope. (experimental)
+/// - scoped: boolean (EXPERIMENTAL) enables "scoping" for the extmark. See
+/// |nvim__win_add_ns()|
///
/// @param[out] err Error details, if any
/// @return Id of the created/updated extmark
@@ -682,7 +682,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
goto error;
});
- size_t len = 0;
+ colnr_T len = 0;
if (HAS_KEY(opts, set_extmark, spell)) {
hl.flags |= (opts->spell) ? kSHSpellOn : kSHSpellOff;
@@ -712,16 +712,16 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
});
line = buf->b_ml.ml_line_count;
} else if (line < buf->b_ml.ml_line_count) {
- len = opts->ephemeral ? MAXCOL : strlen(ml_get_buf(buf, (linenr_T)line + 1));
+ len = opts->ephemeral ? MAXCOL : ml_get_buf_len(buf, (linenr_T)line + 1);
}
if (col == -1) {
- col = (Integer)len;
- } else if (col > (Integer)len) {
+ col = len;
+ } else if (col > len) {
VALIDATE_RANGE(!strict, "col", {
goto error;
});
- col = (Integer)len;
+ col = len;
} else if (col < -1) {
VALIDATE_RANGE(false, "col", {
goto error;
@@ -730,7 +730,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
if (col2 >= 0) {
if (line2 >= 0 && line2 < buf->b_ml.ml_line_count) {
- len = opts->ephemeral ? MAXCOL : strlen(ml_get_buf(buf, (linenr_T)line2 + 1));
+ len = opts->ephemeral ? MAXCOL : ml_get_buf_len(buf, (linenr_T)line2 + 1);
} else if (line2 == buf->b_ml.ml_line_count) {
// We are trying to add an extmark past final newline
len = 0;
@@ -738,11 +738,11 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
// reuse len from before
line2 = (int)line;
}
- if (col2 > (Integer)len) {
+ if (col2 > len) {
VALIDATE_RANGE(!strict, "end_col", {
goto error;
});
- col2 = (int)len;
+ col2 = len;
}
} else if (line2 >= 0) {
col2 = 0;
@@ -761,32 +761,20 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
col2 = c;
}
- DecorPriority subpriority = DECOR_PRIORITY_BASE;
- if (HAS_KEY(opts, set_extmark, _subpriority)) {
- VALIDATE_RANGE((opts->_subpriority >= 0 && opts->_subpriority <= UINT16_MAX),
- "_subpriority", {
- goto error;
- });
- subpriority = (DecorPriority)opts->_subpriority;
- }
-
if (kv_size(virt_text.data.virt_text)) {
- decor_range_add_virt(&decor_state, r, c, line2, col2, decor_put_vt(virt_text, NULL), true,
- subpriority);
+ decor_range_add_virt(&decor_state, r, c, line2, col2, decor_put_vt(virt_text, NULL), true);
}
if (kv_size(virt_lines.data.virt_lines)) {
- decor_range_add_virt(&decor_state, r, c, line2, col2, decor_put_vt(virt_lines, NULL), true,
- subpriority);
+ decor_range_add_virt(&decor_state, r, c, line2, col2, decor_put_vt(virt_lines, NULL), true);
}
if (url != NULL) {
DecorSignHighlight sh = DECOR_SIGN_HIGHLIGHT_INIT;
sh.url = url;
- decor_range_add_sh(&decor_state, r, c, line2, col2, &sh, true, 0, 0, subpriority);
+ decor_range_add_sh(&decor_state, r, c, line2, col2, &sh, true, 0, 0);
}
if (has_hl) {
DecorSignHighlight sh = decor_sh_from_inline(hl);
- decor_range_add_sh(&decor_state, r, c, line2, col2, &sh, true, (uint32_t)ns_id, id,
- subpriority);
+ decor_range_add_sh(&decor_state, r, c, line2, col2, &sh, true, (uint32_t)ns_id, id);
}
} else {
if (opts->ephemeral) {
@@ -1177,7 +1165,7 @@ VirtText parse_virt_text(Array chunks, Error *err, int *width)
String str = chunk.items[0].data.string;
- int hl_id = 0;
+ int hl_id = -1;
if (chunk.size == 2) {
Object hl = chunk.items[1];
if (hl.type == kObjectTypeArray) {
@@ -1227,13 +1215,15 @@ String nvim__buf_debug_extmarks(Buffer buffer, Boolean keys, Boolean dot, Error
return mt_inspect(buf->b_marktree, keys, dot);
}
-/// Adds the namespace scope to the window.
+/// EXPERIMENTAL: this API will change in the future.
+///
+/// Scopes a namespace to the a window, so extmarks in the namespace will be active only in the
+/// given window.
///
/// @param window Window handle, or 0 for current window
-/// @param ns_id the namespace to add
+/// @param ns_id Namespace
/// @return true if the namespace was added, else false
-Boolean nvim_win_add_ns(Window window, Integer ns_id, Error *err)
- FUNC_API_SINCE(12)
+Boolean nvim__win_add_ns(Window window, Integer ns_id, Error *err)
{
win_T *win = find_window_by_handle(window, err);
if (!win) {
@@ -1246,17 +1236,20 @@ Boolean nvim_win_add_ns(Window window, Integer ns_id, Error *err)
set_put(uint32_t, &win->w_ns_set, (uint32_t)ns_id);
- changed_window_setting_win(win);
+ if (map_has(uint32_t, win->w_buffer->b_extmark_ns, (uint32_t)ns_id)) {
+ changed_window_setting(win);
+ }
return true;
}
-/// Gets all the namespaces scopes associated with a window.
+/// EXPERIMENTAL: this API will change in the future.
+///
+/// Gets the namespace scopes for a given window.
///
/// @param window Window handle, or 0 for current window
/// @return a list of namespaces ids
-ArrayOf(Integer) nvim_win_get_ns(Window window, Arena *arena, Error *err)
- FUNC_API_SINCE(12)
+ArrayOf(Integer) nvim__win_get_ns(Window window, Arena *arena, Error *err)
{
win_T *win = find_window_by_handle(window, err);
if (!win) {
@@ -1272,13 +1265,14 @@ ArrayOf(Integer) nvim_win_get_ns(Window window, Arena *arena, Error *err)
return rv;
}
-/// Removes the namespace scope from the window.
+/// EXPERIMENTAL: this API will change in the future.
+///
+/// Unscopes a namespace (un-binds it from the given scope).
///
/// @param window Window handle, or 0 for current window
/// @param ns_id the namespace to remove
/// @return true if the namespace was removed, else false
-Boolean nvim_win_remove_ns(Window window, Integer ns_id, Error *err)
- FUNC_API_SINCE(12)
+Boolean nvim__win_del_ns(Window window, Integer ns_id, Error *err)
{
win_T *win = find_window_by_handle(window, err);
if (!win) {
@@ -1291,7 +1285,9 @@ Boolean nvim_win_remove_ns(Window window, Integer ns_id, Error *err)
set_del(uint32_t, &win->w_ns_set, (uint32_t)ns_id);
- changed_window_setting_win(win);
+ if (map_has(uint32_t, win->w_buffer->b_extmark_ns, (uint32_t)ns_id)) {
+ changed_window_setting(win);
+ }
return true;
}
diff --git a/src/nvim/api/keysets_defs.h b/src/nvim/api/keysets_defs.h
index fe91d9760d..00d8aa8428 100644
--- a/src/nvim/api/keysets_defs.h
+++ b/src/nvim/api/keysets_defs.h
@@ -56,8 +56,6 @@ typedef struct {
Boolean undo_restore;
String url;
Boolean scoped;
-
- Integer _subpriority;
} Dict(set_extmark);
typedef struct {
@@ -375,3 +373,17 @@ typedef struct {
Boolean ignore_blank_lines;
Boolean indent_heuristic;
} Dict(xdl_diff);
+
+typedef struct {
+ OptionalKeys is_set__redraw_;
+ Boolean flush;
+ Boolean cursor;
+ Boolean valid;
+ Boolean statuscolumn;
+ Boolean statusline;
+ Boolean tabline;
+ Boolean winbar;
+ Array range;
+ Window win;
+ Buffer buf;
+} Dict(redraw);
diff --git a/src/nvim/api/private/converter.c b/src/nvim/api/private/converter.c
index a70ef1e50b..a78d78c057 100644
--- a/src/nvim/api/private/converter.c
+++ b/src/nvim/api/private/converter.c
@@ -76,8 +76,7 @@ static Object typval_cbuf_to_obj(EncodedData *edata, const char *data, size_t le
do { \
ufunc_T *fp = find_func(fun); \
if (fp != NULL && (fp->uf_flags & FC_LUAREF)) { \
- LuaRef ref = api_new_luaref(fp->uf_luaref); \
- kvi_push(edata->stack, LUAREF_OBJ(ref)); \
+ kvi_push(edata->stack, LUAREF_OBJ(api_new_luaref(fp->uf_luaref))); \
} else { \
TYPVAL_ENCODE_CONV_NIL(tv); \
} \
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 1cd98aa0c4..a17e78cc31 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -524,10 +524,10 @@ String buf_get_text(buf_T *buf, int64_t lnum, int64_t start_col, int64_t end_col
}
char *bufstr = ml_get_buf(buf, (linenr_T)lnum);
- size_t line_length = strlen(bufstr);
+ colnr_T line_length = ml_get_buf_len(buf, (linenr_T)lnum);
- start_col = start_col < 0 ? (int64_t)line_length + start_col + 1 : start_col;
- end_col = end_col < 0 ? (int64_t)line_length + end_col + 1 : end_col;
+ start_col = start_col < 0 ? line_length + start_col + 1 : start_col;
+ end_col = end_col < 0 ? line_length + end_col + 1 : end_col;
if (start_col >= MAXCOL || end_col >= MAXCOL) {
api_set_error(err, kErrorTypeValidation, "Column index is too high");
@@ -539,7 +539,7 @@ String buf_get_text(buf_T *buf, int64_t lnum, int64_t start_col, int64_t end_col
return rv;
}
- if ((size_t)start_col >= line_length) {
+ if (start_col >= line_length) {
return rv;
}
diff --git a/src/nvim/api/tabpage.c b/src/nvim/api/tabpage.c
index 040abb1e3f..56a3f1cf23 100644
--- a/src/nvim/api/tabpage.c
+++ b/src/nvim/api/tabpage.c
@@ -146,7 +146,11 @@ void nvim_tabpage_set_win(Tabpage tabpage, Window win, Error *err)
}
if (tp == curtab) {
- win_enter(wp, true);
+ try_start();
+ win_goto(wp);
+ if (!try_end(err) && curwin != wp) {
+ api_set_error(err, kErrorTypeException, "Failed to switch to window %d", win);
+ }
} else if (tp->tp_curwin != wp) {
tp->tp_prevwin = tp->tp_curwin;
tp->tp_curwin = wp;
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index 692e3f95fc..fdf25c75d7 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -67,7 +67,6 @@ static void mpack_str_small(char **buf, const char *str, size_t len)
static void remote_ui_destroy(RemoteUI *ui)
FUNC_ATTR_NONNULL_ALL
{
- kv_destroy(ui->call_buf);
xfree(ui->packer.startptr);
XFREE_CLEAR(ui->term_name);
xfree(ui);
@@ -190,8 +189,6 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona
.anydata = ui,
};
ui->wildmenu_active = false;
- ui->call_buf = (Array)ARRAY_DICT_INIT;
- kv_ensure_space(ui->call_buf, 16);
pmap_put(uint64_t)(&connected_uis, channel_id, ui);
ui_attach_impl(ui, channel_id);
@@ -533,7 +530,8 @@ static void ui_alloc_buf(RemoteUI *ui)
static void prepare_call(RemoteUI *ui, const char *name)
{
- if (ui->packer.startptr && BUF_POS(ui) > UI_BUF_SIZE - EVENT_BUF_SIZE) {
+ if (ui->packer.startptr
+ && (BUF_POS(ui) > UI_BUF_SIZE - EVENT_BUF_SIZE || ui->ncells_pending >= 500)) {
ui_flush_buf(ui);
}
@@ -582,7 +580,7 @@ static void ui_flush_callback(PackerBuffer *packer)
void remote_ui_grid_clear(RemoteUI *ui, Integer grid)
{
- Array args = ui->call_buf;
+ MAXSIZE_TEMP_ARRAY(args, 1);
if (ui->ui_ext[kUILinegrid]) {
ADD_C(args, INTEGER_OBJ(grid));
}
@@ -592,7 +590,7 @@ void remote_ui_grid_clear(RemoteUI *ui, Integer grid)
void remote_ui_grid_resize(RemoteUI *ui, Integer grid, Integer width, Integer height)
{
- Array args = ui->call_buf;
+ MAXSIZE_TEMP_ARRAY(args, 3);
if (ui->ui_ext[kUILinegrid]) {
ADD_C(args, INTEGER_OBJ(grid));
} else {
@@ -608,7 +606,7 @@ void remote_ui_grid_scroll(RemoteUI *ui, Integer grid, Integer top, Integer bot,
Integer right, Integer rows, Integer cols)
{
if (ui->ui_ext[kUILinegrid]) {
- Array args = ui->call_buf;
+ MAXSIZE_TEMP_ARRAY(args, 7);
ADD_C(args, INTEGER_OBJ(grid));
ADD_C(args, INTEGER_OBJ(top));
ADD_C(args, INTEGER_OBJ(bot));
@@ -618,20 +616,19 @@ void remote_ui_grid_scroll(RemoteUI *ui, Integer grid, Integer top, Integer bot,
ADD_C(args, INTEGER_OBJ(cols));
push_call(ui, "grid_scroll", args);
} else {
- Array args = ui->call_buf;
+ MAXSIZE_TEMP_ARRAY(args, 4);
ADD_C(args, INTEGER_OBJ(top));
ADD_C(args, INTEGER_OBJ(bot - 1));
ADD_C(args, INTEGER_OBJ(left));
ADD_C(args, INTEGER_OBJ(right - 1));
push_call(ui, "set_scroll_region", args);
- args = ui->call_buf;
+ kv_size(args) = 0;
ADD_C(args, INTEGER_OBJ(rows));
push_call(ui, "scroll", args);
- // some clients have "clear" being affected by scroll region,
- // so reset it.
- args = ui->call_buf;
+ // some clients have "clear" being affected by scroll region, so reset it.
+ kv_size(args) = 0;
ADD_C(args, INTEGER_OBJ(0));
ADD_C(args, INTEGER_OBJ(ui->height - 1));
ADD_C(args, INTEGER_OBJ(0));
@@ -646,7 +643,7 @@ void remote_ui_default_colors_set(RemoteUI *ui, Integer rgb_fg, Integer rgb_bg,
if (!ui->ui_ext[kUITermColors]) {
HL_SET_DEFAULT_COLORS(rgb_fg, rgb_bg, rgb_sp);
}
- Array args = ui->call_buf;
+ MAXSIZE_TEMP_ARRAY(args, 5);
ADD_C(args, INTEGER_OBJ(rgb_fg));
ADD_C(args, INTEGER_OBJ(rgb_bg));
ADD_C(args, INTEGER_OBJ(rgb_sp));
@@ -656,15 +653,15 @@ void remote_ui_default_colors_set(RemoteUI *ui, Integer rgb_fg, Integer rgb_bg,
// Deprecated
if (!ui->ui_ext[kUILinegrid]) {
- args = ui->call_buf;
+ kv_size(args) = 0;
ADD_C(args, INTEGER_OBJ(ui->rgb ? rgb_fg : cterm_fg - 1));
push_call(ui, "update_fg", args);
- args = ui->call_buf;
+ kv_size(args) = 0;
ADD_C(args, INTEGER_OBJ(ui->rgb ? rgb_bg : cterm_bg - 1));
push_call(ui, "update_bg", args);
- args = ui->call_buf;
+ kv_size(args) = 0;
ADD_C(args, INTEGER_OBJ(ui->rgb ? rgb_sp : -1));
push_call(ui, "update_sp", args);
}
@@ -677,7 +674,7 @@ void remote_ui_hl_attr_define(RemoteUI *ui, Integer id, HlAttrs rgb_attrs, HlAtt
return;
}
- Array args = ui->call_buf;
+ MAXSIZE_TEMP_ARRAY(args, 4);
ADD_C(args, INTEGER_OBJ(id));
MAXSIZE_TEMP_DICT(rgb, HLATTRS_DICT_SIZE);
MAXSIZE_TEMP_DICT(cterm, HLATTRS_DICT_SIZE);
@@ -705,14 +702,14 @@ void remote_ui_hl_attr_define(RemoteUI *ui, Integer id, HlAttrs rgb_attrs, HlAtt
void remote_ui_highlight_set(RemoteUI *ui, int id)
{
- Array args = ui->call_buf;
-
if (ui->hl_id == id) {
return;
}
+
ui->hl_id = id;
MAXSIZE_TEMP_DICT(dict, HLATTRS_DICT_SIZE);
hlattrs2dict(&dict, NULL, syn_attr2entry(id), ui->rgb, false);
+ MAXSIZE_TEMP_ARRAY(args, 1);
ADD_C(args, DICTIONARY_OBJ(dict));
push_call(ui, "highlight_set", args);
}
@@ -721,7 +718,7 @@ void remote_ui_highlight_set(RemoteUI *ui, int id)
void remote_ui_grid_cursor_goto(RemoteUI *ui, Integer grid, Integer row, Integer col)
{
if (ui->ui_ext[kUILinegrid]) {
- Array args = ui->call_buf;
+ MAXSIZE_TEMP_ARRAY(args, 3);
ADD_C(args, INTEGER_OBJ(grid));
ADD_C(args, INTEGER_OBJ(row));
ADD_C(args, INTEGER_OBJ(col));
@@ -741,7 +738,7 @@ void remote_ui_cursor_goto(RemoteUI *ui, Integer row, Integer col)
}
ui->client_row = row;
ui->client_col = col;
- Array args = ui->call_buf;
+ MAXSIZE_TEMP_ARRAY(args, 2);
ADD_C(args, INTEGER_OBJ(row));
ADD_C(args, INTEGER_OBJ(col));
push_call(ui, "cursor_goto", args);
@@ -750,7 +747,7 @@ void remote_ui_cursor_goto(RemoteUI *ui, Integer row, Integer col)
void remote_ui_put(RemoteUI *ui, const char *cell)
{
ui->client_col++;
- Array args = ui->call_buf;
+ MAXSIZE_TEMP_ARRAY(args, 1);
ADD_C(args, CSTR_AS_OBJ(cell));
push_call(ui, "put", args);
}
@@ -781,11 +778,14 @@ void remote_ui_raw_line(RemoteUI *ui, Integer grid, Integer row, Integer startco
for (size_t i = 0; i < ncells; i++) {
repeat++;
if (i == ncells - 1 || attrs[i] != attrs[i + 1] || chunk[i] != chunk[i + 1]) {
- if (UI_BUF_SIZE - BUF_POS(ui) < 2 * (1 + 2 + sizeof(schar_T) + 5 + 5) + 1) {
+ if (UI_BUF_SIZE - BUF_POS(ui) < 2 * (1 + 2 + MAX_SCHAR_SIZE + 5 + 5) + 1
+ || ui->ncells_pending >= 500) {
// close to overflowing the redraw buffer. finish this event,
// flush, and start a new "grid_line" event at the current position.
// For simplicity leave place for the final "clear" element
// as well, hence the factor of 2 in the check.
+ // Also if there is a lot of packed cells, pass them of to the UI to
+ // let it start processing them
mpack_w2(&lenpos, nelem);
// We only ever set the wrap field on the final "grid_line" event for the line.
@@ -831,11 +831,6 @@ void remote_ui_raw_line(RemoteUI *ui, Integer grid, Integer row, Integer startco
}
mpack_w2(&lenpos, nelem);
mpack_bool(buf, flags & kLineFlagWrap);
-
- if (ui->ncells_pending > 500) {
- // pass off cells to UI to let it start processing them
- ui_flush_buf(ui);
- }
} else {
for (int i = 0; i < endcol - startcol; i++) {
remote_ui_cursor_goto(ui, row, startcol + i);
@@ -951,12 +946,12 @@ void remote_ui_event(RemoteUI *ui, char *name, Array args)
push_call(ui, name, new_args);
goto free_ret;
} else if (strequal(name, "cmdline_block_show")) {
- Array new_args = ui->call_buf;
Array block = args.items[0].data.array;
Array new_block = arena_array(&arena, block.size);
for (size_t i = 0; i < block.size; i++) {
ADD_C(new_block, ARRAY_OBJ(translate_contents(ui, block.items[i].data.array, &arena)));
}
+ MAXSIZE_TEMP_ARRAY(new_args, 1);
ADD_C(new_args, ARRAY_OBJ(new_block));
push_call(ui, name, new_args);
goto free_ret;
@@ -973,18 +968,18 @@ void remote_ui_event(RemoteUI *ui, char *name, Array args)
ui->wildmenu_active = (args.items[4].data.integer == -1)
|| !ui->ui_ext[kUIPopupmenu];
if (ui->wildmenu_active) {
- Array new_args = ui->call_buf;
Array items = args.items[0].data.array;
Array new_items = arena_array(&arena, items.size);
for (size_t i = 0; i < items.size; i++) {
ADD_C(new_items, items.items[i].data.array.items[0]);
}
+ MAXSIZE_TEMP_ARRAY(new_args, 1);</