aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraltermo <107814000+altermo@users.noreply.github.com>2024-06-07 17:33:40 +0200
committerGitHub <noreply@github.com>2024-06-07 08:33:40 -0700
commitf3632e14e3a75114415050ab01c2d04a06036009 (patch)
treeb3a7067d7cbde9305b01324384a0aac76e6a56ae
parent2ce4a4d91e4abee0aab8b98c47eea9fbd4849ba6 (diff)
downloadrneovim-f3632e14e3a75114415050ab01c2d04a06036009.tar.gz
rneovim-f3632e14e3a75114415050ab01c2d04a06036009.tar.bz2
rneovim-f3632e14e3a75114415050ab01c2d04a06036009.zip
feat: get/set namespace properties #28728
ref https://github.com/neovim/neovim/pull/28432 ref https://github.com/neovim/neovim/issues/28469
-rw-r--r--runtime/doc/api.txt35
-rw-r--r--runtime/doc/news-0.10.txt2
-rw-r--r--runtime/doc/news.txt2
-rw-r--r--runtime/lua/vim/_meta/api.lua51
-rw-r--r--runtime/lua/vim/_meta/api_keysets.lua3
-rw-r--r--runtime/lua/vim/highlight.lua9
-rw-r--r--src/nvim/api/deprecated.c2
-rw-r--r--src/nvim/api/extmark.c155
-rw-r--r--src/nvim/api/extmark.h15
-rw-r--r--src/nvim/api/keysets_defs.h5
-rw-r--r--src/nvim/decoration.c8
-rw-r--r--src/nvim/extmark.c4
-rw-r--r--src/nvim/marktree.c2
-rw-r--r--src/nvim/marktree.h20
-rw-r--r--src/nvim/plines.c3
-rw-r--r--src/nvim/sign.c2
-rw-r--r--test/functional/lua/highlight_spec.lua14
-rw-r--r--test/functional/ui/decorations_spec.lua218
18 files changed, 285 insertions, 265 deletions
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 577329ad00..f92a69af4e 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -2758,8 +2758,6 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {opts})
• 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()|
Return: ~
Id of the created/updated extmark
@@ -2841,41 +2839,26 @@ nvim_set_decoration_provider({ns_id}, {opts})
["end", tick]
<
-nvim__win_add_ns({window}, {ns_id}) *nvim__win_add_ns()*
+nvim__ns_get({ns_id}) *nvim__ns_get()*
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.
+ Get the properties for namespace
Parameters: ~
- • {window} Window handle, or 0 for current window
- • {ns_id} Namespace
-
- Return: ~
- true if the namespace was added, else false
-
-nvim__win_del_ns({window}, {ns_id}) *nvim__win_del_ns()*
- EXPERIMENTAL: this API will change in the future.
-
- Unscopes a namespace (un-binds it from the given scope).
-
- Parameters: ~
- • {window} Window handle, or 0 for current window
- • {ns_id} the namespace to remove
+ • {ns_id} Namespace
Return: ~
- true if the namespace was removed, else false
+ Map defining the namespace properties, see |nvim__ns_set()|
-nvim__win_get_ns({window}) *nvim__win_get_ns()*
+nvim__ns_set({ns_id}, {opts}) *nvim__ns_set()*
EXPERIMENTAL: this API will change in the future.
- Gets the namespace scopes for a given window.
+ Set some properties for namespace
Parameters: ~
- • {window} Window handle, or 0 for current window
-
- Return: ~
- a list of namespaces ids
+ • {ns_id} Namespace
+ • {opts} Optional parameters to set:
+ • wins: a list of windows to be scoped in
==============================================================================
diff --git a/runtime/doc/news-0.10.txt b/runtime/doc/news-0.10.txt
index d611eee242..bc868c1099 100644
--- a/runtime/doc/news-0.10.txt
+++ b/runtime/doc/news-0.10.txt
@@ -155,8 +155,6 @@ The following new features were added.
• |nvim_input_mouse()| supports mouse buttons "x1" and "x2".
• Added "force_crlf" option field in |nvim_open_term()|.
• Added |nvim_tabpage_set_win()| to set the current window of a tabpage.
- • |nvim__win_add_ns()| can bind a |namespace| to a window-local scope(s).
- • Extmarks opt-in to this scoping via the `scoped` flag of |nvim_buf_set_extmark()|.
• Mapping APIs now support abbreviations when mode short-name has suffix "a".
• Floating windows can now show footer with new `footer` and `footer_pos`
config fields. Uses |hl-FloatFooter| by default.
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index 2fed1b6b29..b316cc7b04 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -83,7 +83,7 @@ The following new features were added.
API
-• TODO
+• |nvim__ns_set()| can set properties for a namespace
DEFAULTS
diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua
index bb27ee4269..d91b2d08bf 100644
--- a/runtime/lua/vim/_meta/api.lua
+++ b/runtime/lua/vim/_meta/api.lua
@@ -100,6 +100,25 @@ function vim.api.nvim__inspect_cell(grid, row, col) end
function vim.api.nvim__invalidate_glyph_cache() end
--- @private
+--- EXPERIMENTAL: this API will change in the future.
+---
+--- Get the properties for namespace
+---
+--- @param ns_id integer Namespace
+--- @return vim.api.keyset.ns_opts
+function vim.api.nvim__ns_get(ns_id) end
+
+--- @private
+--- EXPERIMENTAL: this API will change in the future.
+---
+--- Set some properties for namespace
+---
+--- @param ns_id integer Namespace
+--- @param opts vim.api.keyset.ns_opts Optional parameters to set:
+--- • wins: a list of windows to be scoped in
+function vim.api.nvim__ns_set(ns_id, opts) end
+
+--- @private
--- EXPERIMENTAL: this API may change in the future.
---
--- Instruct Nvim to redraw various components.
@@ -144,36 +163,6 @@ function vim.api.nvim__stats() end
--- @return any
function vim.api.nvim__unpack(str) end
---- @private
---- EXPERIMENTAL: this API will change in the future.
----
---- Scopes a namespace to the a window, so extmarks in the namespace will be
---- active only in the given window.
----
---- @param window integer Window handle, or 0 for current window
---- @param ns_id integer Namespace
---- @return boolean
-function vim.api.nvim__win_add_ns(window, ns_id) end
-
---- @private
---- EXPERIMENTAL: this API will change in the future.
----
---- Unscopes a namespace (un-binds it from the given scope).
----
---- @param window integer Window handle, or 0 for current window
---- @param ns_id integer the namespace to remove
---- @return boolean
-function vim.api.nvim__win_del_ns(window, ns_id) end
-
---- @private
---- EXPERIMENTAL: this API will change in the future.
----
---- Gets the namespace scopes for a given window.
----
---- @param window integer Window handle, or 0 for current window
---- @return integer[]
-function vim.api.nvim__win_get_ns(window) end
-
--- Adds a highlight to buffer.
---
--- Useful for plugins that dynamically generate highlights to a buffer (like
@@ -686,8 +675,6 @@ function vim.api.nvim_buf_line_count(buffer) end
--- • 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()`
--- @return integer
function vim.api.nvim_buf_set_extmark(buffer, ns_id, line, col, opts) end
diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua
index f7cd92a3b2..2fe5c32faf 100644
--- a/runtime/lua/vim/_meta/api_keysets.lua
+++ b/runtime/lua/vim/_meta/api_keysets.lua
@@ -197,6 +197,9 @@ error('Cannot require a meta file')
--- @field desc? string
--- @field replace_keycodes? boolean
+--- @class vim.api.keyset.ns_opts
+--- @field wins? any[]
+
--- @class vim.api.keyset.open_term
--- @field on_input? function
--- @field force_crlf? boolean
diff --git a/runtime/lua/vim/highlight.lua b/runtime/lua/vim/highlight.lua
index e972ffaa8c..233bc50237 100644
--- a/runtime/lua/vim/highlight.lua
+++ b/runtime/lua/vim/highlight.lua
@@ -31,8 +31,6 @@ M.priorities = {
--- Indicates priority of highlight
--- (default: `vim.highlight.priorities.user`)
--- @field priority? integer
----
---- @field package _scoped? boolean
--- Apply highlight group to range of text.
---
@@ -47,7 +45,6 @@ function M.range(bufnr, ns, higroup, start, finish, opts)
local regtype = opts.regtype or 'v'
local inclusive = opts.inclusive or false
local priority = opts.priority or M.priorities.user
- local scoped = opts._scoped or false
local v_maxcol = vim.v.maxcol
@@ -114,7 +111,6 @@ function M.range(bufnr, ns, higroup, start, finish, opts)
end_col = end_col,
priority = priority,
strict = false,
- scoped = scoped,
})
end
end
@@ -178,19 +174,18 @@ function M.on_yank(opts)
yank_cancel()
end
- vim.api.nvim__win_add_ns(winid, yank_ns)
+ vim.api.nvim__ns_set(yank_ns, { wins = { winid } })
M.range(bufnr, yank_ns, higroup, "'[", "']", {
regtype = event.regtype,
inclusive = event.inclusive,
priority = opts.priority or M.priorities.user,
- _scoped = true,
})
yank_cancel = function()
yank_timer = nil
yank_cancel = nil
pcall(vim.api.nvim_buf_clear_namespace, bufnr, yank_ns, 0, -1)
- pcall(vim.api.nvim__win_del_ns, winid, yank_ns)
+ pcall(vim.api.nvim__ns_set, { wins = {} })
end
yank_timer = vim.defer_fn(yank_cancel, timeout)
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);
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index 52a3fa5924..0cf02d96da 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -89,7 +89,7 @@ void bufhl_add_hl_pos_offset(buf_T *buf, int src_id, int hl_id, lpos_T pos_start
extmark_set(buf, (uint32_t)src_id, NULL,
(int)lnum - 1, hl_start, (int)lnum - 1 + end_off, hl_end,
- decor, MT_FLAG_DECOR_HL, true, false, true, false, false, NULL);
+ decor, MT_FLAG_DECOR_HL, true, false, true, false, NULL);
}
}
@@ -598,7 +598,7 @@ int decor_redraw_col(win_T *wp, int col, int win_col, bool hidden, DecorState *s
break;
}
- if (!mt_scoped_in_win(mark, wp)) {
+ if (!ns_in_win(mark.ns, wp)) {
goto next_mark;
}
@@ -747,7 +747,7 @@ void decor_redraw_signs(win_T *wp, buf_T *buf, int row, SignTextAttrs sattrs[],
break;
}
if (!mt_end(mark) && !mt_invalid(mark) && mt_decor_sign(mark)
- && mt_scoped_in_win(mark, wp)) {
+ && ns_in_win(mark.ns, wp)) {
DecorSignHighlight *sh = decor_find_sign(mt_decor(mark));
num_text += (sh->text[0] != NUL);
kv_push(signs, ((SignItem){ sh, mark.id }));
@@ -927,7 +927,7 @@ int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines, TriState has_fo
while (true) {
MTKey mark = marktree_itr_current(itr);
DecorVirtText *vt = mt_decor_virt(mark);
- if (mt_scoped_in_win(mark, wp)) {
+ if (ns_in_win(mark.ns, wp)) {
while (vt) {
if (vt->flags & kVTIsLines) {
bool above = vt->flags & kVTLinesAbove;
diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c
index 4e47fa76fe..b592283d92 100644
--- a/src/nvim/extmark.c
+++ b/src/nvim/extmark.c
@@ -54,12 +54,12 @@
/// must not be used during iteration!
void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col, int end_row,
colnr_T end_col, DecorInline decor, uint16_t decor_flags, bool right_gravity,
- bool end_right_gravity, bool no_undo, bool invalidate, bool scoped, Error *err)
+ bool end_right_gravity, bool no_undo, bool invalidate, Error *err)
{
uint32_t *ns = map_put_ref(uint32_t, uint32_t)(buf->b_extmark_ns, ns_id, NULL, NULL);
uint32_t id = idp ? *idp : 0;
- uint16_t flags = mt_flags(right_gravity, no_undo, invalidate, decor.ext, scoped) | decor_flags;
+ uint16_t flags = mt_flags(right_gravity, no_undo, invalidate, decor.ext) | decor_flags;
if (id == 0) {
id = ++*ns;
} else {
diff --git a/src/nvim/marktree.c b/src/nvim/marktree.c
index 34d6cd118f..9e3005b6a3 100644
--- a/src/nvim/marktree.c
+++ b/src/nvim/marktree.c
@@ -2286,7 +2286,7 @@ static void marktree_itr_fix_pos(MarkTree *b, MarkTreeIter *itr)
void marktree_put_test(MarkTree *b, uint32_t ns, uint32_t id, int row, int col, bool right_gravity,
int end_row, int end_col, bool end_right, bool meta_inline)
{
- uint16_t flags = mt_flags(right_gravity, false, false, false, false);
+ uint16_t flags = mt_flags(right_gravity, false, false, false);
// The specific choice is irrelevant here, we pick one counted decor
// type to test the counting and filtering logic.
flags |= meta_inline ? MT_FLAG_DECOR_VIRT_TEXT_INLINE : 0;
diff --git a/src/nvim/marktree.h b/src/nvim/marktree.h
index 8e5cf30ff3..15df57ef63 100644
--- a/src/nvim/marktree.h
+++ b/src/nvim/marktree.h
@@ -35,8 +35,6 @@
#define MT_FLAG_DECOR_VIRT_LINES (((uint16_t)1) << 11)
#define MT_FLAG_DECOR_VIRT_TEXT_INLINE (((uint16_t)1) << 12)
-#define MT_FLAG_SCOPED (((uint16_t)1) << 13)
-
// These _must_ be last to preserve ordering of marks
#define MT_FLAG_RIGHT_GRAVITY (((uint16_t)1) << 14)
#define MT_FLAG_LAST (((uint16_t)1) << 15)
@@ -46,7 +44,7 @@
| MT_FLAG_DECOR_VIRT_TEXT_INLINE)
#define MT_FLAG_EXTERNAL_MASK (MT_FLAG_DECOR_MASK | MT_FLAG_NO_UNDO \
- | MT_FLAG_INVALIDATE | MT_FLAG_INVALID | MT_FLAG_SCOPED)
+ | MT_FLAG_INVALIDATE | MT_FLAG_INVALID)
// this is defined so that start and end of the same range have adjacent ids
#define MARKTREE_END_FLAG ((uint64_t)1)
@@ -110,24 +108,12 @@ static inline bool mt_decor_sign(MTKey key)
return key.flags & (MT_FLAG_DECOR_SIGNTEXT | MT_FLAG_DECOR_SIGNHL);
}
-static inline bool mt_scoped(MTKey key)
-{
- return key.flags & MT_FLAG_SCOPED;
-}
-
-static inline bool mt_scoped_in_win(MTKey key, win_T *wp)
-{
- return !mt_scoped(key) || set_has(uint32_t, &wp->w_ns_set, key.ns);
-}
-
-static inline uint16_t mt_flags(bool right_gravity, bool no_undo, bool invalidate, bool decor_ext,
- bool scoped)
+static inline uint16_t mt_flags(bool right_gravity, bool no_undo, bool invalidate, bool decor_ext)
{
return (uint16_t)((right_gravity ? MT_FLAG_RIGHT_GRAVITY : 0)
| (no_undo ? MT_FLAG_NO_UNDO : 0)
| (invalidate ? MT_FLAG_INVALIDATE : 0)
- | (decor_ext ? MT_FLAG_DECOR_EXT : 0)
- | (scoped ? MT_FLAG_SCOPED : 0));
+ | (decor_ext ? MT_FLAG_DECOR_EXT : 0));
}
static inline MTPair mtpair_from(MTKey start, MTKey end)
diff --git a/src/nvim/plines.c b/src/nvim/plines.c
index 5881d34c48..f273f88dd1 100644
--- a/src/nvim/plines.c
+++ b/src/nvim/plines.c
@@ -5,6 +5,7 @@
#include <stdint.h>
#include <string.h>
+#include "nvim/api/extmark.h"
#include "nvim/ascii_defs.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
@@ -158,7 +159,7 @@ CharSize charsize_regular(CharsizeArg *csarg, char *const cur, colnr_T const vco
break;
} else if (mark.pos.col == col) {
if (!mt_end(mark) && (mark.flags & MT_FLAG_DECOR_VIRT_TEXT_INLINE)
- && mt_scoped_in_win(mark, wp)) {
+ && ns_in_win(mark.ns, wp)) {
DecorInline decor = mt_decor(mark);
DecorVirtText *vt = decor.ext ? decor.data.ext.vt : NULL;
while (vt) {
diff --git a/src/nvim/sign.c b/src/nvim/sign.c
index 496913f9bf..1ca0e846a9 100644
--- a/src/nvim/sign.c
+++ b/src/nvim/sign.c
@@ -127,7 +127,7 @@ static void buf_set_sign(buf_T *buf, uint32_t *id, char *group, int prio, linenr
DecorInline decor = { .ext = true, .data.ext = { .vt = NULL, .sh_idx = decor_put_sh(sign) } };
extmark_set(buf, ns, id, lnum - 1, 0, -1, -1, decor, decor_flags, true,
- false, true, true, false, NULL);
+ false, true, true, NULL);
}
/// For an existing, placed sign with "id", modify the sign, group or priority.
diff --git a/test/functional/lua/highlight_spec.lua b/test/functional/lua/highlight_spec.lua
index 66095121b0..ad709a06f1 100644
--- a/test/functional/lua/highlight_spec.lua
+++ b/test/functional/lua/highlight_spec.lua
@@ -4,7 +4,6 @@ local Screen = require('test.functional.ui.screen')
local exec_lua = n.exec_lua
local eq = t.eq
-local neq = t.neq
local eval = n.eval
local command = n.command
local clear = n.clear
@@ -142,9 +141,11 @@ describe('vim.highlight.on_yank', function()
vim.api.nvim_buf_set_mark(0,"]",1,1,{})
vim.highlight.on_yank({timeout = math.huge, on_macro = true, event = {operator = "y"}})
]])
- neq({}, api.nvim__win_get_ns(0))
+ local ns = api.nvim_create_namespace('hlyank')
+ local win = api.nvim_get_current_win()
+ eq({ win }, api.nvim__ns_get(ns).wins)
command('wincmd w')
- eq({}, api.nvim__win_get_ns(0))
+ eq({ win }, api.nvim__ns_get(ns).wins)
end)
it('removes old highlight if new one is created before old one times out', function()
@@ -154,14 +155,17 @@ describe('vim.highlight.on_yank', function()
vim.api.nvim_buf_set_mark(0,"]",1,1,{})
vim.highlight.on_yank({timeout = math.huge, on_macro = true, event = {operator = "y"}})
]])
- neq({}, api.nvim__win_get_ns(0))
+ local ns = api.nvim_create_namespace('hlyank')
+ eq(api.nvim_get_current_win(), api.nvim__ns_get(ns).wins[1])
command('wincmd w')
exec_lua([[
vim.api.nvim_buf_set_mark(0,"[",1,1,{})
vim.api.nvim_buf_set_mark(0,"]",1,1,{})
vim.highlight.on_yank({timeout = math.huge, on_macro = true, event = {operator = "y"}})
]])
+ local win = api.nvim_get_current_win()
+ eq({ win }, api.nvim__ns_get(ns).wins)
command('wincmd w')
- eq({}, api.nvim__win_get_ns(0))
+ eq({ win }, api.nvim__ns_get(ns).wins)
end)
end)
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
index 3e67e33ddb..318dc8c197 100644
--- a/test/functional/ui/decorations_spec.lua
+++ b/test/functional/ui/decorations_spec.lua
@@ -5595,20 +5595,26 @@ describe('decorations: virt_text', function()
end)
describe('decorations: window scoped', function()
- local screen, ns
+ local screen, ns, win_other
local url = 'https://example.com'
before_each(function()
clear()
screen = Screen.new(20, 10)
screen:attach()
screen:add_extra_attr_ids {
- [100] = { special = Screen.colors.Red, undercurl = true },
- [101] = { url = "https://example.com" },
+ [100] = { special = Screen.colors.Red, undercurl = true },
+ [101] = { url = 'https://example.com' },
}
ns = api.nvim_create_namespace 'test'
insert('12345')
+
+ win_other = api.nvim_open_win(0, false, {
+ col=0,row=0,width=20,height=10,
+ relative = 'win',style = 'minimal',
+ hide = true
+ })
end)
local noextmarks = {
@@ -5616,28 +5622,28 @@ describe('decorations: window scoped', function()
1234^5 |
{1:~ }|*8
|
- ]]}
+ ]],
+ }
- local function set_scoped_extmark(line, col, opts)
- return api.nvim_buf_set_extmark(0, ns, line, col, vim.tbl_extend('error', { scoped = true }, opts))
+ local function set_extmark(line, col, opts)
+ return api.nvim_buf_set_extmark(0, ns, line, col, opts)
end
it('hl_group', function()
- set_scoped_extmark(0, 0, {
+ set_extmark(0, 0, {
hl_group = 'Comment',
end_col = 3,
})
- screen:expect(noextmarks)
-
- api.nvim__win_add_ns(0, ns)
+ api.nvim__ns_set(ns, { wins = { 0 } })
screen:expect {
grid = [[
{18:123}4^5 |
{1:~ }|*8
|
- ]]}
+ ]],
+ }
command 'split'
command 'only'
@@ -5646,48 +5652,55 @@ describe('decorations: window scoped', function()
end)
it('virt_text', function()
- set_scoped_extmark(0, 0, {
+ set_extmark(0, 0, {
virt_text = { { 'a', 'Comment' } },
virt_text_pos = 'eol',
})
- set_scoped_extmark(0, 5, {
+ set_extmark(0, 5, {
virt_text = { { 'b', 'Comment' } },
virt_text_pos = 'inline',
})
- set_scoped_extmark(0, 1, {
+ set_extmark(0, 1, {
virt_text = { { 'c', 'Comment' } },
virt_text_pos = 'overlay',
})
- set_scoped_extmark(0, 1, {
+ set_extmark(0, 1, {
virt_text = { { 'd', 'Comment' } },
virt_text_pos = 'right_align',
})
- screen:expect(noextmarks)
-
- api.nvim__win_add_ns(0, ns)
+ api.nvim__ns_set(ns, { wins = { 0 } })
screen:expect {
grid = [[
1{18:c}34^5{18:b} {18:a} {18:d}|
{1:~ }|*8
|
- ]]}
+ ]],
+ }
command 'split'
command 'only'
screen:expect(noextmarks)
+
+ api.nvim__ns_set(ns, { wins = {} })
+
+ screen:expect {
+ grid = [[
+ 1{18:c}34^5{18:b} {18:a} {18:d}|
+ {1:~ }|*8
+ |
+ ]],
+ }
end)
it('virt_lines', function()
- set_scoped_extmark(0, 0, {
+ set_extmark(0, 0, {
virt_lines = { { { 'a', 'Comment' } } },
})
- screen:expect(noextmarks)
-
- api.nvim__win_add_ns(0, ns)
+ api.nvim__ns_set(ns, { wins = { 0 } })
screen:expect {
grid = [[
@@ -5695,7 +5708,8 @@ describe('decorations: window scoped', function()
{18:a} |
{1:~ }|*7
|
- ]]}
+ ]],
+ }
command 'split'
command 'only'
@@ -5704,14 +5718,12 @@ describe('decorations: window scoped', function()
end)
it('redraws correctly with inline virt_text and wrapping', function()
- set_scoped_extmark(0, 2, {
- virt_text = {{ ('b'):rep(18), 'Comment' }},
- virt_text_pos = 'inline'
+ set_extmark(0, 2, {
+ virt_text = { { ('b'):rep(18), 'Comment' } },
+ virt_text_pos = 'inline',
})
- screen:expect(noextmarks)
-
- api.nvim__win_add_ns(0, ns)
+ api.nvim__ns_set(ns, { wins = { 0 } })
screen:expect {
grid = [[
@@ -5719,9 +5731,10 @@ describe('decorations: window scoped', function()
34^5 |
{1:~ }|*7
|
- ]]}
+ ]],
+ }
- api.nvim__win_del_ns(0, ns)
+ api.nvim__ns_set(ns, { wins = { win_other } })
screen:expect(noextmarks)
end)
@@ -5729,21 +5742,20 @@ describe('decorations: window scoped', function()
pending('sign_text', function()
-- TODO(altermo): The window signcolumn width is calculated wrongly (when `signcolumn=auto`)
-- This happens in function `win_redraw_signcols` on line containing `buf_meta_total(buf, kMTMetaSignText) > 0`
- set_scoped_extmark(0, 0, {
+ set_extmark(0, 0, {
sign_text = 'a',
sign_hl_group = 'Comment',
})
- screen:expect(noextmarks)
-
- api.nvim__win_add_ns(0, ns)
+ api.nvim__ns_set(ns, { wins = { 0 } })
screen:expect {
grid = [[
a 1234^5 |
{2:~ }|*8
|
- ]]}
+ ]],
+ }
command 'split'
command 'only'
@@ -5752,30 +5764,34 @@ describe('decorations: window scoped', function()
end)
it('statuscolumn hl group', function()
- set_scoped_extmark(0, 0, {
- number_hl_group='comment',
+ set_extmark(0, 0, {
+ number_hl_group = 'comment',
})
- set_scoped_extmark(0, 0, {
- line_hl_group='comment',
+ set_extmark(0, 0, {
+ line_hl_group = 'comment',
})
command 'set number'
+ api.nvim__ns_set(ns, { wins = { win_other } })
+
screen:expect {
grid = [[
{8: 1 }1234^5 |
{1:~ }|*8
|
- ]]}
+ ]],
+ }
- api.nvim__win_add_ns(0, ns)
+ api.nvim__ns_set(ns, { wins = { 0 } })
screen:expect {
grid = [[
{18: 1 1234^5 }|
{1:~ }|*8
|
- ]]}
+ ]],
+ }
command 'split'
command 'only'
@@ -5785,36 +5801,43 @@ describe('decorations: window scoped', function()
{8: 1 }1234^5 |
{1:~ }|*8
|
- ]]}
+ ]],
+ }
end)
it('spell', function()
- api.nvim_buf_set_lines(0,0,-1,true,{'aa'})
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'aa' })
- set_scoped_extmark(0, 0, {
- spell=true,
- end_col=2,
+ set_extmark(0, 0, {
+ spell = true,
+ end_col = 2,
})
command 'set spelloptions=noplainbuffer'
command 'set spell'
command 'syntax off'
+ screen:expect({ unchanged = true })
+
+ api.nvim__ns_set(ns, { wins = { win_other } })
+
screen:expect {
grid = [[
a^a |
{1:~ }|*8
|
- ]]}
+ ]],
+ }
- api.nvim__win_add_ns(0, ns)
+ api.nvim__ns_set(ns, { wins = { 0 } })
screen:expect {
grid = [[
{100:a^a} |
{1:~ }|*8
|
- ]]}
+ ]],
+ }
command 'split'
command 'only'
@@ -5824,25 +5847,25 @@ describe('decorations: window scoped', function()
a^a |
{1:~ }|*8
|
- ]]}
+ ]],
+ }
end)
it('url', function()
- set_scoped_extmark(0, 0, {
- end_col=3,
- url=url,
+ set_extmark(0, 0, {
+ end_col = 3,
+ url = url,
})
- screen:expect(noextmarks)
-
- api.nvim__win_add_ns(0, ns)
+ api.nvim__ns_set(ns, { wins = { 0 } })
screen:expect {
grid = [[
{101:123}4^5 |
{1:~ }|*8
|
- ]]}
+ ]],
+ }
command 'split'
command 'only'
@@ -5850,85 +5873,72 @@ describe('decorations: window scoped', function()
screen:expect(noextmarks)
end)
- it('change extmarks scoped option', function()
- local id = set_scoped_extmark(0, 0, {
+ it('change namespace scope', function()
+ set_extmark(0, 0, {
hl_group = 'Comment',
end_col = 3,
})
- api.nvim__win_add_ns(0, ns)
+ api.nvim__ns_set(ns, { wins = { 0 } })
+ eq({ wins={ api.nvim_get_current_win() } }, api.nvim__ns_get(ns))
screen:expect {
grid = [[
{18:123}4^5 |
{1:~ }|*8
|
- ]]}
+ ]],
+ }
command 'split'
command 'only'
screen:expect(noextmarks)
- api.nvim_buf_set_extmark(0, ns, 0, 0, {
- id = id,
- hl_group = 'Comment',
- end_col = 3,
- scoped = false,
- })
+ api.nvim__ns_set(ns, { wins = { 0 } })
+ eq({ wins={ api.nvim_get_current_win() } }, api.nvim__ns_get(ns))
screen:expect {
grid = [[
{18:123}4^5 |
{1:~ }|*8
|
- ]]}
+ ]],
+ }
- api.nvim_buf_set_extmark(0, ns, 0, 0, {
- id = id,
- hl_group = 'Comment',
- end_col = 3,
- scoped = true,
+ local win_new = api.nvim_open_win(0, false, {
+ col=0,row=0,width=20,height=10,
+ relative = 'win',style = 'minimal',
+ hide = true
})
+ api.nvim__ns_set(ns, { wins = { win_new } })
+ eq({ wins={ win_new } }, api.nvim__ns_get(ns))
+
screen:expect(noextmarks)
end)
- it('change namespace scope', function()
- set_scoped_extmark(0, 0, {
- hl_group = 'Comment',
- end_col = 3,
- })
+ it('namespace get works', function()
+ eq({ wins = {} }, api.nvim__ns_get(ns))
- eq(true, api.nvim__win_add_ns(0, ns))
- eq({ ns }, api.nvim__win_get_ns(0))
+ api.nvim__ns_set(ns, { wins = { 0 } })
- screen:expect {
- grid = [[
- {18:123}4^5 |
- {1:~ }|*8
- |
- ]]}
+ eq({ wins = { api.nvim_get_current_win() } }, api.nvim__ns_get(ns))
- command 'split'
- command 'only'
- eq({}, api.nvim__win_get_ns(0))
+ api.nvim__ns_set(ns, { wins = {} })
- screen:expect(noextmarks)
+ eq({ wins = {} }, api.nvim__ns_get(ns))
+ end)
- eq(true, api.nvim__win_add_ns(0, ns))
- eq({ ns }, api.nvim__win_get_ns(0))
+ it('remove window from namespace scope when deleted', function ()
+ api.nvim__ns_set(ns, { wins = { 0 } })
- screen:expect {
- grid = [[
- {18:123}4^5 |
- {1:~ }|*8
- |
- ]]}
+ eq({ wins = { api.nvim_get_current_win() } }, api.nvim__ns_get(ns))
- eq(true, api.nvim__win_del_ns(0, ns))
- eq({}, api.nvim__win_get_ns(0))
+ command 'split'
+ command 'only'
- screen:expect(noextmarks)
+ eq({ wins = {} }, api.nvim__ns_get(ns))
end)
end)
+