aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/extmark.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/api/extmark.c')
-rw-r--r--src/nvim/api/extmark.c360
1 files changed, 228 insertions, 132 deletions
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index d71498d6ed..1b03a97edb 100644
--- a/src/nvim/api/extmark.c
+++ b/src/nvim/api/extmark.c
@@ -14,16 +14,19 @@
#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/decoration.h"
+#include "nvim/decoration_defs.h"
#include "nvim/decoration_provider.h"
#include "nvim/drawscreen.h"
#include "nvim/extmark.h"
-#include "nvim/func_attr.h"
#include "nvim/grid.h"
#include "nvim/highlight_group.h"
+#include "nvim/map_defs.h"
#include "nvim/marktree.h"
+#include "nvim/marktree_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
+#include "nvim/move.h"
#include "nvim/pos_defs.h"
#include "nvim/sign.h"
@@ -40,7 +43,7 @@ void api_extmark_free_all_mem(void)
map_destroy(String, &namespace_ids);
}
-/// Creates a new namespace or gets an existing one. \*namespace\*
+/// Creates a new namespace or gets an existing one. [namespace]()
///
/// Namespaces are used for buffer highlights and virtual text, see
/// |nvim_buf_add_highlight()| and |nvim_buf_set_extmark()|.
@@ -69,15 +72,15 @@ Integer nvim_create_namespace(String name)
/// Gets existing, non-anonymous |namespace|s.
///
/// @return dict that maps from names to namespace ids.
-Dictionary nvim_get_namespaces(void)
+Dictionary nvim_get_namespaces(Arena *arena)
FUNC_API_SINCE(5)
{
- Dictionary retval = ARRAY_DICT_INIT;
+ Dictionary retval = arena_dict(arena, map_size(&namespace_ids));
String name;
handle_T id;
map_foreach(&namespace_ids, name, id, {
- PUT(retval, name.data, INTEGER_OBJ(id));
+ PUT_C(retval, name.data, INTEGER_OBJ(id));
})
return retval;
@@ -104,73 +107,85 @@ bool ns_initialized(uint32_t ns)
return ns < (uint32_t)next_namespace_id;
}
-Array virt_text_to_array(VirtText vt, bool hl_name)
+Array virt_text_to_array(VirtText vt, bool hl_name, Arena *arena)
{
- Array chunks = ARRAY_DICT_INIT;
- Array hl_array = ARRAY_DICT_INIT;
+ Array chunks = arena_array(arena, kv_size(vt));
for (size_t i = 0; i < kv_size(vt); i++) {
- char *text = kv_A(vt, i).text;
- int hl_id = kv_A(vt, i).hl_id;
- if (text == NULL) {
+ size_t j = i;
+ for (; j < kv_size(vt); j++) {
+ if (kv_A(vt, j).text != NULL) {
+ break;
+ }
+ }
+
+ Array hl_array = arena_array(arena, i < j ? j - i + 1 : 0);
+ for (; i < j; i++) {
+ int hl_id = kv_A(vt, i).hl_id;
if (hl_id > 0) {
- ADD(hl_array, hl_group_name(hl_id, hl_name));
+ ADD_C(hl_array, hl_group_name(hl_id, hl_name));
}
- continue;
}
- Array chunk = ARRAY_DICT_INIT;
- ADD(chunk, CSTR_TO_OBJ(text));
+
+ char *text = kv_A(vt, i).text;
+ int hl_id = kv_A(vt, i).hl_id;
+ Array chunk = arena_array(arena, 2);
+ ADD_C(chunk, CSTR_AS_OBJ(text));
if (hl_array.size > 0) {
if (hl_id > 0) {
- ADD(hl_array, hl_group_name(hl_id, hl_name));
+ ADD_C(hl_array, hl_group_name(hl_id, hl_name));
}
- ADD(chunk, ARRAY_OBJ(hl_array));
- hl_array = (Array)ARRAY_DICT_INIT;
+ ADD_C(chunk, ARRAY_OBJ(hl_array));
} else if (hl_id > 0) {
- ADD(chunk, hl_group_name(hl_id, hl_name));
+ ADD_C(chunk, hl_group_name(hl_id, hl_name));
}
- ADD(chunks, ARRAY_OBJ(chunk));
+ ADD_C(chunks, ARRAY_OBJ(chunk));
}
- assert(hl_array.size == 0);
return chunks;
}
-static Array extmark_to_array(MTPair extmark, bool id, bool add_dict, bool hl_name)
+static Array extmark_to_array(MTPair extmark, bool id, bool add_dict, bool hl_name, Arena *arena)
{
MTKey start = extmark.start;
- Array rv = ARRAY_DICT_INIT;
+ Array rv = arena_array(arena, 4);
if (id) {
- ADD(rv, INTEGER_OBJ((Integer)start.id));
+ ADD_C(rv, INTEGER_OBJ((Integer)start.id));
}
- ADD(rv, INTEGER_OBJ(start.pos.row));
- ADD(rv, INTEGER_OBJ(start.pos.col));
+ ADD_C(rv, INTEGER_OBJ(start.pos.row));
+ ADD_C(rv, INTEGER_OBJ(start.pos.col));
if (add_dict) {
- Dictionary dict = ARRAY_DICT_INIT;
+ // TODO(bfredl): coding the size like this is a bit fragile.
+ // We want ArrayOf(Dict(set_extmark)) as the return type..
+ Dictionary dict = arena_dict(arena, ARRAY_SIZE(set_extmark_table));
- PUT(dict, "ns_id", INTEGER_OBJ((Integer)start.ns));
+ PUT_C(dict, "ns_id", INTEGER_OBJ((Integer)start.ns));
- PUT(dict, "right_gravity", BOOLEAN_OBJ(mt_right(start)));
+ PUT_C(dict, "right_gravity", BOOLEAN_OBJ(mt_right(start)));
- if (extmark.end_pos.row >= 0) {
- PUT(dict, "end_row", INTEGER_OBJ(extmark.end_pos.row));
- PUT(dict, "end_col", INTEGER_OBJ(extmark.end_pos.col));
- PUT(dict, "end_right_gravity", BOOLEAN_OBJ(extmark.end_right_gravity));
+ if (mt_paired(start)) {
+ PUT_C(dict, "end_row", INTEGER_OBJ(extmark.end_pos.row));
+ PUT_C(dict, "end_col", INTEGER_OBJ(extmark.end_pos.col));
+ PUT_C(dict, "end_right_gravity", BOOLEAN_OBJ(extmark.end_right_gravity));
}
if (mt_no_undo(start)) {
- PUT(dict, "undo_restore", BOOLEAN_OBJ(false));
+ PUT_C(dict, "undo_restore", BOOLEAN_OBJ(false));
}
if (mt_invalidate(start)) {
- PUT(dict, "invalidate", BOOLEAN_OBJ(true));
+ PUT_C(dict, "invalidate", BOOLEAN_OBJ(true));
}
if (mt_invalid(start)) {
- PUT(dict, "invalid", BOOLEAN_OBJ(true));
+ 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);
+ decor_to_dict_legacy(&dict, mt_decor(start), hl_name, arena);
- ADD(rv, DICTIONARY_OBJ(dict));
+ ADD_C(rv, DICTIONARY_OBJ(dict));
}
return rv;
@@ -188,8 +203,8 @@ static Array extmark_to_array(MTPair extmark, bool id, bool add_dict, bool hl_na
/// @return 0-indexed (row, col) tuple or empty list () if extmark id was
/// absent
ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
- Integer id, Dictionary opts,
- Error *err)
+ Integer id, Dict(get_extmark) *opts,
+ Arena *arena, Error *err)
FUNC_API_SINCE(7)
{
Array rv = ARRAY_DICT_INIT;
@@ -204,37 +219,19 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
return rv;
});
- bool details = false;
- bool hl_name = true;
- for (size_t i = 0; i < opts.size; i++) {
- String k = opts.items[i].key;
- Object *v = &opts.items[i].value;
- if (strequal("details", k.data)) {
- details = api_object_to_bool(*v, "details", false, err);
- if (ERROR_SET(err)) {
- return rv;
- }
- } else if (strequal("hl_name", k.data)) {
- hl_name = api_object_to_bool(*v, "hl_name", false, err);
- if (ERROR_SET(err)) {
- return rv;
- }
- } else {
- VALIDATE_S(false, "'opts' key", k.data, {
- return rv;
- });
- }
- }
+ bool details = opts->details;
+
+ bool hl_name = GET_BOOL_OR_TRUE(opts, get_extmark, hl_name);
MTPair extmark = extmark_from_id(buf, (uint32_t)ns_id, (uint32_t)id);
if (extmark.start.pos.row < 0) {
return rv;
}
- return extmark_to_array(extmark, false, details, hl_name);
+ return extmark_to_array(extmark, false, details, hl_name, arena);
}
-/// Gets |extmarks| (including |signs|) in "traversal order" from a |charwise|
-/// region defined by buffer positions (inclusive, 0-indexed |api-indexing|).
+/// Gets |extmarks| in "traversal order" from a |charwise| region defined by
+/// buffer positions (inclusive, 0-indexed |api-indexing|).
///
/// Region can be given as (row,col) tuples, or valid extmark ids (whose
/// positions define the bounds). 0 and -1 are understood as (0,0) and (-1,-1)
@@ -252,6 +249,10 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
/// the `overlap` option might be useful. Otherwise only the start position
/// of an extmark will be considered.
///
+/// Note: legacy signs placed through the |:sign| commands are implemented
+/// as extmarks and will show up here. Their details array will contain a
+/// `sign_name` field.
+///
/// Example:
///
/// ```lua
@@ -283,9 +284,9 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
/// their start position is less than `start`
/// - type: Filter marks by type: "highlight", "sign", "virt_text" and "virt_lines"
/// @param[out] err Error details, if any
-/// @return List of [extmark_id, row, col] tuples in "traversal order".
+/// @return List of `[extmark_id, row, col]` tuples in "traversal order".
Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object end,
- Dict(get_extmarks) *opts, Error *err)
+ Dict(get_extmarks) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(7)
{
Array rv = ARRAY_DICT_INIT;
@@ -349,8 +350,9 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
ExtmarkInfoArray marks = extmark_get(buf, (uint32_t)ns_id, l_row, l_col, u_row,
u_col, (int64_t)limit, reverse, type, opts->overlap);
+ rv = arena_array(arena, kv_size(marks));
for (size_t i = 0; i < kv_size(marks); i++) {
- ADD(rv, ARRAY_OBJ(extmark_to_array(kv_A(marks, i), true, details, hl_name)));
+ ADD_C(rv, ARRAY_OBJ(extmark_to_array(kv_A(marks, i), true, details, hl_name, arena)));
}
kv_destroy(marks);
@@ -388,7 +390,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
/// of the screen line (just like for diff and
/// cursorline highlight).
/// - virt_text : virtual text to link to this mark.
-/// A list of [text, highlight] tuples, each representing a
+/// A list of `[text, highlight]` tuples, each representing a
/// text chunk with specified highlight. `highlight` element
/// can either be a single highlight group, or an array of
/// multiple highlight groups that will be stacked
@@ -410,6 +412,8 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
/// text is selected or hidden because of
/// scrolling with 'nowrap' or 'smoothscroll'.
/// Currently only affects "overlay" virt_text.
+/// - virt_text_repeat_linebreak : repeat the virtual text on
+/// wrapped lines.
/// - hl_mode : control how highlights are combined with the
/// highlights of the text. Currently only affects
/// virt_text highlights, but might affect `hl_group`
@@ -421,7 +425,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
///
/// - virt_lines : virtual lines to add next to this mark
/// This should be an array over lines, where each line in
-/// turn is an array over [text, highlight] tuples. In
+/// turn is an array over `[text, highlight]` tuples. In
/// general, buffer and window options do not affect the
/// display of the text. In particular 'wrap'
/// and 'linebreak' options do not take effect, so
@@ -450,35 +454,28 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
/// if text around the mark was deleted and then restored by undo.
/// Defaults to true.
/// - invalidate : boolean that indicates whether to hide the
-/// extmark if the entirety of its range is deleted. If
+/// extmark if the entirety of its range is deleted. For
+/// hidden marks, an "invalid" key is added to the "details"
+/// array of |nvim_buf_get_extmarks()| and family. If
/// "undo_restore" is false, the extmark is deleted instead.
-/// - priority: a priority value for the highlight group or sign
-/// attribute. For example treesitter highlighting uses a
-/// value of 100.
+/// - priority: a priority value for the highlight group, sign
+/// attribute or virtual text. For virtual text, item with
+/// highest priority is drawn last. For example treesitter
+/// highlighting uses a value of 100.
/// - strict: boolean that indicates extmark should not be placed
/// if the line or column value is past the end of the
/// buffer or end of the line respectively. Defaults to true.
/// - sign_text: string of length 1-2 used to display in the
/// sign column.
-/// Note: ranges are unsupported and decorations are only
-/// applied to start_row
/// - sign_hl_group: name of the highlight group used to
/// highlight the sign column text.
-/// Note: ranges are unsupported and decorations are only
-/// applied to start_row
/// - number_hl_group: name of the highlight group used to
/// highlight the number column.
-/// Note: ranges are unsupported and decorations are only
-/// applied to start_row
/// - line_hl_group: name of the highlight group used to
/// highlight the whole line.
-/// Note: ranges are unsupported and decorations are only
-/// applied to start_row
/// - cursorline_hl_group: name of the highlight group used to
-/// highlight the line when the cursor is on the same line
-/// as the mark and 'cursorline' is enabled.
-/// Note: ranges are unsupported and decorations are only
-/// applied to start_row
+/// highlight the sign column text when the cursor is on
+/// the same line as the mark and 'cursorline' is enabled.
/// - conceal: string which should be either empty or a single
/// character. Enable concealing similar to |:syn-conceal|.
/// When a character is supplied it is used as |:syn-cchar|.
@@ -490,6 +487,10 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
/// by a UI. When set, the UI will receive win_extmark events.
/// Note: the mark is positioned by virt_text attributes. Can be
/// used together with virt_text.
+/// - url: A URL to associate with this extmark. In the TUI, the OSC 8 control
+/// sequence is used to generate a clickable hyperlink to this URL.
+/// - scoped: boolean that indicates that the extmark should only be
+/// displayed in the namespace scope. (experimental)
///
/// @param[out] err Error details, if any
/// @return Id of the created/updated extmark
@@ -503,6 +504,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
DecorSignHighlight sign = DECOR_SIGN_HIGHLIGHT_INIT;
DecorVirtText virt_text = DECOR_VIRT_TEXT_INIT;
DecorVirtText virt_lines = DECOR_VIRT_LINES_INIT;
+ char *url = NULL;
bool has_hl = false;
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -556,36 +558,15 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
col2 = (int)val;
}
- // uncrustify:off
+ hl.hl_id = (int)opts->hl_group;
+ has_hl = hl.hl_id > 0;
+ sign.hl_id = (int)opts->sign_hl_group;
+ sign.cursorline_hl_id = (int)opts->cursorline_hl_group;
+ sign.number_hl_id = (int)opts->number_hl_group;
+ sign.line_hl_id = (int)opts->line_hl_group;
- // TODO(bfredl): keyset type alias for hl_group? (nil|int|string)
- struct {
- const char *name;
- Object *opt;
- int *dest;
- } hls[] = {
- { "hl_group" , &opts->hl_group , &hl.hl_id },
- { "sign_hl_group" , &opts->sign_hl_group , &sign.hl_id },
- { "number_hl_group" , &opts->number_hl_group , &sign.number_hl_id },
- { "line_hl_group" , &opts->line_hl_group , &sign.line_hl_id },
- { "cursorline_hl_group", &opts->cursorline_hl_group, &sign.cursorline_hl_id },
- { NULL, NULL, NULL },
- };
-
- // uncrustify:on
-
- for (int j = 0; hls[j].name && hls[j].dest; j++) {
- if (hls[j].opt->type != kObjectTypeNil) {
- if (j > 0) {
- sign.flags |= kSHIsSign;
- } else {
- has_hl = true;
- }
- *hls[j].dest = object_to_hl_id(*hls[j].opt, hls[j].name, err);
- if (ERROR_SET(err)) {
- goto error;
- }
- }
+ if (sign.hl_id || sign.cursorline_hl_id || sign.number_hl_id || sign.line_hl_id) {
+ sign.flags |= kSHIsSign;
}
if (HAS_KEY(opts, set_extmark, conceal)) {
@@ -632,7 +613,8 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
}
hl.flags |= opts->hl_eol ? kSHHlEol : 0;
- virt_text.flags |= opts->virt_text_hide ? kVTHide : 0;
+ virt_text.flags |= ((opts->virt_text_hide ? kVTHide : 0)
+ | (opts->virt_text_repeat_linebreak ? kVTRepeatLinebreak : 0));
if (HAS_KEY(opts, set_extmark, hl_mode)) {
String str = opts->hl_mode;
@@ -684,9 +666,8 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
}
if (HAS_KEY(opts, set_extmark, sign_text)) {
- sign.text.ptr = NULL;
- VALIDATE_S(init_sign_text(NULL, &sign.text.ptr, opts->sign_text.data),
- "sign_text", "", {
+ sign.text[0] = 0;
+ VALIDATE_S(init_sign_text(NULL, sign.text, opts->sign_text.data), "sign_text", "", {
goto error;
});
sign.flags |= kSHIsSign;
@@ -708,6 +689,10 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
has_hl = true;
}
+ if (HAS_KEY(opts, set_extmark, url)) {
+ url = string_to_cstr(opts->url);
+ }
+
if (opts->ui_watched) {
hl.flags |= kSHUIWatched;
if (virt_text.pos == kVPosOverlay) {
@@ -764,6 +749,11 @@ 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) {
@@ -771,15 +761,32 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
col2 = c;
}
+ DecorPriority subpriority = DECOR_PRIORITY_BASE;
+ if (HAS_KEY(opts, set_extmark, _subpriority)) {
+ VALIDATE_RANGE((opts->_subpriority >= 0 && opts->_subpriority <= UINT16_MAX),
+ "_subpriority", {
+ goto error;
+ });
+ subpriority = (DecorPriority)opts->_subpriority;
+ }
+
if (kv_size(virt_text.data.virt_text)) {
- decor_range_add_virt(&decor_state, r, c, line2, col2, decor_put_vt(virt_text, NULL), true);
+ decor_range_add_virt(&decor_state, r, c, line2, col2, decor_put_vt(virt_text, NULL), true,
+ subpriority);
}
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);
+ decor_range_add_virt(&decor_state, r, c, line2, col2, decor_put_vt(virt_lines, NULL), true,
+ subpriority);
+ }
+ if (url != NULL) {
+ DecorSignHighlight sh = DECOR_SIGN_HIGHLIGHT_INIT;
+ sh.url = url;
+ decor_range_add_sh(&decor_state, r, c, line2, col2, &sh, true, 0, 0, subpriority);
}
if (has_hl) {
DecorSignHighlight sh = decor_sh_from_inline(hl);
- decor_range_add_sh(&decor_state, r, c, line2, col2, &sh, true, (uint32_t)ns_id, id);
+ decor_range_add_sh(&decor_state, r, c, line2, col2, &sh, true, (uint32_t)ns_id, id,
+ subpriority);
}
} else {
if (opts->ephemeral) {
@@ -802,9 +809,16 @@ 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);
- if (sign.text.ptr != NULL) {
+ if (sign.text[0]) {
decor_flags |= MT_FLAG_DECOR_SIGNTEXT;
}
if (sign.number_hl_id || sign.line_hl_id || sign.cursorline_hl_id) {
@@ -832,7 +846,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, err);
+ opts->invalidate, opts->scoped, err);
if (ERROR_SET(err)) {
decor_free(decor);
return 0;
@@ -844,6 +858,10 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
error:
clear_virttext(&virt_text.data.virt_text);
clear_virtlines(&virt_lines.data.virt_lines);
+ if (url != NULL) {
+ xfree(url);
+ }
+
return 0;
}
@@ -954,7 +972,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, NULL);
+ decor, MT_FLAG_DECOR_HL, true, false, false, false, false, NULL);
return ns_id;
}
@@ -1022,19 +1040,27 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start,
/// @param ns_id Namespace id from |nvim_create_namespace()|
/// @param opts Table of callbacks:
/// - on_start: called first on each screen redraw
+/// ```
/// ["start", tick]
+/// ```
/// - on_buf: called for each buffer being redrawn (before
-/// window callbacks)
+/// window callbacks)
+/// ```
/// ["buf", bufnr, tick]
-/// - on_win: called when starting to redraw a
-/// specific window. botline_guess is an approximation
-/// that does not exceed the last line number.
-/// ["win", winid, bufnr, topline, botline_guess]
+/// ```
+/// - on_win: called when starting to redraw a specific window.
+/// ```
+/// ["win", winid, bufnr, topline, botline]
+/// ```
/// - on_line: called for each buffer line being redrawn.
/// (The interaction with fold lines is subject to change)
-/// ["win", winid, bufnr, row]
+/// ```
+/// ["line", winid, bufnr, row]
+/// ```
/// - on_end: called at the end of a redraw cycle
+/// ```
/// ["end", tick]
+/// ```
void nvim_set_decoration_provider(Integer ns_id, Dict(set_decoration_provider) *opts, Error *err)
FUNC_API_SINCE(7) FUNC_API_LUA_ONLY
{
@@ -1070,7 +1096,7 @@ void nvim_set_decoration_provider(Integer ns_id, Dict(set_decoration_provider) *
*v = LUA_NOREF;
}
- p->active = true;
+ p->state = kDecorProviderActive;
p->hl_valid++;
p->hl_cached = false;
}
@@ -1189,8 +1215,9 @@ free_exit:
return virt_text;
}
+/// @nodoc
String nvim__buf_debug_extmarks(Buffer buffer, Boolean keys, Boolean dot, Error *err)
- FUNC_API_SINCE(7)
+ FUNC_API_SINCE(7) FUNC_API_RET_ALLOC
{
buf_T *buf = find_buffer_by_handle(buffer, err);
if (!buf) {
@@ -1199,3 +1226,72 @@ String nvim__buf_debug_extmarks(Buffer buffer, Boolean keys, Boolean dot, Error
return mt_inspect(buf->b_marktree, keys, dot);
}
+
+/// Adds the namespace scope to the window.
+///
+/// @param window Window handle, or 0 for current window
+/// @param ns_id the namespace to add
+/// @return true if the namespace was added, else false
+Boolean nvim_win_add_ns(Window window, Integer ns_id, Error *err)
+ FUNC_API_SINCE(12)
+{
+ 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;
+ });
+
+ set_put(uint32_t, &win->w_ns_set, (uint32_t)ns_id);
+
+ changed_window_setting_win(win);
+
+ return true;
+}
+
+/// Gets all the namespaces scopes associated with a window.
+///
+/// @param window Window handle, or 0 for current window
+/// @return a list of namespaces ids
+ArrayOf(Integer) nvim_win_get_ns(Window window, Arena *arena, Error *err)
+ FUNC_API_SINCE(12)
+{
+ win_T *win = find_window_by_handle(window, err);
+ if (!win) {
+ return (Array)ARRAY_DICT_INIT;
+ }
+
+ 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)));
+ });
+
+ return rv;
+}
+
+/// Removes the namespace scope from the window.
+///
+/// @param window Window handle, or 0 for current window
+/// @param ns_id the namespace to remove
+/// @return true if the namespace was removed, else false
+Boolean nvim_win_remove_ns(Window window, Integer ns_id, Error *err)
+ FUNC_API_SINCE(12)
+{
+ win_T *win = find_window_by_handle(window, err);
+ if (!win) {
+ return false;
+ }
+
+ if (!set_has(uint32_t, &win->w_ns_set, (uint32_t)ns_id)) {
+ return false;
+ }
+
+ set_del(uint32_t, &win->w_ns_set, (uint32_t)ns_id);
+
+ changed_window_setting_win(win);
+
+ return true;
+}