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 (stri