diff options
| author | Josh Rahm <joshuarahm@gmail.com> | 2024-05-24 19:18:11 +0000 |
|---|---|---|
| committer | Josh Rahm <joshuarahm@gmail.com> | 2024-05-24 19:18:11 +0000 |
| commit | ff7ed8f586589d620a806c3758fac4a47a8e7e15 (patch) | |
| tree | 729bbcb92231538fa61dab6c3d890b025484b7f5 /src/nvim/api | |
| parent | 376914f419eb08fdf4c1a63a77e1f035898a0f10 (diff) | |
| parent | 28c04948a1c887a1cc0cb64de79fa32631700466 (diff) | |
| download | rneovim-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.c | 6 | ||||
| -rw-r--r-- | src/nvim/api/buffer.c | 68 | ||||
| -rw-r--r-- | src/nvim/api/deprecated.c | 109 | ||||
| -rw-r--r-- | src/nvim/api/extmark.c | 80 | ||||
| -rw-r--r-- | src/nvim/api/keysets_defs.h | 16 | ||||
| -rw-r--r-- | src/nvim/api/private/converter.c | 3 | ||||
| -rw-r--r-- | src/nvim/api/private/helpers.c | 8 | ||||
| -rw-r--r-- | src/nvim/api/tabpage.c | 6 | ||||
| -rw-r--r-- | src/nvim/api/ui.c | 61 | ||||
| -rw-r--r-- | src/nvim/api/ui_events.in.h | 4 | ||||
| -rw-r--r-- | src/nvim/api/vim.c | 355 | ||||
| -rw-r--r-- | src/nvim/api/win_config.c | 363 | ||||
| -rw-r--r-- | src/nvim/api/window.c | 12 |
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); |