From 8b2b1fba2abfb99186e3a1f0123251a3e2eae3fe Mon Sep 17 00:00:00 2001 From: glepnir Date: Fri, 3 May 2024 15:53:13 +0800 Subject: fix(float): missing default highlight for title Problem: there is missing default title highlight when highlight not defined in title text chunk. Solution: when attr is not set use default title highlight group. --- src/nvim/api/win_config.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c index 3a9986a7d1..70235d8db6 100644 --- a/src/nvim/api/win_config.c +++ b/src/nvim/api/win_config.c @@ -189,13 +189,13 @@ /// ``` /// - title: Title (optional) in window border, string or list. /// List should consist of `[text, highlight]` tuples. -/// If string, the default highlight group is `FloatTitle`. +/// If string, or a tuple lacks a highlight, the default highlight group is `FloatTitle`. /// - title_pos: Title position. Must be set with `title` option. /// Value can be one of "left", "center", or "right". /// Default is `"left"`. /// - footer: Footer (optional) in window border, string or list. /// List should consist of `[text, highlight]` tuples. -/// If string, the default highlight group is `FloatFooter`. +/// If string, or a tuple lacks a highlight, the default highlight group is `FloatFooter`. /// - footer_pos: Footer position. Must be set with `footer` option. /// Value can be one of "left", "center", or "right". /// Default is `"left"`. @@ -851,7 +851,6 @@ static void parse_bordertext(Object bordertext, BorderTextType bordertext_type, bool *is_present; VirtText *chunks; int *width; - int default_hl_id; switch (bordertext_type) { case kBorderTextTitle: if (fconfig->title) { @@ -861,7 +860,6 @@ static void parse_bordertext(Object bordertext, BorderTextType bordertext_type, is_present = &fconfig->title; chunks = &fconfig->title_chunks; width = &fconfig->title_width; - default_hl_id = syn_check_group(S_LEN("FloatTitle")); break; case kBorderTextFooter: if (fconfig->footer) { @@ -871,7 +869,6 @@ static void parse_bordertext(Object bordertext, BorderTextType bordertext_type, is_present = &fconfig->footer; chunks = &fconfig->footer_chunks; width = &fconfig->footer_width; - default_hl_id = syn_check_group(S_LEN("FloatFooter")); break; } @@ -881,7 +878,7 @@ static void parse_bordertext(Object bordertext, BorderTextType bordertext_type, return; } kv_push(*chunks, ((VirtTextChunk){ .text = xstrdup(bordertext.data.string.data), - .hl_id = default_hl_id })); + .hl_id = -1 })); *width = (int)mb_string2cells(bordertext.data.string.data); *is_present = true; return; -- cgit From 104800ce2eadd21475b5a4897265a8a177e58d77 Mon Sep 17 00:00:00 2001 From: Malte Dehling Date: Mon, 27 May 2024 04:14:57 -0700 Subject: build: "popcount" name conflict on NetBSD #28983 Problem: NetBSD's libc already has a function by the same name. Solution: Rename popcount to xpopcount and add #if defined(__NetBSD__) to prefer NetBSD's own implementation. This fixes #28983. --- src/nvim/api/vim.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index fc780e1248..52ab18cbff 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -2354,8 +2354,8 @@ void nvim__redraw(Dict(redraw) *opts, Error *err) } } - int count = (win != NULL) + (buf != NULL); - VALIDATE(popcount(opts->is_set__redraw_) > count, "%s", "at least one action required", { + unsigned count = (win != NULL) + (buf != NULL); + VALIDATE(xpopcount(opts->is_set__redraw_) > count, "%s", "at least one action required", { return; }); -- cgit From 6d6974eae685feeccac027287b4dee58730a7464 Mon Sep 17 00:00:00 2001 From: bfredl Date: Fri, 31 May 2024 20:36:16 +0200 Subject: refactor(input): don't use a ring for input Since paste data is handled via a separate channel, the data processed via `input_buffer` is typically just explicit keys as typed in by the user. Therefore it should be fine to use `memmove()` to always put the remaining data in front when refilling the buffer. --- src/nvim/api/vim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 52ab18cbff..ae8f73fa2c 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -313,7 +313,7 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_ks) keys_esc = keys.data; } if (lowlevel) { - input_enqueue_raw(cstr_as_string(keys_esc)); + input_enqueue_raw(keys_esc, strlen(keys_esc)); } else { ins_typebuf(keys_esc, (remap ? REMAP_YES : REMAP_NONE), insert ? 0 : typebuf.tb_len, !typed, false); -- cgit From bb6190bec5f18c1f9e2c1d29ef1f7cf7912ea625 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 1 Jun 2024 08:19:41 -0700 Subject: refactor: move shared messages to errors.h #26214 --- src/nvim/api/vim.c | 1 + src/nvim/api/win_config.c | 1 + src/nvim/api/window.c | 1 + 3 files changed, 3 insertions(+) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 52ab18cbff..f5c89fb283 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -28,6 +28,7 @@ #include "nvim/cursor.h" #include "nvim/decoration.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c index 70235d8db6..f0b90d8512 100644 --- a/src/nvim/api/win_config.c +++ b/src/nvim/api/win_config.c @@ -17,6 +17,7 @@ #include "nvim/decoration.h" #include "nvim/decoration_defs.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval/window.h" #include "nvim/extmark_defs.h" #include "nvim/globals.h" diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index 54a19513db..92dc9dc7e3 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -13,6 +13,7 @@ #include "nvim/buffer_defs.h" #include "nvim/cursor.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval/window.h" #include "nvim/ex_docmd.h" #include "nvim/gettext_defs.h" -- cgit From 200e7ad1578619e78c664bd0c6be024168433412 Mon Sep 17 00:00:00 2001 From: James Tirta Halim Date: Mon, 3 Jun 2024 11:10:30 +0700 Subject: fixup: apply the change on more files --- src/nvim/api/buffer.c | 6 +++--- src/nvim/api/command.c | 4 ++-- src/nvim/api/private/validate.c | 2 +- src/nvim/api/vimscript.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 7e64808709..e078d85f33 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1375,7 +1375,7 @@ static inline void init_line_array(lua_State *lstate, Array *a, size_t size, Are /// @param s String to push /// @param len Size of string /// @param idx 0-based index to place s (only used for Lua) -/// @param replace_nl Replace newlines ('\n') with null ('\0') +/// @param replace_nl Replace newlines ('\n') with null (NUL) static void push_linestr(lua_State *lstate, Array *a, const char *s, size_t len, int idx, bool replace_nl, Arena *arena) { @@ -1384,7 +1384,7 @@ static void push_linestr(lua_State *lstate, Array *a, const char *s, size_t len, if (s && replace_nl && strchr(s, '\n')) { // TODO(bfredl): could manage scratch space in the arena, for the NUL case char *tmp = xmemdupz(s, len); - strchrsub(tmp, '\n', '\0'); + strchrsub(tmp, '\n', NUL); lua_pushlstring(lstate, tmp, len); xfree(tmp); } else { @@ -1397,7 +1397,7 @@ static void push_linestr(lua_State *lstate, Array *a, const char *s, size_t len, str = CBUF_TO_ARENA_STR(arena, s, len); if (replace_nl) { // Vim represents NULs as NLs, but this may confuse clients. - strchrsub(str.data, '\n', '\0'); + strchrsub(str.data, '\n', NUL); } } diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index 779e216c74..5ad439af9c 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -193,7 +193,7 @@ Dict(cmd) nvim_parse_cmd(String str, Dict(empty) *opts, Arena *arena, Error *err } else { nargs[0] = '0'; } - nargs[1] = '\0'; + nargs[1] = NUL; PUT_KEY(result, cmd, nargs, CSTR_TO_ARENA_OBJ(arena, nargs)); char *addr; @@ -391,7 +391,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Arena case kObjectTypeBoolean: data_str = arena_alloc(arena, 2, false); data_str[0] = elem.data.boolean ? '1' : '0'; - data_str[1] = '\0'; + data_str[1] = NUL; ADD_C(args, CSTR_AS_OBJ(data_str)); break; case kObjectTypeBuffer: diff --git a/src/nvim/api/private/validate.c b/src/nvim/api/private/validate.c index e198c671eb..9fd7d3bfa6 100644 --- a/src/nvim/api/private/validate.c +++ b/src/nvim/api/private/validate.c @@ -17,7 +17,7 @@ void api_err_invalid(Error *err, const char *name, const char *val_s, int64_t va char *has_space = strchr(name, ' '); // No value. - if (val_s && val_s[0] == '\0') { + if (val_s && val_s[0] == NUL) { api_set_error(err, errtype, has_space ? "Invalid %s" : "Invalid '%s'", name); return; } diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c index 477cbe2428..124c26d175 100644 --- a/src/nvim/api/vimscript.c +++ b/src/nvim/api/vimscript.c @@ -109,7 +109,7 @@ String exec_impl(uint64_t channel_id, String src, Dict(exec_opts) *opts, Error * // redir usually (except :echon) prepends a newline. if (s.data[0] == '\n') { memmove(s.data, s.data + 1, s.size - 1); - s.data[s.size - 1] = '\0'; + s.data[s.size - 1] = NUL; s.size = s.size - 1; } return s; // Caller will free the memory. -- cgit From 8c5af0eb85a3932f6ca018d2aa681521369a26be Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Fri, 7 Jun 2024 04:55:14 +0200 Subject: docs: misc (#28837) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Danymat Co-authored-by: Gregory Anders Co-authored-by: Jakub Okoński Co-authored-by: John L. Villalovos Co-authored-by: Maria José Solano Co-authored-by: Michaili K Co-authored-by: TheLeoP Co-authored-by: Tobias Schmitz Co-authored-by: W20MC <157727813+W20MC@users.noreply.github.com> Co-authored-by: Will Hopkins Co-authored-by: Yifan Hu <141280278+b0ae989c@users.noreply.github.com> Co-authored-by: glepnir Co-authored-by: prljav <74116121+prljav@users.noreply.github.com> --- src/nvim/api/buffer.c | 6 +++--- src/nvim/api/extmark.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index e078d85f33..a0678dc3e4 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1183,12 +1183,12 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Arena *arena, return rv; } -/// call a function with buffer as temporary current buffer +/// Call a function with buffer as temporary current buffer. /// /// This temporarily switches current buffer to "buffer". -/// If the current window already shows "buffer", the window is not switched +/// If the current window already shows "buffer", the window is not switched. /// If a window inside the current tabpage (including a float) already shows the -/// buffer One of these windows will be set as current window temporarily. +/// buffer, then one of these windows will be set as current window temporarily. /// Otherwise a temporary scratch window (called the "autocmd window" for /// historical reasons) will be used. /// diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index 85cce45560..3c8fded2f6 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -1038,7 +1038,7 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start, /// ``` /// - on_win: called when starting to redraw a specific window. /// ``` -/// ["win", winid, bufnr, topline, botline] +/// ["win", winid, bufnr, toprow, botrow] /// ``` /// - on_line: called for each buffer line being redrawn. /// (The interaction with fold lines is subject to change) -- cgit From f3632e14e3a75114415050ab01c2d04a06036009 Mon Sep 17 00:00:00 2001 From: altermo <107814000+altermo@users.noreply.github.com> Date: Fri, 7 Jun 2024 17:33:40 +0200 Subject: feat: get/set namespace properties #28728 ref https://github.com/neovim/neovim/pull/28432 ref https://github.com/neovim/neovim/issues/28469 --- src/nvim/api/deprecated.c | 2 +- src/nvim/api/extmark.c | 155 +++++++++++++++++++++++++++----------------- src/nvim/api/extmark.h | 15 +++++ src/nvim/api/keysets_defs.h | 5 ++ 4 files changed, 115 insertions(+), 62 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c index af3bfe2c03..a1af354577 100644 --- a/src/nvim/api/deprecated.c +++ b/src/nvim/api/deprecated.c @@ -170,7 +170,7 @@ Integer nvim_buf_set_virtual_text(Buffer buffer, Integer src_id, Integer line, A DecorInline decor = { .ext = true, .data.ext.vt = vt, .data.ext.sh_idx = DECOR_ID_INVALID }; extmark_set(buf, ns_id, NULL, (int)line, 0, -1, -1, decor, 0, true, - false, false, false, false, NULL); + false, false, false, NULL); return src_id; } diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index 3c8fded2f6..ab6ff5ff1f 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -18,6 +18,7 @@ #include "nvim/decoration_provider.h" #include "nvim/drawscreen.h" #include "nvim/extmark.h" +#include "nvim/globals.h" #include "nvim/grid.h" #include "nvim/highlight_group.h" #include "nvim/map_defs.h" @@ -41,6 +42,7 @@ void api_extmark_free_all_mem(void) xfree(name.data); }) map_destroy(String, &namespace_ids); + set_destroy(uint32_t, &namespace_localscope); } /// Creates a new namespace or gets an existing one. [namespace]() @@ -179,10 +181,6 @@ static Array extmark_to_array(MTPair extmark, bool id, bool add_dict, bool hl_na PUT_C(dict, "invalid", BOOLEAN_OBJ(true)); } - if (mt_scoped(start)) { - PUT_C(dict, "scoped", BOOLEAN_OBJ(true)); - } - decor_to_dict_legacy(&dict, mt_decor(start), hl_name, arena); ADD_C(rv, DICTIONARY_OBJ(dict)); @@ -489,8 +487,6 @@ 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 (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 @@ -749,11 +745,6 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer } if (opts->ephemeral && decor_state.win && decor_state.win->w_buffer == buf) { - if (opts->scoped) { - api_set_error(err, kErrorTypeException, "not yet implemented"); - goto error; - } - int r = (int)line; int c = (int)col; if (line2 == -1) { @@ -834,7 +825,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer extmark_set(buf, (uint32_t)ns_id, &id, (int)line, (colnr_T)col, line2, col2, decor, decor_flags, right_gravity, opts->end_right_gravity, !GET_BOOL_OR_TRUE(opts, set_extmark, undo_restore), - opts->invalidate, opts->scoped, err); + opts->invalidate, err); if (ERROR_SET(err)) { decor_free(decor); return 0; @@ -960,7 +951,7 @@ Integer nvim_buf_add_highlight(Buffer buffer, Integer ns_id, String hl_group, In decor.data.hl.hl_id = hl_id; extmark_set(buf, ns, NULL, (int)line, (colnr_T)col_start, end_line, (colnr_T)col_end, - decor, MT_FLAG_DECOR_HL, true, false, false, false, false, NULL); + decor, MT_FLAG_DECOR_HL, true, false, false, false, NULL); return ns_id; } @@ -1217,77 +1208,119 @@ String nvim__buf_debug_extmarks(Buffer buffer, Boolean keys, Boolean dot, Error /// 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. +/// Set some properties for namespace /// -/// @param window Window handle, or 0 for current window /// @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) +/// @param opts Optional parameters to set: +/// - wins: a list of windows to be scoped in +/// +void nvim__ns_set(Integer ns_id, Dict(ns_opts) *opts, Error *err) { - win_T *win = find_window_by_handle(window, err); - if (!win) { - return false; - } - VALIDATE_INT(ns_initialized((uint32_t)ns_id), "ns_id", ns_id, { - return false; + return; }); - set_put(uint32_t, &win->w_ns_set, (uint32_t)ns_id); + bool set_scoped = true; - if (map_has(uint32_t, win->w_buffer->b_extmark_ns, (uint32_t)ns_id)) { - changed_window_setting(win); - } + if (HAS_KEY(opts, ns_opts, wins)) { + if (opts->wins.size == 0) { + set_scoped = false; + } - return true; -} + Set(ptr_t) windows = SET_INIT; + for (size_t i = 0; i < opts->wins.size; i++) { + Integer win = opts->wins.items[i].data.integer; -/// 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) -{ - win_T *win = find_window_by_handle(window, err); - if (!win) { - return (Array)ARRAY_DICT_INIT; + win_T *wp = find_window_by_handle((Window)win, err); + if (!wp) { + return; + } + + set_put(ptr_t, &windows, wp); + } + + FOR_ALL_TAB_WINDOWS(tp, wp) { + if (set_has(ptr_t, &windows, wp) && !set_has(uint32_t, &wp->w_ns_set, (uint32_t)ns_id)) { + set_put(uint32_t, &wp->w_ns_set, (uint32_t)ns_id); + + if (map_has(uint32_t, wp->w_buffer->b_extmark_ns, (uint32_t)ns_id)) { + changed_window_setting(wp); + } + } + + if (set_has(uint32_t, &wp->w_ns_set, (uint32_t)ns_id) && !set_has(ptr_t, &windows, wp)) { + set_del(uint32_t, &wp->w_ns_set, (uint32_t)ns_id); + + if (map_has(uint32_t, wp->w_buffer->b_extmark_ns, (uint32_t)ns_id)) { + changed_window_setting(wp); + } + } + } + + set_destroy(ptr_t, &windows); } - Array rv = arena_array(arena, set_size(&win->w_ns_set)); - uint32_t i; - set_foreach(&win->w_ns_set, i, { - ADD_C(rv, INTEGER_OBJ((Integer)(i))); - }); + if (set_scoped && !set_has(uint32_t, &namespace_localscope, (uint32_t)ns_id)) { + set_put(uint32_t, &namespace_localscope, (uint32_t)ns_id); - return rv; + // When a namespace becomes scoped, any window which contains + // elements associated with namespace needs to be redrawn + FOR_ALL_TAB_WINDOWS(tp, wp) { + if (map_has(uint32_t, wp->w_buffer->b_extmark_ns, (uint32_t)ns_id)) { + changed_window_setting(wp); + } + } + } else if (!set_scoped && set_has(uint32_t, &namespace_localscope, (uint32_t)ns_id)) { + set_del(uint32_t, &namespace_localscope, (uint32_t)ns_id); + + // When a namespace becomes unscoped, any window which does not + // contain elements associated with namespace needs to be redrawn + FOR_ALL_TAB_WINDOWS(tp, wp) { + if (map_has(uint32_t, wp->w_buffer->b_extmark_ns, (uint32_t)ns_id)) { + changed_window_setting(wp); + } + } + } } /// EXPERIMENTAL: this API will change in the future. /// -/// Unscopes a namespace (un-binds it from the given scope). +/// Get the properties for namespace /// -/// @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_del_ns(Window window, Integer ns_id, Error *err) +/// @param ns_id Namespace +/// @return Map defining the namespace properties, see |nvim__ns_set()| +Dict(ns_opts) nvim__ns_get(Integer ns_id, Arena *arena, Error *err) { - win_T *win = find_window_by_handle(window, err); - if (!win) { - return false; + Dict(ns_opts) opts = KEYDICT_INIT; + + Array windows = ARRAY_DICT_INIT; + + PUT_KEY(opts, ns_opts, wins, windows); + + VALIDATE_INT(ns_initialized((uint32_t)ns_id), "ns_id", ns_id, { + return opts; + }); + + if (!set_has(uint32_t, &namespace_localscope, (uint32_t)ns_id)) { + return opts; } - if (!set_has(uint32_t, &win->w_ns_set, (uint32_t)ns_id)) { - return false; + size_t count = 0; + FOR_ALL_TAB_WINDOWS(tp, wp) { + if (set_has(uint32_t, &wp->w_ns_set, (uint32_t)ns_id)) { + count++; + } } - set_del(uint32_t, &win->w_ns_set, (uint32_t)ns_id); + windows = arena_array(arena, count); - if (map_has(uint32_t, win->w_buffer->b_extmark_ns, (uint32_t)ns_id)) { - changed_window_setting(win); + FOR_ALL_TAB_WINDOWS(tp, wp) { + if (set_has(uint32_t, &wp->w_ns_set, (uint32_t)ns_id)) { + ADD(windows, INTEGER_OBJ(wp->handle)); + } } - return true; + PUT_KEY(opts, ns_opts, wins, windows); + + return opts; } diff --git a/src/nvim/api/extmark.h b/src/nvim/api/extmark.h index 124feaabfb..af2d51c95c 100644 --- a/src/nvim/api/extmark.h +++ b/src/nvim/api/extmark.h @@ -4,14 +4,29 @@ #include "nvim/api/keysets_defs.h" // IWYU pragma: keep #include "nvim/api/private/defs.h" // IWYU pragma: keep +#include "nvim/buffer_defs.h" #include "nvim/decoration_defs.h" // IWYU pragma: keep #include "nvim/macros_defs.h" #include "nvim/map_defs.h" #include "nvim/types_defs.h" EXTERN Map(String, int) namespace_ids INIT( = MAP_INIT); +/// Non-global namespaces. A locally-scoped namespace may be "orphaned" if all +/// window(s) it was scoped to, are destroyed. Such orphans are tracked here to +/// avoid being mistaken as "global scope". +EXTERN Set(uint32_t) namespace_localscope INIT( = SET_INIT); EXTERN handle_T next_namespace_id INIT( = 1); +/// Returns true if the namespace is global or scoped in the given window. +static inline bool ns_in_win(uint32_t ns_id, win_T *wp) +{ + if (!set_has(uint32_t, &namespace_localscope, ns_id)) { + return true; + } + + return set_has(uint32_t, &wp->w_ns_set, ns_id); +} + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "api/extmark.h.generated.h" #endif diff --git a/src/nvim/api/keysets_defs.h b/src/nvim/api/keysets_defs.h index 00d8aa8428..cc2ef981b5 100644 --- a/src/nvim/api/keysets_defs.h +++ b/src/nvim/api/keysets_defs.h @@ -387,3 +387,8 @@ typedef struct { Window win; Buffer buf; } Dict(redraw); + +typedef struct { + OptionalKeys is_set__ns_opts_; + Array wins; +} Dict(ns_opts); -- cgit From 743c5808b616daece73145ddd12b39ae07bbd87a Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sun, 9 Jun 2024 15:59:44 +0200 Subject: fix(api): allow `scope = 'local'` with `buf` when using `nvim_get_option_value` `nvim_get_option_value` throws a warning if both `scope` and `buf` options are used at the same time. This is because using `buf` always implies `scope` is local, and is therefore not needed. There's however no need to error if `scope` is already set "local" as it's the correct value. --- src/nvim/api/options.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c index d9bc0ccc92..5adaff8449 100644 --- a/src/nvim/api/options.c +++ b/src/nvim/api/options.c @@ -54,6 +54,10 @@ static int validate_option_value_args(Dict(option) *opts, char *name, OptIndex * } if (HAS_KEY_X(opts, buf)) { + VALIDATE(!(HAS_KEY_X(opts, scope) && *scope == OPT_GLOBAL), "%s", + "cannot use both global 'scope' and 'buf'", { + return FAIL; + }); *scope = OPT_LOCAL; *req_scope = kOptReqBuf; *from = find_buffer_by_handle(opts->buf, err); @@ -68,11 +72,6 @@ static int validate_option_value_args(Dict(option) *opts, char *name, OptIndex * return FAIL; }); - VALIDATE((!HAS_KEY_X(opts, scope) || !HAS_KEY_X(opts, buf)), "%s", - "cannot use both 'scope' and 'buf'", { - return FAIL; - }); - VALIDATE((!HAS_KEY_X(opts, win) || !HAS_KEY_X(opts, buf)), "%s", "cannot use both 'buf' and 'win'", { return FAIL; -- cgit From 19052e0a06240be018a234d87f51113eca6d17fa Mon Sep 17 00:00:00 2001 From: bfredl Date: Sat, 8 Jun 2024 14:19:30 +0200 Subject: refactor(shada): use msgpack_sbuffer less Work towards getting rid of libmsgpack depedency eventually. msgpack_sbuffer is just a string buffer, we can use our own String type. --- src/nvim/api/private/helpers.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index a17e78cc31..ac621b1486 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -548,10 +548,6 @@ String buf_get_text(buf_T *buf, int64_t lnum, int64_t start_col, int64_t end_col void api_free_string(String value) { - if (!value.data) { - return; - } - xfree(value.data); } -- cgit From 6e28589e00a32045d5a62654151299802e40fdb0 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 15 Jun 2024 01:04:27 +0200 Subject: docs: misc (#29229) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ilia Choly Co-authored-by: Jose Pedro Oliveira Co-authored-by: Maria José Solano Co-authored-by: zeertzjq --- src/nvim/api/extmark.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index ab6ff5ff1f..e30ec9a2ca 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -1002,7 +1002,7 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start, /// Note: this function should not be called often. Rather, the callbacks /// themselves can be used to throttle unneeded callbacks. the `on_start` /// callback can return `false` to disable the provider until the next redraw. -/// Similarly, return `false` in `on_win` will skip the `on_lines` calls +/// Similarly, return `false` in `on_win` will skip the `on_line` calls /// for that window (but any extmarks set in `on_win` will still be used). /// A plugin managing multiple sources of decoration should ideally only set /// one provider, and merge the sources internally. You can use multiple `ns_id` @@ -1011,10 +1011,10 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start, /// Note: doing anything other than setting extmarks is considered experimental. /// Doing things like changing options are not explicitly forbidden, but is /// likely to have unexpected consequences (such as 100% CPU consumption). -/// doing `vim.rpcnotify` should be OK, but `vim.rpcrequest` is quite dubious +/// Doing `vim.rpcnotify` should be OK, but `vim.rpcrequest` is quite dubious /// for the moment. /// -/// Note: It is not allowed to remove or update extmarks in 'on_line' callbacks. +/// Note: It is not allowed to remove or update extmarks in `on_line` callbacks. /// /// @param ns_id Namespace id from |nvim_create_namespace()| /// @param opts Table of callbacks: -- cgit From 2bb1a18631c4035e4a582b7d995968acbac874bf Mon Sep 17 00:00:00 2001 From: bfredl Date: Sat, 15 Jun 2024 19:50:44 +0200 Subject: refactor(typval): don't use msgpack_packer for msgpackdump() Step towords completely eliminating msgpack_packer. --- src/nvim/api/private/converter.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/converter.c b/src/nvim/api/private/converter.c index a78d78c057..0a4daf1dae 100644 --- a/src/nvim/api/private/converter.c +++ b/src/nvim/api/private/converter.c @@ -28,6 +28,7 @@ typedef struct { #endif #define TYPVAL_ENCODE_ALLOW_SPECIALS false +#define TYPVAL_ENCODE_CHECK_BEFORE #define TYPVAL_ENCODE_CONV_NIL(tv) \ kvi_push(edata->stack, NIL) @@ -217,6 +218,7 @@ static inline void typval_encode_dict_end(EncodedData *const edata) #undef TYPVAL_ENCODE_CONV_LIST_START #undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START #undef TYPVAL_ENCODE_CONV_EMPTY_DICT +#undef TYPVAL_ENCODE_CHECK_BEFORE #undef TYPVAL_ENCODE_CONV_NIL #undef TYPVAL_ENCODE_CONV_BOOL #undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER -- cgit From bda63d5b97dfb333de6f4bd757dbb978906062a2 Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 25 Jun 2024 15:33:47 +0200 Subject: refactor(typval)!: remove distinction of binary and nonbinary strings This is a breaking change which will make refactor of typval and shada code a lot easier. In particular, code that would use or check for v:msgpack_types.binary in the wild would be broken. This appears to be rarely used in existing plugins. Also some cases where v:msgpack_type.string would be used to represent a binary string of "string" type, we use a BLOB instead, which is vimscripts native type for binary blobs, and already was used for BIN formats when necessary. msgpackdump(msgpackparse(data)) no longer preserves the distinction of BIN and STR strings. This is very common behavior for language-specific msgpack bindings. Nvim uses msgpack as a tool to serialize its data. Nvim is not a tool to bit-perfectly manipulate arbitrary msgpack data out in the wild. The changed tests should indicate how behavior changes in various edge cases. --- src/nvim/api/private/converter.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/converter.c b/src/nvim/api/private/converter.c index 0a4daf1dae..a1c5816a49 100644 --- a/src/nvim/api/private/converter.c +++ b/src/nvim/api/private/converter.c @@ -7,7 +7,9 @@ #include "nvim/api/private/converter.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/ascii_defs.h" #include "nvim/assert_defs.h" +#include "nvim/eval/decode.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" #include "nvim/eval/userfunc.h" @@ -302,15 +304,11 @@ void object_to_vim_take_luaref(Object *obj, typval_T *tv, bool take_luaref, Erro tv->vval.v_float = obj->data.floating; break; - case kObjectTypeString: - tv->v_type = VAR_STRING; - if (obj->data.string.data == NULL) { - tv->vval.v_string = NULL; - } else { - tv->vval.v_string = xmemdupz(obj->data.string.data, - obj->data.string.size); - } + case kObjectTypeString: { + String s = obj->data.string; + *tv = decode_string(s.data, s.size, false, false); break; + } case kObjectTypeArray: { list_T *const list = tv_list_alloc((ptrdiff_t)obj->data.array.size); -- cgit From 7dffc36e61c46e6adc92cff5944e876446f3c40e Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 13 Jun 2024 12:00:58 +0200 Subject: refactor(declarations): also generate prototypes for functions in headers Before this change, "static inline" functions in headers needed to have their function attributes specified in a completely different way. The prototype had to be duplicated, and REAL_FATTR_ had to be used instead of the public FUNC_ATTR_ names. TODO: need a check that a "header.h.inline.generated.h" file is not forgotten when the first "static inline" function with attributes is added to a header (they would just be silently missing). --- src/nvim/api/private/defs.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h index ca088d7a55..94e2d76cbe 100644 --- a/src/nvim/api/private/defs.h +++ b/src/nvim/api/private/defs.h @@ -5,7 +5,6 @@ #include #include "klib/kvec.h" -#include "nvim/func_attr.h" #include "nvim/types_defs.h" #define ARRAY_DICT_INIT KV_INITIAL_VALUE @@ -20,6 +19,7 @@ # define ArrayOf(...) Array # define DictionaryOf(...) Dictionary # define Dict(name) KeyDict_##name +# include "api/private/defs.h.inline.generated.h" #endif // Basic types @@ -47,15 +47,13 @@ typedef enum { /// Internal call from Lua code #define LUA_INTERNAL_CALL (VIML_INTERNAL_CALL + 1) -static inline bool is_internal_call(uint64_t channel_id) - REAL_FATTR_ALWAYS_INLINE REAL_FATTR_CONST; - /// Check whether call is internal /// /// @param[in] channel_id Channel id. /// /// @return true if channel_id refers to internal channel. static inline bool is_internal_call(const uint64_t channel_id) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_CONST { return !!(channel_id & INTERNAL_CALL_MASK); } -- cgit From 594c7f3d77262a1222c9786d86353a0595f2894c Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 15 Jul 2024 18:35:20 +0800 Subject: fix(ui): avoid ambiguity about last chunk when flushing halfway (#29718) --- src/nvim/api/ui.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index fdf25c75d7..852b8b9b48 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -778,16 +778,26 @@ 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 + MAX_SCHAR_SIZE + 5 + 5) + 1 + if ( + // 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. + UI_BUF_SIZE - BUF_POS(ui) < 2 * (1 + 2 + MAX_SCHAR_SIZE + 5 + 5) + 1 + // Also if there is a lot of packed cells, pass them off to the UI to + // let it start processing them. || 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 + // If the last chunk was all spaces, add an empty clearing chunk, + // so it's clear that the last chunk wasn't a clearing chunk. + if (was_space) { + nelem++; + ui->ncells_pending += 1; + mpack_array(buf, 3); + mpack_str_small(buf, S_LEN(" ")); + mpack_uint(buf, (uint32_t)clearattr); + mpack_uint(buf, 0); + } mpack_w2(&lenpos, nelem); - // We only ever set the wrap field on the final "grid_line" event for the line. mpack_bool(buf, false); ui_flush_buf(ui); -- cgit From 89f9f168a5c4317bcc71cb61e64a1dd63d17a377 Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Mon, 20 May 2024 20:21:11 +0200 Subject: fix(api): alloc and draw cursor window in nvim__redraw Problem: Unable to move cursor to recently opened window. Solution: Make sure uninitialized window is drawn before trying to move the cursor to it. --- src/nvim/api/vim.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 26dc223948..7a4aefc620 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -2393,10 +2393,6 @@ void nvim__redraw(Dict(redraw) *opts, Error *err) redraw_buf_range_later(rbuf, first, last); } - if (opts->cursor) { - setcursor_mayforce(win ? win : curwin, true); - } - bool flush = opts->flush; if (opts->tabline) { // Flush later in case tabline was just hidden or shown for the first time. @@ -2423,11 +2419,22 @@ void nvim__redraw(Dict(redraw) *opts, Error *err) } } - // Flush pending screen updates if "flush" or "clear" is true, or when - // redrawing a status component may have changed the grid dimensions. + win_T *cwin = win ? win : curwin; + // Allow moving cursor to recently opened window and make sure it is drawn #28868. + if (opts->cursor && (!cwin->w_grid.target || !cwin->w_grid.target->valid)) { + flush = true; + } + + // Redraw pending screen updates when explicitly requested or when determined + // that it is necessary to properly draw other requested components. if (flush && !cmdpreview) { update_screen(); } + + if (opts->cursor) { + setcursor_mayforce(cwin, true); + } + ui_flush(); RedrawingDisabled = save_rd; -- cgit From f926cc32c9262b6254e2843276b951cef9da1afe Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 2 Jul 2024 13:45:50 +0200 Subject: refactor(shada): rework msgpack decoding without msgpack-c This also makes shada reading slightly faster due to avoiding some copying and allocation. Use keysets to drive decoding of msgpack maps for shada entries. --- src/nvim/api/command.c | 6 +++--- src/nvim/api/keysets_defs.h | 42 ++++++++++++++++++++++++++++++++++++++++-- src/nvim/api/private/defs.h | 10 +++++++++- src/nvim/api/private/helpers.c | 11 ++++++----- src/nvim/api/ui.c | 1 - 5 files changed, 58 insertions(+), 12 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index 5ad439af9c..78be0a2cf7 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -515,7 +515,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Arena if (HAS_KEY(cmd, cmd, magic)) { Dict(cmd_magic) magic[1] = KEYDICT_INIT; - if (!api_dict_to_keydict(magic, KeyDict_cmd_magic_get_field, cmd->magic, err)) { + if (!api_dict_to_keydict(magic, DictHash(cmd_magic), cmd->magic, err)) { goto end; } @@ -533,14 +533,14 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Arena if (HAS_KEY(cmd, cmd, mods)) { Dict(cmd_mods) mods[1] = KEYDICT_INIT; - if (!api_dict_to_keydict(mods, KeyDict_cmd_mods_get_field, cmd->mods, err)) { + if (!api_dict_to_keydict(mods, DictHash(cmd_mods), cmd->mods, err)) { goto end; } if (HAS_KEY(mods, cmd_mods, filter)) { Dict(cmd_mods_filter) filter[1] = KEYDICT_INIT; - if (!api_dict_to_keydict(&filter, KeyDict_cmd_mods_filter_get_field, + if (!api_dict_to_keydict(&filter, DictHash(cmd_mods_filter), mods->filter, err)) { goto end; } diff --git a/src/nvim/api/keysets_defs.h b/src/nvim/api/keysets_defs.h index cc2ef981b5..ce4e3d56e1 100644 --- a/src/nvim/api/keysets_defs.h +++ b/src/nvim/api/keysets_defs.h @@ -103,7 +103,7 @@ typedef struct { Object nargs; Object preview; Object range; - Boolean register_; + Boolean register_ DictKey(register); } Dict(user_command); typedef struct { @@ -170,7 +170,7 @@ typedef struct { Boolean reverse; Boolean altfont; Boolean nocombine; - Boolean default_; + Boolean default_ DictKey(default); Object cterm; Object foreground; Object fg; @@ -392,3 +392,41 @@ typedef struct { OptionalKeys is_set__ns_opts_; Array wins; } Dict(ns_opts); + +typedef struct { + OptionalKeys is_set___shada_search_pat_; + Boolean magic DictKey(sm); + Boolean smartcase DictKey(sc); + Boolean has_line_offset DictKey(sl); + Boolean place_cursor_at_end DictKey(se); + Boolean is_last_used DictKey(su); + Boolean is_substitute_pattern DictKey(ss); + Boolean highlighted DictKey(sh); + Boolean search_backward DictKey(sb); + Integer offset DictKey(so); + String pat DictKey(sp); +} Dict(_shada_search_pat); + +typedef struct { + OptionalKeys is_set___shada_mark_; + Integer n; + Integer l; + Integer c; + String f; +} Dict(_shada_mark); + +typedef struct { + OptionalKeys is_set___shada_register_; + StringArray rc; + Boolean ru; + Integer rt; + Integer n; + Integer rw; +} Dict(_shada_register); + +typedef struct { + OptionalKeys is_set___shada_buflist_item_; + Integer l; + Integer c; + String f; +} Dict(_shada_buflist_item); diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h index 94e2d76cbe..ac3404cf86 100644 --- a/src/nvim/api/private/defs.h +++ b/src/nvim/api/private/defs.h @@ -19,6 +19,8 @@ # define ArrayOf(...) Array # define DictionaryOf(...) Dictionary # define Dict(name) KeyDict_##name +# define DictHash(name) KeyDict_##name##_get_field +# define DictKey(name) # include "api/private/defs.h.inline.generated.h" #endif @@ -88,6 +90,8 @@ typedef kvec_t(Object) Array; typedef struct key_value_pair KeyValuePair; typedef kvec_t(KeyValuePair) Dictionary; +typedef kvec_t(String) StringArray; + typedef enum { kObjectTypeNil = 0, kObjectTypeBoolean, @@ -103,6 +107,10 @@ typedef enum { kObjectTypeTabpage, } ObjectType; +typedef enum { + kUnpackTypeStringArray = -1, +} UnpackType; + /// Value by which objects represented as EXT type are shifted /// /// Subtracted when packing, added when unpacking. Used to allow moving @@ -140,7 +148,7 @@ typedef struct { typedef struct { char *str; size_t ptr_off; - ObjectType type; // kObjectTypeNil == untyped + int type; // ObjectType or UnpackType. kObjectTypeNil == untyped int opt_index; bool is_hlgroup; } KeySetLink; diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index ac621b1486..017265e0d3 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -922,15 +921,17 @@ bool api_dict_to_keydict(void *retval, FieldHashfn hashy, Dictionary dict, Error } else if (value->type == kObjectTypeDictionary) { *val = value->data.dictionary; } else { - api_err_exp(err, field->str, api_typename(field->type), api_typename(value->type)); + api_err_exp(err, field->str, api_typename((ObjectType)field->type), + api_typename(value->type)); return false; } } else if (field->type == kObjectTypeBuffer || field->type == kObjectTypeWindow || field->type == kObjectTypeTabpage) { - if (value->type == kObjectTypeInteger || value->type == field->type) { + if (value->type == kObjectTypeInteger || value->type == (ObjectType)field->type) { *(handle_T *)mem = (handle_T)value->data.integer; } else { - api_err_exp(err, field->str, api_typename(field->type), api_typename(value->type)); + api_err_exp(err, field->str, api_typename((ObjectType)field->type), + api_typename(value->type)); return false; } } else if (field->type == kObjectTypeLuaRef) { @@ -980,7 +981,7 @@ Dictionary api_keydict_to_dict(void *value, KeySetLink *table, size_t max_size, } else if (field->type == kObjectTypeBuffer || field->type == kObjectTypeWindow || field->type == kObjectTypeTabpage) { val.data.integer = *(handle_T *)mem; - val.type = field->type; + val.type = (ObjectType)field->type; } else if (field->type == kObjectTypeLuaRef) { // do nothing } else { diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 852b8b9b48..82a5ff5f8e 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -1,6 +1,5 @@ #include #include -#include #include #include #include -- cgit From 6bcefad5a671faab202d5359752b75c6619b9e28 Mon Sep 17 00:00:00 2001 From: William Wong Date: Tue, 13 Aug 2024 16:25:29 +0800 Subject: fix(highlight): fix the seg fault caused by the invalid linked hl ids --- src/nvim/api/private/helpers.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 017265e0d3..e00b8c6146 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -774,7 +774,8 @@ int object_to_hl_id(Object obj, const char *what, Error *err) String str = obj.data.string; return str.size ? syn_check_group(str.data, str.size) : 0; } else if (obj.type == kObjectTypeInteger) { - return MAX((int)obj.data.integer, 0); + int id = (int)obj.data.integer; + return (1 <= id && id <= highlight_num_groups()) ? id : 0; } else { api_set_error(err, kErrorTypeValidation, "Invalid highlight: %s", what); return 0; -- cgit From cce1eb0806cc8c2f75b60aee5841b4750c2258c1 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 18 Aug 2024 07:10:27 +0800 Subject: fix(api): error properly with invalid field in nvim_open_win (#30078) --- src/nvim/api/win_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c index f0b90d8512..996e587446 100644 --- a/src/nvim/api/win_config.c +++ b/src/nvim/api/win_config.c @@ -1038,7 +1038,7 @@ static void parse_border_style(Object style, WinConfig *fconfig, Error *err) static void generate_api_error(win_T *wp, const char *attribute, Error *err) { - if (wp->w_floating) { + if (wp != NULL && wp->w_floating) { api_set_error(err, kErrorTypeValidation, "Missing 'relative' field when reconfiguring floating window %d", wp->handle); -- cgit From a8fbe1d409e08c68b05bc26b096486020ae3162b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 20 Aug 2024 08:20:19 +0800 Subject: fix(decor): don't use separate DecorSignHighlight for url (#30096) --- src/nvim/api/extmark.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index e30ec9a2ca..1673519479 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -687,6 +687,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer if (HAS_KEY(opts, set_extmark, url)) { url = string_to_cstr(opts->url); + has_hl = true; } if (opts->ui_watched) { @@ -758,13 +759,9 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer 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); } - 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); - } if (has_hl) { DecorSignHighlight sh = decor_sh_from_inline(hl); + sh.url = url; decor_range_add_sh(&decor_state, r, c, line2, col2, &sh, true, (uint32_t)ns_id, id); } } else { @@ -788,12 +785,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer } uint32_t decor_indexed = DECOR_ID_INVALID; - if (url != NULL) { - DecorSignHighlight sh = DECOR_SIGN_HIGHLIGHT_INIT; - sh.url = url; - sh.next = decor_indexed; - decor_indexed = decor_put_sh(sh); - } + if (sign.flags & kSHIsSign) { sign.next = decor_indexed; decor_indexed = decor_put_sh(sign); @@ -806,9 +798,11 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer } DecorInline decor = DECOR_INLINE_INIT; - if (decor_alloc || decor_indexed != DECOR_ID_INVALID || schar_high(hl.conceal_char)) { + if (decor_alloc || decor_indexed != DECOR_ID_INVALID || url != NULL + || schar_high(hl.conceal_char)) { if (has_hl) { DecorSignHighlight sh = decor_sh_from_inline(hl); + sh.url = url; sh.next = decor_indexed; decor_indexed = decor_put_sh(sh); } -- cgit From cfdf68a7acde16597fbd896674af68c42361102c Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 8 Aug 2024 10:42:08 +0200 Subject: feat(mbyte): support extended grapheme clusters including more emoji Use the grapheme break algorithm from utf8proc to support grapheme clusters from recent unicode versions. Handle variant selector VS16 turning some codepoints into double-width emoji. This means we need to use ptr2cells rather than char2cells when possible. --- src/nvim/api/extmark.c | 2 +- src/nvim/api/ui.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index 1673519479..d694b64f66 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -571,7 +571,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer String c = opts->conceal; if (c.size > 0) { int ch; - hl.conceal_char = utfc_ptr2schar_len(c.data, (int)c.size, &ch); + hl.conceal_char = utfc_ptr2schar(c.data, &ch); if (!hl.conceal_char || !vim_isprintc(ch)) { api_set_error(err, kErrorTypeValidation, "conceal char has to be printable"); goto error; diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 82a5ff5f8e..a99d97acb8 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -847,7 +847,7 @@ void remote_ui_raw_line(RemoteUI *ui, Integer grid, Integer row, Integer startco char sc_buf[MAX_SCHAR_SIZE]; schar_get(sc_buf, chunk[i]); remote_ui_put(ui, sc_buf); - if (utf_ambiguous_width(utf_ptr2char(sc_buf))) { + if (utf_ambiguous_width(sc_buf)) { ui->client_col = -1; // force cursor update } } -- cgit From 96128a5076b7e45fc01163151401a9e2acdff565 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 2 Sep 2024 15:57:07 +0200 Subject: feat(startup): validate --listen address Problem: `nvim --listen` does not error on EADDRINUSE. #30123 Solution: Now that `$NVIM_LISTEN_ADDRESS` is deprecated and input *only* (instead of the old, ambiguous situation where it was both an input *and* an output), we can be fail fast instead of trying to "recover". This reverts the "recovery" behavior of 704ba4151e7f67999510ee0ac19fdabb595d530c, but that was basically a workaround for the fragility of `$NVIM_LISTEN_ADDRESS`. --- src/nvim/api/ui.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index a99d97acb8..5dc373acdc 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -93,15 +93,15 @@ void remote_ui_free_all_mem(void) } #endif -/// Wait until ui has connected on stdio channel if only_stdio -/// is true, otherwise any channel. +/// Wait until UI has connected. +/// +/// @param only_stdio UI is expected to connect on stdio. void remote_ui_wait_for_attach(bool only_stdio) { if (only_stdio) { Channel *channel = find_channel(CHAN_STDIO); if (!channel) { - // this function should only be called in --embed mode, stdio channel - // can be assumed. + // `only_stdio` implies --embed mode, thus stdio channel can be assumed. abort(); } -- cgit From d1d7d5468091fc71fb85c090da87253efdfcdf08 Mon Sep 17 00:00:00 2001 From: vanaigr Date: Tue, 3 Sep 2024 08:01:42 -0500 Subject: fix(api): nvim_buf_get_text() crashes with large negative column #28740 Problem: crash when calling nvim_buf_get_text() with a large negative start_col: call nvim_buf_get_text(0, 0, -123456789, 0, 0, {}) Solution: clamp start_col after subtracting it from the line length. --- src/nvim/api/private/helpers.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index e00b8c6146..23119f7ada 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -528,21 +528,15 @@ String buf_get_text(buf_T *buf, int64_t lnum, int64_t start_col, int64_t 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"); - return rv; - } + start_col = MIN(MAX(0, start_col), line_length); + end_col = MIN(MAX(0, end_col), line_length); if (start_col > end_col) { - api_set_error(err, kErrorTypeValidation, "start_col must be less than end_col"); - return rv; - } - - if (start_col >= line_length) { + api_set_error(err, kErrorTypeValidation, "start_col must be less than or equal to end_col"); return rv; } - return cstrn_as_string(&bufstr[start_col], (size_t)(end_col - start_col)); + return cbuf_as_string(bufstr + start_col, (size_t)(end_col - start_col)); } void api_free_string(String value) -- cgit From fa99afe35eb5d8cf01d875e12b53165bf1104a60 Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 4 Sep 2024 12:09:42 +0200 Subject: fix(multibyte): handle backspace of wide clusters in replace mode Make utf_head_off more robust against invalid sequences and embedded NUL chars --- src/nvim/api/vim.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 7a4aefc620..630c534a7f 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -28,6 +28,7 @@ #include "nvim/cursor.h" #include "nvim/decoration.h" #include "nvim/drawscreen.h" +#include "nvim/edit.h" #include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" -- cgit From 057d27a9d6ef0bb2ee5130704c45b9e9197e7c36 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 15 Sep 2024 12:20:58 -0700 Subject: refactor: rename "process" => "proc" #30387 Problem: - "process" is often used as a verb (`multiqueue_process_events`), which is ambiguous for cases where it's used as a topic. - The documented naming convention for processes is "proc". - `:help dev-name-common` - Shorter is better, when it doesn't harm readability or discoverability. Solution: Rename "process" => "proc" in all C symbols and module names. --- src/nvim/api/vim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 630c534a7f..fe263d051d 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -70,7 +70,7 @@ #include "nvim/optionstr.h" #include "nvim/os/input.h" #include "nvim/os/os_defs.h" -#include "nvim/os/process.h" +#include "nvim/os/proc.h" #include "nvim/popupmenu.h" #include "nvim/pos_defs.h" #include "nvim/runtime.h" -- cgit From ff85e54939b0aca34a779a2b6381d09db1858b29 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Wed, 18 Sep 2024 04:14:06 -0700 Subject: feat(tui): builtin UI (TUI) sets client info #30397 Problem: The default builtin UI client does not declare its client info. This reduces discoverability and makes it difficult for plugins to identify the UI. Solution: - Call nvim_set_client_info after attaching, as recommended by `:help dev-ui`. - Also set the "pid" field. - Also change `ui_active()` to return a count. Not directly relevant to this commit, but will be useful later. --- src/nvim/api/vim.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index fe263d051d..d10ee91042 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1586,6 +1586,7 @@ Array nvim_get_api_info(uint64_t channel_id, Arena *arena) /// /// @param attributes Arbitrary string:string map of informal client properties. /// Suggested keys: +/// - "pid": Process id. /// - "website": Client homepage URL (e.g. GitHub repository) /// - "license": License description ("Apache 2", "GPLv3", "MIT", …) /// - "logo": URI or path to image, preferably small logo or icon. @@ -1627,7 +1628,7 @@ void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version, /// Gets information about a channel. /// /// @param chan channel_id, or 0 for current channel -/// @returns Dictionary describing a channel, with these keys: +/// @returns Channel info dict with these keys: /// - "id" Channel id. /// - "argv" (optional) Job arguments list. /// - "stream" Stream underlying the channel. @@ -1639,14 +1640,12 @@ void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version, /// - "bytes" Send and receive raw bytes. /// - "terminal" |terminal| instance interprets ASCII sequences. /// - "rpc" |RPC| communication on the channel is active. -/// - "pty" (optional) Name of pseudoterminal. On a POSIX system this -/// is a device path like "/dev/pts/1". If the name is unknown, -/// the key will still be present if a pty is used (e.g. for -/// conpty on Windows). -/// - "buffer" (optional) Buffer with connected |terminal| instance. -/// - "client" (optional) Info about the peer (client on the other end of -/// the RPC channel), if provided by it via -/// |nvim_set_client_info()|. +/// - "pty" (optional) Name of pseudoterminal. On a POSIX system this is a device path like +/// "/dev/pts/1". If unknown, the key will still be present if a pty is used (e.g. +/// for conpty on Windows). +/// - "buffer" (optional) Buffer connected to |terminal| instance. +/// - "client" (optional) Info about the peer (client on the other end of the RPC channel), +/// which it provided via |nvim_set_client_info()|. /// Dictionary nvim_get_chan_info(uint64_t channel_id, Integer chan, Arena *arena, Error *err) FUNC_API_SINCE(4) -- cgit From e697c1b43dfbeab132fee4149157f7abd08c51a0 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 22 Sep 2024 06:02:48 +0800 Subject: fix(paste): improve repeating of pasted text (#30438) - Fixes 'autoindent' being applied during redo. - Makes redoing a large paste significantly faster. - Stores pasted text in the register being recorded. Fix #28561 --- src/nvim/api/vim.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index d10ee91042..4b80369654 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1259,30 +1259,19 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Arena *arena, Error draining = true; goto theend; } - if (!(State & (MODE_CMDLINE | MODE_INSERT)) && (phase == -1 || phase == 1)) { - ResetRedobuff(); - AppendCharToRedobuff('a'); // Dot-repeat. + if (phase == -1 || phase == 1) { + paste_store(kFalse, NULL_STRING, crlf); } // vim.paste() decides if client should cancel. Errors do NOT cancel: we // want to drain remaining chunks (rather than divert them to main input). cancel = (rv.type == kObjectTypeBoolean && !rv.data.boolean); - if (!cancel && !(State & MODE_CMDLINE)) { // Dot-repeat. - for (size_t i = 0; i < lines.size; i++) { - String s = lines.items[i].data.string; - assert(s.size <= INT_MAX); - AppendToRedobuffLit(s.data, (int)s.size); - // readfile()-style: "\n" is indicated by presence of N+1 item. - if (i + 1 < lines.size) { - AppendCharToRedobuff(NL); - } - } - } - if (!(State & (MODE_CMDLINE | MODE_INSERT)) && (phase == -1 || phase == 3)) { - AppendCharToRedobuff(ESC); // Dot-repeat. + if (!cancel) { + paste_store(kNone, data, crlf); } theend: if (cancel || phase == -1 || phase == 3) { // End of paste-stream. draining = false; + paste_store(kTrue, NULL_STRING, crlf); } return !cancel; -- cgit From 29bceb4f758097cc6b66726f1dcd3967ad170e35 Mon Sep 17 00:00:00 2001 From: Evgeni Chasnovski Date: Sun, 22 Sep 2024 13:51:22 +0300 Subject: docs(api): nvim_get_runtime_file preserves 'runtimepath' order #30454 --- src/nvim/api/vim.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 4b80369654..3d60dfa8ab 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -573,10 +573,10 @@ typedef struct { Arena *arena; } RuntimeCookie; -/// Find files in runtime directories +/// Finds files in runtime directories, in 'runtimepath' order. /// /// "name" can contain wildcards. For example -/// nvim_get_runtime_file("colors/*.vim", true) will return all color +/// `nvim_get_runtime_file("colors/*.{vim,lua}", true)` will return all color /// scheme files. Always use forward slashes (/) in the search pattern for /// subdirectories regardless of platform. /// -- cgit From 737f58e23230ea14f1648ac1fc7f442ea0f8563c Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 20 Sep 2024 07:34:50 +0200 Subject: refactor(api)!: rename Dictionary => Dict In the api_info() output: :new|put =map(filter(api_info().functions, '!has_key(v:val,''deprecated_since'')'), 'v:val') ... {'return_type': 'ArrayOf(Integer, 2)', 'name': 'nvim_win_get_position', 'method': v:true, 'parameters': [['Window', 'window']], 'since': 1} The `ArrayOf(Integer, 2)` return type didn't break clients when we added it, which is evidence that clients don't use the `return_type` field, thus renaming Dictionary => Dict in api_info() is not (in practice) a breaking change. --- src/nvim/api/autocmd.c | 10 ++--- src/nvim/api/buffer.c | 8 ++-- src/nvim/api/command.c | 30 +++++++------- src/nvim/api/deprecated.c | 10 ++--- src/nvim/api/extmark.c | 8 ++-- src/nvim/api/keysets_defs.h | 6 +-- src/nvim/api/options.c | 14 +++---- src/nvim/api/private/converter.c | 27 ++++++------ src/nvim/api/private/defs.h | 8 ++-- src/nvim/api/private/helpers.c | 54 ++++++++++++------------ src/nvim/api/private/helpers.h | 10 ++--- src/nvim/api/private/validate.h | 8 ++-- src/nvim/api/ui.c | 15 ++++--- src/nvim/api/vim.c | 90 ++++++++++++++++++++-------------------- src/nvim/api/vimscript.c | 46 ++++++++++---------- src/nvim/api/window.c | 7 ++-- 16 files changed, 172 insertions(+), 179 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c index ca8367b7ce..22932fd1a2 100644 --- a/src/nvim/api/autocmd.c +++ b/src/nvim/api/autocmd.c @@ -67,7 +67,7 @@ static int64_t next_autocmd_id = 1; /// NOTE: When multiple patterns or events are provided, it will find all the autocommands that /// match any combination of them. /// -/// @param opts Dictionary with at least one of the following: +/// @param opts Dict with at least one of the following: /// - group (string|integer): the autocommand group name or id to match against. /// - event (string|array): event or events to match against |autocmd-events|. /// - pattern (string|array): pattern or patterns to match against |autocmd-pattern|. @@ -270,7 +270,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Arena *arena, Error *err) } } - Dictionary autocmd_info = arena_dict(arena, 11); + Dict autocmd_info = arena_dict(arena, 11); if (ap->group != AUGROUP_DEFAULT) { PUT_C(autocmd_info, "group", INTEGER_OBJ(ap->group)); @@ -334,7 +334,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Arena *arena, Error *err) // PUT_C(autocmd_info, "sid", INTEGER_OBJ(ac->script_ctx.sc_sid)); // PUT_C(autocmd_info, "lnum", INTEGER_OBJ(ac->script_ctx.sc_lnum)); - kvi_push(autocmd_list, DICTIONARY_OBJ(autocmd_info)); + kvi_push(autocmd_list, DICT_OBJ(autocmd_info)); } } @@ -621,7 +621,7 @@ void nvim_clear_autocmds(Dict(clear_autocmds) *opts, Arena *arena, Error *err) /// ``` /// /// @param name String: The name of the group -/// @param opts Dictionary Parameters +/// @param opts Dict Parameters /// - clear (bool) optional: defaults to true. Clear existing /// commands if the group already exists |autocmd-groups|. /// @return Integer id of the created group. @@ -686,7 +686,7 @@ void nvim_del_augroup_by_name(String name, Error *err) /// Execute all autocommands for {event} that match the corresponding /// {opts} |autocmd-execute|. /// @param event (String|Array) The event or events to execute -/// @param opts Dictionary of autocommand options: +/// @param opts Dict of autocommand options: /// - group (string|integer) optional: the autocommand group name or /// id to match against. |autocmd-groups|. /// - pattern (string|array) optional: defaults to "*" |autocmd-pattern|. Cannot be used diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index a0678dc3e4..3baf8a97d9 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -866,7 +866,7 @@ Integer nvim_buf_get_changedtick(Buffer buffer, Error *err) /// @param[out] err Error details, if any /// @returns Array of |maparg()|-like dictionaries describing mappings. /// The "buffer" key holds the associated buffer handle. -ArrayOf(Dictionary) nvim_buf_get_keymap(Buffer buffer, String mode, Arena *arena, Error *err) +ArrayOf(Dict) nvim_buf_get_keymap(Buffer buffer, String mode, Arena *arena, Error *err) FUNC_API_SINCE(3) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -1221,14 +1221,14 @@ Object nvim_buf_call(Buffer buffer, LuaRef fun, Error *err) } /// @nodoc -Dictionary nvim__buf_stats(Buffer buffer, Arena *arena, Error *err) +Dict nvim__buf_stats(Buffer buffer, Arena *arena, Error *err) { buf_T *buf = find_buffer_by_handle(buffer, err); if (!buf) { - return (Dictionary)ARRAY_DICT_INIT; + return (Dict)ARRAY_DICT_INIT; } - Dictionary rv = arena_dict(arena, 7); + Dict rv = arena_dict(arena, 7); // Number of times the cached line was flushed. // This should generally not increase while editing the same // line in the same mode. diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index 78be0a2cf7..ab57d5c009 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -46,7 +46,7 @@ /// @param str Command line string to parse. Cannot contain "\n". /// @param opts Optional parameters. Reserved for future use. /// @param[out] err Error details, if any. -/// @return Dictionary containing command information, with these keys: +/// @return Dict containing command information, with these keys: /// - cmd: (string) Command name. /// - range: (array) (optional) Command range ([] []). /// Omitted if command doesn't accept a range. @@ -63,13 +63,13 @@ /// - nargs: (string) Value of |:command-nargs|. /// - nextcmd: (string) Next command if there are multiple commands separated by a |:bar|. /// Empty if there isn't a next command. -/// - magic: (dictionary) Which characters have special meaning in the command arguments. +/// - magic: (dict) Which characters have special meaning in the command arguments. /// - file: (boolean) The command expands filenames. Which means characters such as "%", /// "#" and wildcards are expanded. /// - bar: (boolean) The "|" character is treated as a command separator and the double /// quote character (") is treated as the start of a comment. -/// - mods: (dictionary) |:command-modifiers|. -/// - filter: (dictionary) |:filter|. +/// - mods: (dict) |:command-modifiers|. +/// - filter: (dict) |:filter|. /// - pattern: (string) Filter pattern. Empty string if there is no filter. /// - force: (boolean) Whether filter is inverted or not. /// - silent: (boolean) |:silent|. @@ -230,12 +230,12 @@ Dict(cmd) nvim_parse_cmd(String str, Dict(empty) *opts, Arena *arena, Error *err PUT_KEY(result, cmd, nextcmd, CSTR_AS_OBJ(ea.nextcmd)); // TODO(bfredl): nested keydict would be nice.. - Dictionary mods = arena_dict(arena, 20); + Dict mods = arena_dict(arena, 20); - Dictionary filter = arena_dict(arena, 2); + Dict filter = arena_dict(arena, 2); PUT_C(filter, "pattern", CSTR_TO_ARENA_OBJ(arena, cmdinfo.cmdmod.cmod_filter_pat)); PUT_C(filter, "force", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_filter_force)); - PUT_C(mods, "filter", DICTIONARY_OBJ(filter)); + PUT_C(mods, "filter", DICT_OBJ(filter)); PUT_C(mods, "silent", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_SILENT)); PUT_C(mods, "emsg_silent", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_ERRSILENT)); @@ -272,7 +272,7 @@ Dict(cmd) nvim_parse_cmd(String str, Dict(empty) *opts, Arena *arena, Error *err PUT_KEY(result, cmd, mods, mods); - Dictionary magic = arena_dict(arena, 2); + Dict magic = arena_dict(arena, 2); PUT_C(magic, "file", BOOLEAN_OBJ(cmdinfo.magic.file)); PUT_C(magic, "bar", BOOLEAN_OBJ(cmdinfo.magic.bar)); PUT_KEY(result, cmd, magic, magic); @@ -284,7 +284,7 @@ end: /// Executes an Ex command. /// -/// Unlike |nvim_command()| this command takes a structured Dictionary instead of a String. This +/// Unlike |nvim_command()| this command takes a structured Dict instead of a String. This /// allows for easier construction and manipulation of an Ex command. This also allows for things /// such as having spaces inside a command argument, expanding filenames in a command that otherwise /// doesn't expand filenames, etc. Command arguments may also be Number, Boolean or String. @@ -298,7 +298,7 @@ end: /// @see |nvim_exec2()| /// @see |nvim_command()| /// -/// @param cmd Command to execute. Must be a Dictionary that can contain the same values as +/// @param cmd Command to execute. Must be a Dict that can contain the same values as /// the return value of |nvim_parse_cmd()| except "addr", "nargs" and "nextcmd" /// which are ignored if provided. All values except for "cmd" are optional. /// @param opts Optional parameters. @@ -1166,7 +1166,7 @@ err: /// @param[out] err Error details, if any. /// /// @returns Map of maps describing commands. -Dictionary nvim_get_commands(Dict(get_commands) *opts, Arena *arena, Error *err) +Dict nvim_get_commands(Dict(get_commands) *opts, Arena *arena, Error *err) FUNC_API_SINCE(4) { return nvim_buf_get_commands(-1, opts, arena, err); @@ -1179,25 +1179,25 @@ Dictionary nvim_get_commands(Dict(get_commands) *opts, Arena *arena, Error *err) /// @param[out] err Error details, if any. /// /// @returns Map of maps describing commands. -Dictionary nvim_buf_get_commands(Buffer buffer, Dict(get_commands) *opts, Arena *arena, Error *err) +Dict nvim_buf_get_commands(Buffer buffer, Dict(get_commands) *opts, Arena *arena, Error *err) FUNC_API_SINCE(4) { bool global = (buffer == -1); if (ERROR_SET(err)) { - return (Dictionary)ARRAY_DICT_INIT; + return (Dict)ARRAY_DICT_INIT; } if (global) { if (opts->builtin) { api_set_error(err, kErrorTypeValidation, "builtin=true not implemented"); - return (Dictionary)ARRAY_DICT_INIT; + return (Dict)ARRAY_DICT_INIT; } return commands_array(NULL, arena); } buf_T *buf = find_buffer_by_handle(buffer, err); if (opts->builtin || !buf) { - return (Dictionary)ARRAY_DICT_INIT; + return (Dict)ARRAY_DICT_INIT; } return commands_array(buf, arena); } diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c index a1af354577..6376011106 100644 --- a/src/nvim/api/deprecated.c +++ b/src/nvim/api/deprecated.c @@ -183,11 +183,11 @@ Integer nvim_buf_set_virtual_text(Buffer buffer, Integer src_id, Integer line, A /// @param[out] err Error details, if any /// @return Highlight definition map /// @see nvim_get_hl_by_name -Dictionary nvim_get_hl_by_id(Integer hl_id, Boolean rgb, Arena *arena, Error *err) +Dict nvim_get_hl_by_id(Integer hl_id, Boolean rgb, Arena *arena, Error *err) FUNC_API_SINCE(3) FUNC_API_DEPRECATED_SINCE(9) { - Dictionary dic = ARRAY_DICT_INIT; + Dict dic = ARRAY_DICT_INIT; VALIDATE_INT((syn_get_final_id((int)hl_id) != 0), "highlight id", hl_id, { return dic; }); @@ -204,11 +204,11 @@ Dictionary nvim_get_hl_by_id(Integer hl_id, Boolean rgb, Arena *arena, Error *er /// @param[out] err Error details, if any /// @return Highlight definition map /// @see nvim_get_hl_by_id -Dictionary nvim_get_hl_by_name(String name, Boolean rgb, Arena *arena, Error *err) +Dict nvim_get_hl_by_name(String name, Boolean rgb, Arena *arena, Error *err) FUNC_API_SINCE(3) FUNC_API_DEPRECATED_SINCE(9) { - Dictionary result = ARRAY_DICT_INIT; + Dict result = ARRAY_DICT_INIT; int id = syn_name2id(name.data); VALIDATE_S((id != 0), "highlight name", name.data, { @@ -515,7 +515,7 @@ static int64_t convert_index(int64_t index) /// @param name Option name /// @param[out] err Error details, if any /// @return Option Information -Dictionary nvim_get_option_info(String name, Arena *arena, Error *err) +Dict nvim_get_option_info(String name, Arena *arena, Error *err) FUNC_API_SINCE(7) FUNC_API_DEPRECATED_SINCE(11) { diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index d694b64f66..7786c30624 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -74,10 +74,10 @@ Integer nvim_create_namespace(String name) /// Gets existing, non-anonymous |namespace|s. /// /// @return dict that maps from names to namespace ids. -Dictionary nvim_get_namespaces(Arena *arena) +Dict nvim_get_namespaces(Arena *arena) FUNC_API_SINCE(5) { - Dictionary retval = arena_dict(arena, map_size(&namespace_ids)); + Dict retval = arena_dict(arena, map_size(&namespace_ids)); String name; handle_T id; @@ -158,7 +158,7 @@ static Array extmark_to_array(MTPair extmark, bool id, bool add_dict, bool hl_na if (add_dict) { // TODO(bfredl): coding the size like this is a bit fragile. // We want ArrayOf(Dict(set_extmark)) as the return type.. - Dictionary dict = arena_dict(arena, ARRAY_SIZE(set_extmark_table)); + Dict dict = arena_dict(arena, ARRAY_SIZE(set_extmark_table)); PUT_C(dict, "ns_id", INTEGER_OBJ((Integer)start.ns)); @@ -183,7 +183,7 @@ static Array extmark_to_array(MTPair extmark, bool id, bool add_dict, bool hl_na decor_to_dict_legacy(&dict, mt_decor(start), hl_name, arena); - ADD_C(rv, DICTIONARY_OBJ(dict)); + ADD_C(rv, DICT_OBJ(dict)); } return rv; diff --git a/src/nvim/api/keysets_defs.h b/src/nvim/api/keysets_defs.h index ce4e3d56e1..552612dd13 100644 --- a/src/nvim/api/keysets_defs.h +++ b/src/nvim/api/keysets_defs.h @@ -275,8 +275,8 @@ typedef struct { String reg; Boolean bang; Array args; - Dictionary magic; - Dictionary mods; + Dict magic; + Dict mods; Object nargs; Object addr; Object nextcmd; @@ -293,7 +293,7 @@ typedef struct { Boolean silent; Boolean emsg_silent; Boolean unsilent; - Dictionary filter; + Dict filter; Boolean sandbox; Boolean noautocmd; Boolean browse; diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c index 5adaff8449..1a0edd551e 100644 --- a/src/nvim/api/options.c +++ b/src/nvim/api/options.c @@ -256,13 +256,13 @@ void nvim_set_option_value(uint64_t channel_id, String name, Object value, Dict( /// Gets the option information for all options. /// -/// The dictionary has the full option names as keys and option metadata -/// dictionaries as detailed at |nvim_get_option_info2()|. +/// The dict has the full option names as keys and option metadata dicts as detailed at +/// |nvim_get_option_info2()|. /// /// @see |nvim_get_commands()| /// -/// @return dictionary of all options -Dictionary nvim_get_all_options_info(Arena *arena, Error *err) +/// @return dict of all options +Dict nvim_get_all_options_info(Arena *arena, Error *err) FUNC_API_SINCE(7) { return get_all_vimoptions(arena); @@ -270,7 +270,7 @@ Dictionary nvim_get_all_options_info(Arena *arena, Error *err) /// Gets the option information for one option from arbitrary buffer or window /// -/// Resulting dictionary has keys: +/// Resulting dict has keys: /// - name: Name of the option (like 'filetype') /// - shortname: Shortened name of the option (like 'ft') /// - type: type of option ("string", "number" or "boolean") @@ -301,7 +301,7 @@ Dictionary nvim_get_all_options_info(Arena *arena, Error *err) /// Implies {scope} is "local". /// @param[out] err Error details, if any /// @return Option Information -Dictionary nvim_get_option_info2(String name, Dict(option) *opts, Arena *arena, Error *err) +Dict nvim_get_option_info2(String name, Dict(option) *opts, Arena *arena, Error *err) FUNC_API_SINCE(11) { OptIndex opt_idx = 0; @@ -310,7 +310,7 @@ Dictionary nvim_get_option_info2(String name, Dict(option) *opts, Arena *arena, void *from = NULL; if (!validate_option_value_args(opts, name.data, &opt_idx, &scope, &req_scope, &from, NULL, err)) { - return (Dictionary)ARRAY_DICT_INIT; + return (Dict)ARRAY_DICT_INIT; } buf_T *buf = (req_scope == kOptReqBuf) ? (buf_T *)from : curbuf; diff --git a/src/nvim/api/private/converter.c b/src/nvim/api/private/converter.c index a1c5816a49..59e7373f68 100644 --- a/src/nvim/api/private/converter.c +++ b/src/nvim/api/private/converter.c @@ -94,8 +94,7 @@ static Object typval_cbuf_to_obj(EncodedData *edata, const char *data, size_t le kvi_push(edata->stack, ARRAY_OBJ(((Array) { .capacity = 0, .size = 0 }))) #define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \ - kvi_push(edata->stack, \ - DICTIONARY_OBJ(((Dictionary) { .capacity = 0, .size = 0 }))) + kvi_push(edata->stack, DICT_OBJ(((Dict) { .capacity = 0, .size = 0 }))) static inline void typval_encode_list_start(EncodedData *const edata, const size_t len) FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL @@ -137,7 +136,7 @@ static inline void typval_encode_list_end(EncodedData *const edata) static inline void typval_encode_dict_start(EncodedData *const edata, const size_t len) FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL { - kvi_push(edata->stack, DICTIONARY_OBJ(arena_dict(edata->arena, len))); + kvi_push(edata->stack, DICT_OBJ(arena_dict(edata->arena, len))); } #define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \ @@ -152,13 +151,13 @@ static inline void typval_encode_after_key(EncodedData *const edata) { Object key = kv_pop(edata->stack); Object *const dict = &kv_last(edata->stack); - assert(dict->type == kObjectTypeDictionary); - assert(dict->data.dictionary.size < dict->data.dictionary.capacity); + assert(dict->type == kObjectTypeDict); + assert(dict->data.dict.size < dict->data.dict.capacity); if (key.type == kObjectTypeString) { - dict->data.dictionary.items[dict->data.dictionary.size].key + dict->data.dict.items[dict->data.dict.size].key = key.data.string; } else { - dict->data.dictionary.items[dict->data.dictionary.size].key + dict->data.dict.items[dict->data.dict.size].key = STATIC_CSTR_AS_STRING("__INVALID_KEY__"); } } @@ -171,9 +170,9 @@ static inline void typval_encode_between_dict_items(EncodedData *const edata) { Object val = kv_pop(edata->stack); Object *const dict = &kv_last(edata->stack); - assert(dict->type == kObjectTypeDictionary); - assert(dict->data.dictionary.size < dict->data.dictionary.capacity); - dict->data.dictionary.items[dict->data.dictionary.size++].value = val; + assert(dict->type == kObjectTypeDict); + assert(dict->data.dict.size < dict->data.dict.capacity); + dict->data.dict.items[dict->data.dict.size++].value = val; } #define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) \ @@ -185,7 +184,7 @@ static inline void typval_encode_dict_end(EncodedData *const edata) typval_encode_between_dict_items(edata); #ifndef NDEBUG const Object *const dict = &kv_last(edata->stack); - assert(dict->data.dictionary.size == dict->data.dictionary.capacity); + assert(dict->data.dict.size == dict->data.dict.capacity); #endif } @@ -325,11 +324,11 @@ void object_to_vim_take_luaref(Object *obj, typval_T *tv, bool take_luaref, Erro break; } - case kObjectTypeDictionary: { + case kObjectTypeDict: { dict_T *const dict = tv_dict_alloc(); - for (uint32_t i = 0; i < obj->data.dictionary.size; i++) { - KeyValuePair *item = &obj->data.dictionary.items[i]; + for (uint32_t i = 0; i < obj->data.dict.size; i++) { + KeyValuePair *item = &obj->data.dict.items[i]; String key = item->key; dictitem_T *const di = tv_dict_item_alloc(key.data); object_to_vim_take_luaref(&item->value, &di->di_tv, take_luaref, err); diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h index ac3404cf86..26d5ac09a8 100644 --- a/src/nvim/api/private/defs.h +++ b/src/nvim/api/private/defs.h @@ -17,7 +17,7 @@ #ifdef INCLUDE_GENERATED_DECLARATIONS # define ArrayOf(...) Array -# define DictionaryOf(...) Dictionary +# define DictOf(...) Dict # define Dict(name) KeyDict_##name # define DictHash(name) KeyDict_##name##_get_field # define DictKey(name) @@ -88,7 +88,7 @@ typedef struct object Object; typedef kvec_t(Object) Array; typedef struct key_value_pair KeyValuePair; -typedef kvec_t(KeyValuePair) Dictionary; +typedef kvec_t(KeyValuePair) Dict; typedef kvec_t(String) StringArray; @@ -99,7 +99,7 @@ typedef enum { kObjectTypeFloat, kObjectTypeString, kObjectTypeArray, - kObjectTypeDictionary, + kObjectTypeDict, kObjectTypeLuaRef, // EXT types, cannot be split or reordered, see #EXT_OBJECT_TYPE_SHIFT kObjectTypeBuffer, @@ -127,7 +127,7 @@ struct object { Float floating; String string; Array array; - Dictionary dictionary; + Dict dict; LuaRef luaref; } data; }; diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 23119f7ada..e1fb4ed732 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -198,7 +198,7 @@ dictitem_T *dict_check_writable(dict_T *dict, String key, bool del, Error *err) api_set_error(err, kErrorTypeException, "Key is fixed: %s", key.data); } } else if (dict->dv_lock) { - api_set_error(err, kErrorTypeException, "Dictionary is locked"); + api_set_error(err, kErrorTypeException, "Dict is locked"); } else if (key.size == 0) { api_set_error(err, kErrorTypeValidation, "Key name is empty"); } else if (key.size > INT_MAX) { @@ -551,9 +551,9 @@ Array arena_array(Arena *arena, size_t max_size) return arr; } -Dictionary arena_dict(Arena *arena, size_t max_size) +Dict arena_dict(Arena *arena, size_t max_size) { - Dictionary dict = ARRAY_DICT_INIT; + Dict dict = ARRAY_DICT_INIT; kv_fixsize_arena(arena, dict, max_size); return dict; } @@ -596,8 +596,8 @@ void api_free_object(Object value) api_free_array(value.data.array); break; - case kObjectTypeDictionary: - api_free_dictionary(value.data.dictionary); + case kObjectTypeDict: + api_free_dict(value.data.dict); break; case kObjectTypeLuaRef: @@ -615,7 +615,7 @@ void api_free_array(Array value) xfree(value.items); } -void api_free_dictionary(Dictionary value) +void api_free_dict(Dict value) { for (size_t i = 0; i < value.size; i++) { api_free_string(value.items[i].key); @@ -648,7 +648,7 @@ Object api_metadata(void) Arena arena = ARENA_EMPTY; Error err = ERROR_INIT; metadata = unpack((char *)packed_api_metadata, sizeof(packed_api_metadata), &arena, &err); - if (ERROR_SET(&err) || metadata.type != kObjectTypeDictionary) { + if (ERROR_SET(&err) || metadata.type != kObjectTypeDict) { abort(); } mem_for_metadata = arena_finish(&arena); @@ -684,9 +684,9 @@ Array copy_array(Array array, Arena *arena) return rv; } -Dictionary copy_dictionary(Dictionary dict, Arena *arena) +Dict copy_dict(Dict dict, Arena *arena) { - Dictionary rv = arena_dict(arena, dict.size); + Dict rv = arena_dict(arena, dict.size); for (size_t i = 0; i < dict.size; i++) { KeyValuePair item = dict.items[i]; PUT_C(rv, copy_string(item.key, arena).data, copy_object(item.value, arena)); @@ -713,8 +713,8 @@ Object copy_object(Object obj, Arena *arena) case kObjectTypeArray: return ARRAY_OBJ(copy_array(obj.data.array, arena)); - case kObjectTypeDictionary: - return DICTIONARY_OBJ(copy_dictionary(obj.data.dictionary, arena)); + case kObjectTypeDict: + return DICT_OBJ(copy_dict(obj.data.dict, arena)); case kObjectTypeLuaRef: return LUAREF_OBJ(api_new_luaref(obj.data.luaref)); @@ -791,7 +791,7 @@ char *api_typename(ObjectType t) return "String"; case kObjectTypeArray: return "Array"; - case kObjectTypeDictionary: + case kObjectTypeDict: return "Dict"; case kObjectTypeLuaRef: return "Function"; @@ -844,7 +844,7 @@ free_exit: } // see also nlua_pop_keydict for the lua specific implementation -bool api_dict_to_keydict(void *retval, FieldHashfn hashy, Dictionary dict, Error *err) +bool api_dict_to_keydict(void *retval, FieldHashfn hashy, Dict dict, Error *err) { for (size_t i = 0; i < dict.size; i++) { String k = dict.items[i].key; @@ -908,13 +908,13 @@ bool api_dict_to_keydict(void *retval, FieldHashfn hashy, Dictionary dict, Error return false; }); *(Array *)mem = value->data.array; - } else if (field->type == kObjectTypeDictionary) { - Dictionary *val = (Dictionary *)mem; + } else if (field->type == kObjectTypeDict) { + Dict *val = (Dict *)mem; // allow empty array as empty dict for lua (directly or via lua-client RPC) if (value->type == kObjectTypeArray && value->data.array.size == 0) { - *val = (Dictionary)ARRAY_DICT_INIT; - } else if (value->type == kObjectTypeDictionary) { - *val = value->data.dictionary; + *val = (Dict)ARRAY_DICT_INIT; + } else if (value->type == kObjectTypeDict) { + *val = value->data.dict; } else { api_err_exp(err, field->str, api_typename((ObjectType)field->type), api_typename(value->type)); @@ -941,9 +941,9 @@ bool api_dict_to_keydict(void *retval, FieldHashfn hashy, Dictionary dict, Error return true; } -Dictionary api_keydict_to_dict(void *value, KeySetLink *table, size_t max_size, Arena *arena) +Dict api_keydict_to_dict(void *value, KeySetLink *table, size_t max_size, Arena *arena) { - Dictionary rv = arena_dict(arena, max_size); + Dict rv = arena_dict(arena, max_size); for (size_t i = 0; table[i].str; i++) { KeySetLink *field = &table[i]; bool is_set = true; @@ -971,8 +971,8 @@ Dictionary api_keydict_to_dict(void *value, KeySetLink *table, size_t max_size, val = STRING_OBJ(*(String *)mem); } else if (field->type == kObjectTypeArray) { val = ARRAY_OBJ(*(Array *)mem); - } else if (field->type == kObjectTypeDictionary) { - val = DICTIONARY_OBJ(*(Dictionary *)mem); + } else if (field->type == kObjectTypeDict) { + val = DICT_OBJ(*(Dict *)mem); } else if (field->type == kObjectTypeBuffer || field->type == kObjectTypeWindow || field->type == kObjectTypeTabpage) { val.data.integer = *(handle_T *)mem; @@ -1002,8 +1002,8 @@ void api_luarefs_free_object(Object value) api_luarefs_free_array(value.data.array); break; - case kObjectTypeDictionary: - api_luarefs_free_dict(value.data.dictionary); + case kObjectTypeDict: + api_luarefs_free_dict(value.data.dict); break; default: @@ -1019,8 +1019,8 @@ void api_luarefs_free_keydict(void *dict, KeySetLink *table) api_luarefs_free_object(*(Object *)mem); } else if (table[i].type == kObjectTypeLuaRef) { api_free_luaref(*(LuaRef *)mem); - } else if (table[i].type == kObjectTypeDictionary) { - api_luarefs_free_dict(*(Dictionary *)mem); + } else if (table[i].type == kObjectTypeDict) { + api_luarefs_free_dict(*(Dict *)mem); } } } @@ -1032,7 +1032,7 @@ void api_luarefs_free_array(Array value) } } -void api_luarefs_free_dict(Dictionary value) +void api_luarefs_free_dict(Dict value) { for (size_t i = 0; i < value.size; i++) { api_luarefs_free_object(value.items[i].value); diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h index 7eda8ffaf6..57932e067e 100644 --- a/src/nvim/api/private/helpers.h +++ b/src/nvim/api/private/helpers.h @@ -53,9 +53,9 @@ .type = kObjectTypeArray, \ .data.array = a }) -#define DICTIONARY_OBJ(d) ((Object) { \ - .type = kObjectTypeDictionary, \ - .data.dictionary = d }) +#define DICT_OBJ(d) ((Object) { \ + .type = kObjectTypeDict, \ + .data.dict = d }) #define LUAREF_OBJ(r) ((Object) { \ .type = kObjectTypeLuaRef, \ @@ -90,7 +90,7 @@ name.items = name##__items; \ #define MAXSIZE_TEMP_DICT(name, maxsize) \ - Dictionary name = ARRAY_DICT_INIT; \ + Dict name = ARRAY_DICT_INIT; \ KeyValuePair name##__items[maxsize]; \ name.capacity = maxsize; \ name.items = name##__items; \ @@ -121,7 +121,7 @@ typedef kvec_withinit_t(Object, 16) ArrayBuilder; #define api_init_tabpage #define api_init_object = NIL #define api_init_array = ARRAY_DICT_INIT -#define api_init_dictionary = ARRAY_DICT_INIT +#define api_init_dict = ARRAY_DICT_INIT #define KEYDICT_INIT { 0 } diff --git a/src/nvim/api/private/validate.h b/src/nvim/api/private/validate.h index 2c1d1a241d..67af8adea8 100644 --- a/src/nvim/api/private/validate.h +++ b/src/nvim/api/private/validate.h @@ -42,7 +42,7 @@ #define VALIDATE_T(name, expected_t, actual_t, code) \ do { \ - STATIC_ASSERT(expected_t != kObjectTypeDictionary, "use VALIDATE_T_DICT"); \ + STATIC_ASSERT(expected_t != kObjectTypeDict, "use VALIDATE_T_DICT"); \ if (expected_t != actual_t) { \ api_err_exp(err, name, api_typename(expected_t), api_typename(actual_t)); \ code; \ @@ -52,7 +52,7 @@ /// Checks that `obj_` has type `expected_t`. #define VALIDATE_T2(obj_, expected_t, code) \ do { \ - STATIC_ASSERT(expected_t != kObjectTypeDictionary, "use VALIDATE_T_DICT"); \ + STATIC_ASSERT(expected_t != kObjectTypeDict, "use VALIDATE_T_DICT"); \ if ((obj_).type != expected_t) { \ api_err_exp(err, STR(obj_), api_typename(expected_t), api_typename((obj_).type)); \ code; \ @@ -62,11 +62,11 @@ /// Checks that `obj_` has Dict type. Also allows empty Array in a Lua context. #define VALIDATE_T_DICT(name, obj_, code) \ do { \ - if ((obj_).type != kObjectTypeDictionary \ + if ((obj_).type != kObjectTypeDict \ && !(channel_id == LUA_INTERNAL_CALL \ && (obj_).type == kObjectTypeArray \ && (obj_).data.array.size == 0)) { \ - api_err_exp(err, name, api_typename(kObjectTypeDictionary), api_typename((obj_).type)); \ + api_err_exp(err, name, api_typename(kObjectTypeDict), api_typename((obj_).type)); \ code; \ } \ } while (0) diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 5dc373acdc..b09a9ed253 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -128,8 +128,7 @@ void remote_ui_wait_for_attach(bool only_stdio) /// @param height Requested screen rows /// @param options |ui-option| map /// @param[out] err Error details, if any -void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictionary options, - Error *err) +void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dict options, Error *err) FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY { if (map_has(uint64_t, &connected_uis, channel_id)) { @@ -687,8 +686,8 @@ void remote_ui_hl_attr_define(RemoteUI *ui, Integer id, HlAttrs rgb_attrs, HlAtt PUT_C(rgb, "url", CSTR_AS_OBJ(url)); } - ADD_C(args, DICTIONARY_OBJ(rgb)); - ADD_C(args, DICTIONARY_OBJ(cterm)); + ADD_C(args, DICT_OBJ(rgb)); + ADD_C(args, DICT_OBJ(cterm)); if (ui->ui_ext[kUIHlState]) { ADD_C(args, ARRAY_OBJ(info)); @@ -709,7 +708,7 @@ void remote_ui_highlight_set(RemoteUI *ui, int 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)); + ADD_C(args, DICT_OBJ(dict)); push_call(ui, "highlight_set", args); } @@ -920,11 +919,11 @@ static Array translate_contents(RemoteUI *ui, Array contents, Arena *arena) Array new_item = arena_array(arena, 2); int attr = (int)item.items[0].data.integer; if (attr) { - Dictionary rgb_attrs = arena_dict(arena, HLATTRS_DICT_SIZE); + Dict rgb_attrs = arena_dict(arena, HLATTRS_DICT_SIZE); hlattrs2dict(&rgb_attrs, NULL, syn_attr2entry(attr), ui->rgb, false); - ADD_C(new_item, DICTIONARY_OBJ(rgb_attrs)); + ADD_C(new_item, DICT_OBJ(rgb_attrs)); } else { - ADD_C(new_item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT)); + ADD_C(new_item, DICT_OBJ((Dict)ARRAY_DICT_INIT)); } ADD_C(new_item, item.items[1]); ADD_C(new_contents, ARRAY_OBJ(new_item)); diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 3d60dfa8ab..c1add75af9 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -117,7 +117,7 @@ Integer nvim_get_hl_id_by_name(String name) /// @param[out] err Error details, if any. /// @return Highlight groups as a map from group name to a highlight definition map as in |nvim_set_hl()|, /// or only a single highlight definition map if requested by name or id. -Dictionary nvim_get_hl(Integer ns_id, Dict(get_highlight) *opts, Arena *arena, Error *err) +Dict nvim_get_hl(Integer ns_id, Dict(get_highlight) *opts, Arena *arena, Error *err) FUNC_API_SINCE(11) { return ns_get_hl_defs((NS)ns_id, opts, arena, err); @@ -526,13 +526,13 @@ Object nvim_exec_lua(String code, Array args, Arena *arena, 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, Arena *arena, Error *err) +Object nvim_notify(String msg, Integer log_level, Dict opts, Arena *arena, Error *err) FUNC_API_SINCE(7) { MAXSIZE_TEMP_ARRAY(args, 3); ADD_C(args, STRING_OBJ(msg)); ADD_C(args, INTEGER_OBJ(log_level)); - ADD_C(args, DICTIONARY_OBJ(opts)); + ADD_C(args, DICT_OBJ(opts)); return NLUA_EXEC_STATIC("return vim.notify(...)", args, kRetObject, arena, err); } @@ -1350,10 +1350,10 @@ Integer nvim_get_color_by_name(String name) /// (e.g. 65535). /// /// @return Map of color names and RGB values. -Dictionary nvim_get_color_map(Arena *arena) +Dict nvim_get_color_map(Arena *arena) FUNC_API_SINCE(1) { - Dictionary colors = arena_dict(arena, ARRAY_SIZE(color_name_table)); + Dict colors = arena_dict(arena, ARRAY_SIZE(color_name_table)); for (int i = 0; color_name_table[i].name != NULL; i++) { PUT_C(colors, color_name_table[i].name, INTEGER_OBJ(color_name_table[i].color)); @@ -1369,7 +1369,7 @@ Dictionary nvim_get_color_map(Arena *arena) /// @param[out] err Error details, if any /// /// @return map of global |context|. -Dictionary nvim_get_context(Dict(context) *opts, Arena *arena, Error *err) +Dict nvim_get_context(Dict(context) *opts, Arena *arena, Error *err) FUNC_API_SINCE(6) { Array types = ARRAY_DICT_INIT; @@ -1396,7 +1396,7 @@ Dictionary nvim_get_context(Dict(context) *opts, Arena *arena, Error *err) int_types |= kCtxFuncs; } else { VALIDATE_S(false, "type", s, { - return (Dictionary)ARRAY_DICT_INIT; + return (Dict)ARRAY_DICT_INIT; }); } } @@ -1405,7 +1405,7 @@ Dictionary nvim_get_context(Dict(context) *opts, Arena *arena, Error *err) Context ctx = CONTEXT_INIT; ctx_save(&ctx, int_types); - Dictionary dict = ctx_to_dict(&ctx, arena); + Dict dict = ctx_to_dict(&ctx, arena); ctx_free(&ctx); return dict; } @@ -1413,7 +1413,7 @@ Dictionary nvim_get_context(Dict(context) *opts, Arena *arena, Error *err) /// Sets the current editor state from the given |context| map. /// /// @param dict |Context| map. -Object nvim_load_context(Dictionary dict, Error *err) +Object nvim_load_context(Dict dict, Error *err) FUNC_API_SINCE(6) { Context ctx = CONTEXT_INIT; @@ -1435,11 +1435,11 @@ Object nvim_load_context(Dictionary dict, Error *err) /// Gets the current mode. |mode()| /// "blocking" is true if Nvim is waiting for input. /// -/// @returns Dictionary { "mode": String, "blocking": Boolean } -Dictionary nvim_get_mode(Arena *arena) +/// @returns Dict { "mode": String, "blocking": Boolean } +Dict nvim_get_mode(Arena *arena) FUNC_API_SINCE(2) FUNC_API_FAST { - Dictionary rv = arena_dict(arena, 2); + Dict rv = arena_dict(arena, 2); char *modestr = arena_alloc(arena, MODE_MAX_LENGTH, false); get_mode(modestr); bool blocked = input_blocking(); @@ -1455,7 +1455,7 @@ Dictionary nvim_get_mode(Arena *arena) /// @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, Arena *arena) +ArrayOf(Dict) nvim_get_keymap(String mode, Arena *arena) FUNC_API_SINCE(3) { return keymap_array(mode, NULL, arena); @@ -1514,7 +1514,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). +/// 1 is the |api-metadata| map (Dict). /// /// @returns 2-tuple `[{channel-id}, {api-metadata}]` Array nvim_get_api_info(uint64_t channel_id, Arena *arena) @@ -1543,7 +1543,7 @@ 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 +/// @param version Dict describing the version, with these /// (optional) keys: /// - "major" major version (defaults to 0 if not set, for no release yet) /// - "minor" minor version @@ -1582,8 +1582,8 @@ Array nvim_get_api_info(uint64_t channel_id, Arena *arena) /// .png or .svg format is preferred. /// /// @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, Arena *arena, Error *err) +void nvim_set_client_info(uint64_t channel_id, String name, Dict version, String type, Dict methods, + Dict attributes, Arena *arena, Error *err) FUNC_API_SINCE(4) FUNC_API_REMOTE_ONLY { MAXSIZE_TEMP_DICT(info, 5); @@ -1597,7 +1597,7 @@ void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version, } } if (!has_major) { - Dictionary v = arena_dict(arena, version.size + 1); + Dict 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; @@ -1605,13 +1605,13 @@ void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version, PUT_C(v, "major", INTEGER_OBJ(0)); version = v; } - PUT_C(info, "version", DICTIONARY_OBJ(version)); + PUT_C(info, "version", DICT_OBJ(version)); PUT_C(info, "type", STRING_OBJ(type)); - PUT_C(info, "methods", DICTIONARY_OBJ(methods)); - PUT_C(info, "attributes", DICTIONARY_OBJ(attributes)); + PUT_C(info, "methods", DICT_OBJ(methods)); + PUT_C(info, "attributes", DICT_OBJ(attributes)); - rpc_set_client_info(channel_id, copy_dictionary(info, NULL)); + rpc_set_client_info(channel_id, copy_dict(info, NULL)); } /// Gets information about a channel. @@ -1636,11 +1636,11 @@ void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version, /// - "client" (optional) Info about the peer (client on the other end of the RPC channel), /// which it provided via |nvim_set_client_info()|. /// -Dictionary nvim_get_chan_info(uint64_t channel_id, Integer chan, Arena *arena, Error *err) +Dict 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 (Dict)ARRAY_DICT_INIT; } if (chan == 0 && !is_internal_call(channel_id)) { @@ -1737,17 +1737,17 @@ Array nvim__id_array(Array arr, Arena *arena) return copy_array(arr, arena); } -/// Returns dictionary given as argument. +/// Returns dict given as argument. /// /// This API function is used for testing. One should not rely on its presence /// in plugins. /// -/// @param[in] dct Dictionary to return. +/// @param[in] dct Dict to return. /// /// @return its argument. -Dictionary nvim__id_dictionary(Dictionary dct, Arena *arena) +Dict nvim__id_dict(Dict dct, Arena *arena) { - return copy_dictionary(dct, arena); + return copy_dict(dct, arena); } /// Returns floating-point value given as argument. @@ -1766,9 +1766,9 @@ Float nvim__id_float(Float flt) /// Gets internal stats. /// /// @return Map of various internal stats. -Dictionary nvim__stats(Arena *arena) +Dict nvim__stats(Arena *arena) { - Dictionary rv = arena_dict(arena, 6); + Dict rv = arena_dict(arena, 6); 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())); @@ -1845,8 +1845,8 @@ Object nvim_get_proc(Integer pid, Arena *arena, Error *err) }); #ifdef MSWIN - rvobj = DICTIONARY_OBJ(os_proc_info((int)pid, arena)); - if (rvobj.data.dictionary.size == 0) { // Process not found. + rvobj = DICT_OBJ(os_proc_info((int)pid, arena)); + if (rvobj.data.dict.size == 0) { // Process not found. return NIL; } #else @@ -1856,7 +1856,7 @@ Object nvim_get_proc(Integer pid, Arena *arena, Error *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) { + } else if (o.type == kObjectTypeDict) { rvobj = o; } else if (!ERROR_SET(err)) { api_set_error(err, kErrorTypeException, @@ -1920,7 +1920,7 @@ Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Arena *arena, E schar_get(sc_buf, g->chars[off]); ADD_C(ret, CSTR_AS_OBJ(sc_buf)); int attr = g->attrs[off]; - ADD_C(ret, DICTIONARY_OBJ(hl_get_attr_by_id(attr, true, arena, err))); + ADD_C(ret, DICT_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, arena))); @@ -2063,18 +2063,18 @@ Array nvim_get_mark(String name, Dict(empty) *opts, Arena *arena, Error *err) /// - use_statuscol_lnum: (number) Evaluate statuscolumn for this line number instead of statusline. /// /// @param[out] err Error details, if any. -/// @return Dictionary containing statusline information, with these keys: +/// @return Dict containing statusline information, with these keys: /// - str: (string) Characters that will be displayed on the statusline. /// - width: (number) Display width of the statusline. /// - highlights: Array containing highlight information of the statusline. Only included when /// the "highlights" key in {opts} is true. Each element of the array is a -/// |Dictionary| with these keys: +/// |Dict| 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, Arena *arena, Error *err) +Dict 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; + Dict result = ARRAY_DICT_INIT; int maxwidth; schar_T fillchar = 0; @@ -2200,18 +2200,18 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Arena * // 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 = arena_dict(arena, 2); + Dict 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_C(hl_info, "start", INTEGER_OBJ(0)); PUT_C(hl_info, "group", CSTR_AS_OBJ(grpname)); - ADD_C(hl_values, DICTIONARY_OBJ(hl_info)); + ADD_C(hl_values, DICT_OBJ(hl_info)); } for (stl_hlrec_t *sp = hltab; sp->start != NULL; sp++) { - Dictionary hl_info = arena_dict(arena, 2); + Dict hl_info = arena_dict(arena, 2); PUT_C(hl_info, "start", INTEGER_OBJ(sp->start - buf)); @@ -2225,7 +2225,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Arena * grpname = arena_memdupz(arena, user_group, strlen(user_group)); } PUT_C(hl_info, "group", CSTR_AS_OBJ(grpname)); - ADD_C(hl_values, DICTIONARY_OBJ(hl_info)); + ADD_C(hl_values, DICT_OBJ(hl_info)); } PUT_C(result, "highlights", ARRAY_OBJ(hl_values)); } @@ -2251,12 +2251,12 @@ void nvim_error_event(uint64_t channel_id, Integer lvl, String data) /// @param index Completion candidate index /// @param opts Optional parameters. /// - info: (string) info text. -/// @return Dictionary containing these keys: +/// @return Dict 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) +Dict nvim__complete_set(Integer index, Dict(complete_set) *opts, Arena *arena) { - Dictionary rv = arena_dict(arena, 2); + Dict 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) { diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c index 124c26d175..165cc93fbe 100644 --- a/src/nvim/api/vimscript.c +++ b/src/nvim/api/vimscript.c @@ -48,12 +48,12 @@ /// - output: (boolean, default false) Whether to capture and return /// all (non-error, non-shell |:!|) output. /// @param[out] err Error details (Vim error), if any -/// @return Dictionary containing information about execution, with these keys: +/// @return Dict containing information about execution, with these keys: /// - output: (string|nil) Output if `opts.output` is true. -Dictionary nvim_exec2(uint64_t channel_id, String src, Dict(exec_opts) *opts, Error *err) +Dict nvim_exec2(uint64_t channel_id, String src, Dict(exec_opts) *opts, Error *err) FUNC_API_SINCE(11) FUNC_API_RET_ALLOC { - Dictionary result = ARRAY_DICT_INIT; + Dict result = ARRAY_DICT_INIT; String output = exec_impl(channel_id, src, opts, err); if (ERROR_SET(err)) { @@ -140,8 +140,7 @@ void nvim_command(String command, Error *err) try_end(err); } -/// Evaluates a Vimscript |expression|. -/// Dictionaries and Lists are recursively expanded. +/// Evaluates a Vimscript |expression|. Dicts and Lists are recursively expanded. /// /// On execution error: fails with Vimscript error, updates v:errmsg. /// @@ -270,7 +269,7 @@ Object nvim_call_function(String fn, Array args, Arena *arena, Error *err) /// /// On execution error: fails with Vimscript error, updates v:errmsg. /// -/// @param dict Dictionary, or String evaluating to a Vimscript |self| dict +/// @param dict Dict, or String evaluating to a Vimscript |self| dict /// @param fn Name of the function defined on the Vimscript dict /// @param args Function arguments packed in an Array /// @param[out] err Error details, if any @@ -297,12 +296,11 @@ Object nvim_call_dict_function(Object dict, String fn, Array args, Arena *arena, // refcount of a dict. Not necessary for a RPC dict. mustfree = true; break; - case kObjectTypeDictionary: + case kObjectTypeDict: object_to_vim(dict, &rettv, err); break; default: - api_set_error(err, kErrorTypeValidation, - "dict argument type must be String or Dictionary"); + api_set_error(err, kErrorTypeValidation, "dict argument type must be String or Dict"); return rv; } dict_T *self_dict = rettv.vval.v_dict; @@ -311,7 +309,7 @@ Object nvim_call_dict_function(Object dict, String fn, Array args, Arena *arena, goto end; } - if (fn.data && fn.size > 0 && dict.type != kObjectTypeDictionary) { + if (fn.data && fn.size > 0 && dict.type != kObjectTypeDict) { dictitem_T *const di = tv_dict_find(self_dict, fn.data, (ptrdiff_t)fn.size); if (di == NULL) { api_set_error(err, kErrorTypeValidation, "Not found: %s", fn.data); @@ -377,8 +375,8 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack; /// one should highlight region [start_col, end_col)). /// /// @return -/// - AST: top-level dictionary with these keys: -/// - "error": Dictionary with error, present only if parser saw some +/// - AST: top-level dict with these keys: +/// - "error": Dict with error, present only if parser saw some /// error. Contains the following keys: /// - "message": String, error message in printf format, translated. /// Must contain exactly one "%.*s". @@ -387,7 +385,7 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack; /// that should be equal to the length of expr string. /// ("Successfully parsed" here means "participated in AST /// creation", not "till the first error".) -/// - "ast": AST, either nil or a dictionary with these keys: +/// - "ast": AST, either nil or a dict with these keys: /// - "type": node type, one of the value names from ExprASTNodeType /// stringified without "kExprNode" prefix. /// - "start": a pair `[line, column]` describing where node is "started" @@ -427,8 +425,7 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack; /// - "svalue": String, value for "SingleQuotedString" and /// "DoubleQuotedString" nodes. /// @param[out] err Error details, if any -Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, Arena *arena, - Error *err) +Dict nvim_parse_expression(String expr, String flags, Boolean highlight, Arena *arena, Error *err) FUNC_API_SINCE(4) FUNC_API_FAST { int pflags = 0; @@ -443,11 +440,11 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, A case NUL: api_set_error(err, kErrorTypeValidation, "Invalid flag: '\\0' (%u)", (unsigned)flags.data[i]); - return (Dictionary)ARRAY_DICT_INIT; + return (Dict)ARRAY_DICT_INIT; default: api_set_error(err, kErrorTypeValidation, "Invalid flag: '%c' (%u)", flags.data[i], (unsigned)flags.data[i]); - return (Dictionary)ARRAY_DICT_INIT; + return (Dict)ARRAY_DICT_INIT; } } ParserLine parser_lines[] = { @@ -471,15 +468,15 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, A + (size_t)highlight // "highlight" + 0); - Dictionary ret = arena_dict(arena, ret_size); + Dict ret = arena_dict(arena, ret_size); PUT_C(ret, "len", INTEGER_OBJ((Integer)(pstate.pos.line == 1 ? parser_lines[0].size : pstate.pos.col))); if (east.err.msg != NULL) { - Dictionary err_dict = arena_dict(arena, 2); + Dict err_dict = arena_dict(arena, 2); PUT_C(err_dict, "message", CSTR_TO_ARENA_OBJ(arena, east.err.msg)); PUT_C(err_dict, "arg", CBUF_TO_ARENA_OBJ(arena, east.err.arg, (size_t)east.err.arg_len)); - PUT_C(ret, "error", DICTIONARY_OBJ(err_dict)); + PUT_C(ret, "error", DICT_OBJ(err_dict)); } if (highlight) { Array hl = arena_array(arena, kv_size(colors)); @@ -530,10 +527,10 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, A || node->type == kExprNodeSingleQuotedString) // "svalue" + (node->type == kExprNodeAssignment) // "augmentation" + 0); - Dictionary ret_node = arena_dict(arena, items_size); - *cur_item.ret_node_p = DICTIONARY_OBJ(ret_node); + Dict ret_node = arena_dict(arena, items_size); + *cur_item.ret_node_p = DICT_OBJ(ret_node); } - Dictionary *ret_node = &cur_item.ret_node_p->data.dictionary; + Dict *ret_node = &cur_item.ret_node_p->data.dict; if (node->children != NULL) { const size_t num_children = 1 + (node->children->next != NULL); Array children_array = arena_array(arena, num_children); @@ -638,8 +635,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, A case kExprNodeMod: break; } - assert(cur_item.ret_node_p->data.dictionary.size - == cur_item.ret_node_p->data.dictionary.capacity); + assert(cur_item.ret_node_p->data.dict.size == cur_item.ret_node_p->data.dict.capacity); xfree(*cur_item.node_p); *cur_item.node_p = NULL; } diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index 92dc9dc7e3..5a4972ef23 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -503,16 +503,15 @@ void nvim_win_set_hl_ns(Window window, Integer ns_id, Error *err) /// - end_vcol: Ending virtual column index on "end_row", /// 0-based exclusive, rounded up to full screen lines. /// When omitted include the whole line. -/// @return Dictionary containing text height information, with these keys: +/// @return Dict containing text height information, with these keys: /// - all: The total number of screen lines occupied by the range. /// - fill: The number of diff filler or virtual lines among them. /// /// @see |virtcol()| for text width. -Dictionary nvim_win_text_height(Window window, Dict(win_text_height) *opts, Arena *arena, - Error *err) +Dict nvim_win_text_height(Window window, Dict(win_text_height) *opts, Arena *arena, Error *err) FUNC_API_SINCE(12) { - Dictionary rv = arena_dict(arena, 2); + Dict rv = arena_dict(arena, 2); win_T *const win = find_window_by_handle(window, err); if (!win) { -- cgit From d831392b156087ddc38eb75b0260c03f955dd23c Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 24 Sep 2024 07:14:14 +0800 Subject: feat(paste): unify cancel and error behavior (#30476) Before this PR, the behavior of nvim_paste is: - When vim.paste() returns false, return false to the client, but treat following chunks normally (i.e. rely on the client cancelling the paste as expected). - When vim.paste() throws an error, still return true to the client, but drain the following chunks in the stream without calling vim.paste(). There are two problems with such behavior: - When vim.paste() errors, the client is still supposed to send the remaining chunks of the stream, even though they do nothing. - Having different code paths for two uncommon but similar situations complicates maintenance. This PR makes both the cancel case and the error case return false to the client and drain the remaining chunks of the stream, which, apart from sharing the same code path, is beneficial whether the client checks the return value of nvim_paste or not: - If the client checks the return value, it can avoid sending the following chunks needlessly after an error. - If the client doesn't check the return value, chunks following a cancelled chunk won't be pasted on the server regardless, which leads to less confusing behavior. --- src/nvim/api/vim.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index c1add75af9..b31accd3b0 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1219,8 +1219,8 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err) /// /// Errors ('nomodifiable', `vim.paste()` failure, …) are reflected in `err` /// but do not affect the return value (which is strictly decided by -/// `vim.paste()`). On error, subsequent calls are ignored ("drained") until -/// the next paste is initiated (phase 1 or -1). +/// `vim.paste()`). On error or cancel, subsequent calls are ignored +/// ("drained") until the next paste is initiated (phase 1 or -1). /// /// @param data Multiline input. May be binary (containing NUL bytes). /// @param crlf Also break lines at CR and CRLF. @@ -1233,20 +1233,19 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err) /// @param[out] err Error details, if any /// @return /// - true: Client may continue pasting. -/// - false: Client must cancel the paste. +/// - false: Client should cancel the paste. Boolean nvim_paste(String data, Boolean crlf, Integer phase, Arena *arena, Error *err) FUNC_API_SINCE(6) FUNC_API_TEXTLOCK_ALLOW_CMDWIN { - static bool draining = false; - bool cancel = false; + static bool cancelled = false; VALIDATE_INT((phase >= -1 && phase <= 3), "phase", phase, { return false; }); if (phase == -1 || phase == 1) { // Start of paste-stream. - draining = false; - } else if (draining) { + cancelled = false; + } else if (cancelled) { // Skip remaining chunks. Report error only once per "stream". goto theend; } @@ -1255,26 +1254,26 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Arena *arena, Error 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; + // vim.paste() decides if client should cancel. + if (ERROR_SET(err) || (rv.type == kObjectTypeBoolean && !rv.data.boolean)) { + cancelled = true; } - if (phase == -1 || phase == 1) { + if (!cancelled && (phase == -1 || phase == 1)) { paste_store(kFalse, NULL_STRING, crlf); } - // vim.paste() decides if client should cancel. Errors do NOT cancel: we - // want to drain remaining chunks (rather than divert them to main input). - cancel = (rv.type == kObjectTypeBoolean && !rv.data.boolean); - if (!cancel) { + if (!cancelled) { paste_store(kNone, data, crlf); } -theend: - if (cancel || phase == -1 || phase == 3) { // End of paste-stream. - draining = false; + if (phase == 3 || phase == (cancelled ? 2 : -1)) { paste_store(kTrue, NULL_STRING, crlf); } - - return !cancel; +theend: + ; + bool retval = !cancelled; + if (phase == -1 || phase == 3) { // End of paste-stream. + cancelled = false; + } + return retval; } /// Puts text at cursor, in any mode. -- cgit From 3f6bc34e663c62bc8899dcdc65bf204b2ccfdaec Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 24 Sep 2024 04:46:50 -0700 Subject: docs: lua error patterns #30240 Co-authored-by: Mathias Fussenegger Co-authored-by: Ananth Bhaskararaman --- src/nvim/api/buffer.c | 8 ++------ src/nvim/api/vim.c | 38 ++++++++++++++++++++++++++------------ 2 files changed, 28 insertions(+), 18 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 3baf8a97d9..9480292d9a 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -462,12 +462,8 @@ end: /// = row` and `start_col = end_col = col`. To delete the text in a range, use /// `replacement = {}`. /// -/// Prefer |nvim_buf_set_lines()| if you are only adding or deleting entire lines. -/// -/// Prefer |nvim_put()| if you want to insert text at the cursor position. -/// -/// @see |nvim_buf_set_lines()| -/// @see |nvim_put()| +/// @note Prefer |nvim_buf_set_lines()| (for performance) to add or delete entire lines. +/// @note Prefer |nvim_paste()| or |nvim_put()| to insert (instead of replace) text at cursor. /// /// @param channel_id /// @param buffer Buffer handle, or 0 for current buffer diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index b31accd3b0..ae649e55d6 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -344,9 +344,10 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_ks) } } -/// Queues raw user-input. Unlike |nvim_feedkeys()|, this uses a low-level -/// input buffer and the call is non-blocking (input is processed -/// asynchronously by the eventloop). +/// Queues raw user-input. Unlike |nvim_feedkeys()|, this uses a low-level input buffer and the call +/// is non-blocking (input is processed asynchronously by the eventloop). +/// +/// To input blocks of text, |nvim_paste()| is much faster and should be preferred. /// /// On execution error: does not fail, but updates v:errmsg. /// @@ -1212,17 +1213,30 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err) } } -/// Pastes at cursor, in any mode. +/// Pastes at cursor (in any mode), and sets "redo" so dot (|.|) will repeat the input. UIs call +/// this to implement "paste", but it's also intended for use by scripts to input large, +/// dot-repeatable blocks of text (as opposed to |nvim_input()| which is subject to mappings/events +/// and is thus much slower). +/// +/// Invokes the |vim.paste()| handler, which handles each mode appropriately. +/// +/// Errors ('nomodifiable', `vim.paste()` failure, …) are reflected in `err` but do not affect the +/// return value (which is strictly decided by `vim.paste()`). On error or cancel, subsequent calls +/// are ignored ("drained") until the next paste is initiated (phase 1 or -1). /// -/// Invokes the `vim.paste` handler, which handles each mode appropriately. -/// Sets redo/undo. Faster than |nvim_input()|. Lines break at LF ("\n"). +/// Useful in mappings and scripts to insert multiline text. Example: /// -/// Errors ('nomodifiable', `vim.paste()` failure, …) are reflected in `err` -/// but do not affect the return value (which is strictly decided by -/// `vim.paste()`). On error or cancel, subsequent calls are ignored -/// ("drained") until the next paste is initiated (phase 1 or -1). +/// ```vim +/// vim.keymap.set('n', 'x', function() +/// vim.api.nvim_paste([[ +/// line1 +/// line2 +/// line3 +/// ]], false, -1) +/// end, { buffer = true }) +/// ``` /// -/// @param data Multiline input. May be binary (containing NUL bytes). +/// @param data Multiline input. Lines break at LF ("\n"). May be binary (containing NUL bytes). /// @param crlf Also break lines at CR and CRLF. /// @param phase -1: paste in a single call (i.e. without streaming). /// To "stream" a paste, call `nvim_paste` sequentially with @@ -1276,7 +1290,7 @@ theend: return retval; } -/// Puts text at cursor, in any mode. +/// Puts text at cursor, in any mode. For dot-repeatable input, use |nvim_paste()|. /// /// Compare |:put| and |p| which are always linewise. /// -- cgit From 052875b9dc3de3283844a30dce9646f26982542d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 24 Sep 2024 19:48:40 +0800 Subject: fix(paste): only record a paste when it's from RPC (#30491) Problem: When using nvim_paste in a mapping during a macro recording, both the mapping and the paste are recorded, causing the paste to be performed twice when replaying the macro. Solution: Only record a paste when it is from RPC. Unfortunately this means there is no way for a script to make a recorded paste. A way to enable that can be discussed later if there is need. --- src/nvim/api/vim.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index ae649e55d6..d18cfaccd0 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1248,7 +1248,8 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err) /// @return /// - true: Client may continue pasting. /// - false: Client should cancel the paste. -Boolean nvim_paste(String data, Boolean crlf, Integer phase, Arena *arena, Error *err) +Boolean nvim_paste(uint64_t channel_id, String data, Boolean crlf, Integer phase, Arena *arena, + Error *err) FUNC_API_SINCE(6) FUNC_API_TEXTLOCK_ALLOW_CMDWIN { @@ -1273,13 +1274,13 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Arena *arena, Error cancelled = true; } if (!cancelled && (phase == -1 || phase == 1)) { - paste_store(kFalse, NULL_STRING, crlf); + paste_store(channel_id, kFalse, NULL_STRING, crlf); } if (!cancelled) { - paste_store(kNone, data, crlf); + paste_store(channel_id, kNone, data, crlf); } if (phase == 3 || phase == (cancelled ? 2 : -1)) { - paste_store(kTrue, NULL_STRING, crlf); + paste_store(channel_id, kTrue, NULL_STRING, crlf); } theend: ; -- cgit From ce7017b850e0f62b3ebe6ea0d7010ba0291624e5 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Wed, 25 Sep 2024 02:34:13 -0700 Subject: docs: render @see, @note items in _meta/api.lua #30494 --- src/nvim/api/vim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index d18cfaccd0..8c88a19147 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1226,7 +1226,7 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err) /// /// Useful in mappings and scripts to insert multiline text. Example: /// -/// ```vim +/// ```lua /// vim.keymap.set('n', 'x', function() /// vim.api.nvim_paste([[ /// line1 -- cgit From f55213ce0e2b0053ded8416e8ae922a0e406012f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 27 Sep 2024 22:33:24 +0800 Subject: fix(api): fix crash/leak with float title/footer on error (#30543) --- src/nvim/api/win_config.c | 92 ++++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 45 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c index 996e587446..b006f86a76 100644 --- a/src/nvim/api/win_config.c +++ b/src/nvim/api/win_config.c @@ -854,19 +854,11 @@ static void parse_bordertext(Object bordertext, BorderTextType bordertext_type, int *width; switch (bordertext_type) { case kBorderTextTitle: - if (fconfig->title) { - clear_virttext(&fconfig->title_chunks); - } - is_present = &fconfig->title; chunks = &fconfig->title_chunks; width = &fconfig->title_width; break; case kBorderTextFooter: - if (fconfig->footer) { - clear_virttext(&fconfig->footer_chunks); - } - is_present = &fconfig->footer; chunks = &fconfig->footer_chunks; width = &fconfig->footer_width; @@ -878,6 +870,7 @@ static void parse_bordertext(Object bordertext, BorderTextType bordertext_type, *is_present = false; return; } + kv_init(*chunks); kv_push(*chunks, ((VirtTextChunk){ .text = xstrdup(bordertext.data.string.data), .hl_id = -1 })); *width = (int)mb_string2cells(bordertext.data.string.data); @@ -1055,13 +1048,13 @@ static bool parse_win_config(win_T *wp, Dict(win_config) *config, WinConfig *fco if (config->relative.size > 0) { if (!parse_float_relative(config->relative, &fconfig->relative)) { api_set_error(err, kErrorTypeValidation, "Invalid value of 'relative' key"); - return false; + goto fail; } if (config->relative.size > 0 && !(HAS_KEY_X(config, row) && HAS_KEY_X(config, col)) && !HAS_KEY_X(config, bufpos)) { api_set_error(err, kErrorTypeValidation, "'relative' requires 'row'/'col' or 'bufpos'"); - return false; + goto fail; } has_relative = true; @@ -1076,39 +1069,39 @@ static bool parse_win_config(win_T *wp, Dict(win_config) *config, WinConfig *fco } else if (wp == NULL) { // new win api_set_error(err, kErrorTypeValidation, "Must specify 'relative' or 'external' when creating a float"); - return false; + goto fail; } } if (HAS_KEY_X(config, vertical)) { if (!is_split) { api_set_error(err, kErrorTypeValidation, "floating windows cannot have 'vertical'"); - return false; + goto fail; } } if (HAS_KEY_X(config, split)) { if (!is_split) { api_set_error(err, kErrorTypeValidation, "floating windows cannot have 'split'"); - return false; + goto fail; } if (!parse_config_split(config->split, &fconfig->split)) { api_set_error(err, kErrorTypeValidation, "Invalid value of 'split' key"); - return false; + goto fail; } } if (HAS_KEY_X(config, anchor)) { if (!parse_float_anchor(config->anchor, &fconfig->anchor)) { api_set_error(err, kErrorTypeValidation, "Invalid value of 'anchor' key"); - return false; + goto fail; } } if (HAS_KEY_X(config, row)) { if (!has_relative || is_split) { generate_api_error(wp, "row", err); - return false; + goto fail; } fconfig->row = config->row; } @@ -1116,7 +1109,7 @@ static bool parse_win_config(win_T *wp, Dict(win_config) *config, WinConfig *fco if (HAS_KEY_X(config, col)) { if (!has_relative || is_split) { generate_api_error(wp, "col", err); - return false; + goto fail; } fconfig->col = config->col; } @@ -1124,11 +1117,11 @@ static bool parse_win_config(win_T *wp, Dict(win_config) *config, WinConfig *fco if (HAS_KEY_X(config, bufpos)) { if (!has_relative || is_split) { generate_api_error(wp, "bufpos", err); - return false; + goto fail; } else { if (!parse_float_bufpos(config->bufpos, &fconfig->bufpos)) { api_set_error(err, kErrorTypeValidation, "Invalid value of 'bufpos' key"); - return false; + goto fail; } if (!HAS_KEY_X(config, row)) { @@ -1145,11 +1138,11 @@ static bool parse_win_config(win_T *wp, Dict(win_config) *config, WinConfig *fco fconfig->width = (int)config->width; } else { api_set_error(err, kErrorTypeValidation, "'width' key must be a positive Integer"); - return false; + goto fail; } } else if (!reconf && !is_split) { api_set_error(err, kErrorTypeValidation, "Must specify 'width'"); - return false; + goto fail; } if (HAS_KEY_X(config, height)) { @@ -1157,23 +1150,23 @@ static bool parse_win_config(win_T *wp, Dict(win_config) *config, WinConfig *fco fconfig->height = (int)config->height; } else { api_set_error(err, kErrorTypeValidation, "'height' key must be a positive Integer"); - return false; + goto fail; } } else if (!reconf && !is_split) { api_set_error(err, kErrorTypeValidation, "Must specify 'height'"); - return false; + goto fail; } if (relative_is_win || is_split) { if (reconf && relative_is_win) { win_T *target_win = find_window_by_handle(config->win, err); if (!target_win) { - return false; + goto fail; } if (target_win == wp) { api_set_error(err, kErrorTypeException, "floating window cannot be relative to itself"); - return false; + goto fail; } } fconfig->window = curwin->handle; @@ -1186,11 +1179,11 @@ static bool parse_win_config(win_T *wp, Dict(win_config) *config, WinConfig *fco if (has_relative) { api_set_error(err, kErrorTypeValidation, "'win' key is only valid with relative='win' and relative=''"); - return false; + goto fail; } else if (!is_split) { api_set_error(err, kErrorTypeValidation, "non-float with 'win' requires at least 'split' or 'vertical'"); - return false; + goto fail; } } @@ -1199,11 +1192,11 @@ static bool parse_win_config(win_T *wp, Dict(win_config) *config, WinConfig *fco if (has_relative && fconfig->external) { api_set_error(err, kErrorTypeValidation, "Only one of 'relative' and 'external' must be used"); - return false; + goto fail; } if (fconfig->external && !ui_has(kUIMultigrid)) { api_set_error(err, kErrorTypeValidation, "UI doesn't support external windows"); - return false; + goto fail; } } @@ -1214,78 +1207,78 @@ static bool parse_win_config(win_T *wp, Dict(win_config) *config, WinConfig *fco if (HAS_KEY_X(config, zindex)) { if (is_split) { api_set_error(err, kErrorTypeValidation, "non-float cannot have 'zindex'"); - return false; + goto fail; } if (config->zindex > 0) { fconfig->zindex = (int)config->zindex; } else { api_set_error(err, kErrorTypeValidation, "'zindex' key must be a positive Integer"); - return false; + goto fail; } } if (HAS_KEY_X(config, title)) { if (is_split) { api_set_error(err, kErrorTypeValidation, "non-float cannot have 'title'"); - return false; + goto fail; } // title only work with border if (!HAS_KEY_X(config, border) && !fconfig->border) { api_set_error(err, kErrorTypeException, "title requires border to be set"); - return false; + goto fail; } parse_bordertext(config->title, kBorderTextTitle, fconfig, err); if (ERROR_SET(err)) { - return false; + goto fail; } // handles unset 'title_pos' same as empty string if (!parse_bordertext_pos(config->title_pos, kBorderTextTitle, fconfig, err)) { - return false; + goto fail; } } else { if (HAS_KEY_X(config, title_pos)) { api_set_error(err, kErrorTypeException, "title_pos requires title to be set"); - return false; + goto fail; } } if (HAS_KEY_X(config, footer)) { if (is_split) { api_set_error(err, kErrorTypeValidation, "non-float cannot have 'footer'"); - return false; + goto fail; } // footer only work with border if (!HAS_KEY_X(config, border) && !fconfig->border) { api_set_error(err, kErrorTypeException, "footer requires border to be set"); - return false; + goto fail; } parse_bordertext(config->footer, kBorderTextFooter, fconfig, err); if (ERROR_SET(err)) { - return false; + goto fail; } // handles unset 'footer_pos' same as empty string if (!parse_bordertext_pos(config->footer_pos, kBorderTextFooter, fconfig, err)) { - return false; + goto fail; } } else { if (HAS_KEY_X(config, footer_pos)) { api_set_error(err, kErrorTypeException, "footer_pos requires footer to be set"); - return false; + goto fail; } } if (HAS_KEY_X(config, border)) { if (is_split) { api_set_error(err, kErrorTypeValidation, "non-float cannot have 'border'"); - return false; + goto fail; } parse_border_style(config->border, fconfig, err); if (ERROR_SET(err)) { - return false; + goto fail; } } @@ -1296,14 +1289,14 @@ static bool parse_win_config(win_T *wp, Dict(win_config) *config, WinConfig *fco fconfig->style = kWinStyleMinimal; } else { api_set_error(err, kErrorTypeValidation, "Invalid value of 'style' key"); - return false; + goto fail; } } if (HAS_KEY_X(config, noautocmd)) { if (wp) { api_set_error(err, kErrorTypeValidation, "'noautocmd' cannot be used with existing windows"); - return false; + goto fail; } fconfig->noautocmd = config->noautocmd; } @@ -1317,5 +1310,14 @@ static bool parse_win_config(win_T *wp, Dict(win_config) *config, WinConfig *fco } return true; + +fail: + if (wp == NULL || fconfig->title_chunks.items != wp->w_config.title_chunks.items) { + clear_virttext(&fconfig->title_chunks); + } + if (wp == NULL || fconfig->footer_chunks.items != wp->w_config.footer_chunks.items) { + clear_virttext(&fconfig->footer_chunks); + } + return false; #undef HAS_KEY_X } -- cgit From 4f9311b759fff0371433fb5b5355fccb001d54e7 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 28 Sep 2024 10:21:06 +0800 Subject: fix(window): making float with title/footer non-float leaks memory (#30551) --- src/nvim/api/win_config.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c index b006f86a76..f63fdc5381 100644 --- a/src/nvim/api/win_config.c +++ b/src/nvim/api/win_config.c @@ -448,7 +448,7 @@ void nvim_win_set_config(Window window, Dict(win_config) *config, Error *err) } } } - win->w_config = fconfig; + merge_win_config(&win->w_config, fconfig); // If there's no "vertical" or "split" set, or if "split" is unchanged, // then we can just change the size of the window. @@ -1312,12 +1312,7 @@ static bool parse_win_config(win_T *wp, Dict(win_config) *config, WinConfig *fco return true; fail: - if (wp == NULL || fconfig->title_chunks.items != wp->w_config.title_chunks.items) { - clear_virttext(&fconfig->title_chunks); - } - if (wp == NULL || fconfig->footer_chunks.items != wp->w_config.footer_chunks.items) { - clear_virttext(&fconfig->footer_chunks); - } + merge_win_config(fconfig, wp != NULL ? wp->w_config : WIN_CONFIG_INIT); return false; #undef HAS_KEY_X } -- cgit