diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 5a106288fd..a47694a0cf 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -2005,7 +2005,7 @@ Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Arena *arena, E ADD_C(ret, DICTIONARY_OBJ(hl_get_attr_by_id(attr, true, arena, err))); // will not work first time if (!highlight_use_hlstate()) { - ADD_C(ret, ARRAY_OBJ(hl_inspect(attr))); + ADD_C(ret, ARRAY_OBJ(hl_inspect(attr, arena))); } return ret; } diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 8b1c226851..1dc06ec988 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -116,12 +116,13 @@ retry: {} // new attr id, send event to remote ui:s int id = (int)k; - Array inspect = hl_inspect(id); + Arena arena = ARENA_EMPTY; + Array inspect = hl_inspect(id, &arena); // Note: internally we don't distinguish between cterm and rgb attributes, // remote_ui_hl_attr_define will however. ui_call_hl_attr_define(id, entry.attr, entry.attr, inspect); - api_free_array(inspect); + arena_mem_free(arena_finish(&arena)); return id; } @@ -129,10 +130,11 @@ retry: {} void ui_send_all_hls(UI *ui) { for (size_t i = 1; i < set_size(&attr_entries); i++) { - Array inspect = hl_inspect((int)i); + Arena arena = ARENA_EMPTY; + Array inspect = hl_inspect((int)i, &arena); HlAttrs attr = attr_entry(i).attr; remote_ui_hl_attr_define(ui, (Integer)i, attr, attr, inspect); - api_free_array(inspect); + arena_mem_free(arena_finish(&arena)); } for (size_t hlf = 0; hlf < HLF_COUNT; hlf++) { remote_ui_hl_group_set(ui, cstr_as_string(hlf_names[hlf]), @@ -204,7 +206,7 @@ int ns_get_hl(NS *ns_hl, int hl_id, bool link, bool nodefault) if (!valid_item && p->hl_def != LUA_NOREF && !recursive) { MAXSIZE_TEMP_ARRAY(args, 3); ADD_C(args, INTEGER_OBJ((Integer)ns_id)); - ADD_C(args, CSTR_TO_OBJ(syn_id2name(hl_id))); + ADD_C(args, CSTR_AS_OBJ(syn_id2name(hl_id))); ADD_C(args, BOOLEAN_OBJ(link)); // TODO(bfredl): preload the "global" attr dict? @@ -1176,17 +1178,30 @@ int object_to_color(Object val, char *key, bool rgb, Error *err) } } -Array hl_inspect(int attr) +Array hl_inspect(int attr, Arena *arena) { - // TODO(bfredl): use arena allocation - Array ret = ARRAY_DICT_INIT; - if (hlstate_active) { - hl_inspect_impl(&ret, attr); + if (!hlstate_active) { + return (Array)ARRAY_DICT_INIT; } + Array ret = arena_array(arena, hl_inspect_size(attr)); + hl_inspect_impl(&ret, attr, arena); return ret; } -static void hl_inspect_impl(Array *arr, int attr) +static size_t hl_inspect_size(int attr) +{ + if (attr <= 0 || attr >= (int)set_size(&attr_entries)) { + return 0; + } + + HlEntry e = attr_entry(attr); + if (e.kind == kHlCombine || e.kind == kHlBlend || e.kind == kHlBlendThrough) { + return hl_inspect_size(e.id1) + hl_inspect_size(e.id2); + } + return 1; +} + +static void hl_inspect_impl(Array *arr, int attr, Arena *arena) { Dictionary item = ARRAY_DICT_INIT; if (attr <= 0 || attr >= (int)set_size(&attr_entries)) { @@ -1196,35 +1211,36 @@ static void hl_inspect_impl(Array *arr, int attr) HlEntry e = attr_entry(attr); switch (e.kind) { case kHlSyntax: - PUT(item, "kind", CSTR_TO_OBJ("syntax")); - PUT(item, "hi_name", - CSTR_TO_OBJ(syn_id2name(e.id1))); + item = arena_dict(arena, 3); + PUT_C(item, "kind", CSTR_AS_OBJ("syntax")); + PUT_C(item, "hi_name", CSTR_AS_OBJ(syn_id2name(e.id1))); break; case kHlUI: - PUT(item, "kind", CSTR_TO_OBJ("ui")); + item = arena_dict(arena, 4); + PUT_C(item, "kind", CSTR_AS_OBJ("ui")); const char *ui_name = (e.id1 == -1) ? "Normal" : hlf_names[e.id1]; - PUT(item, "ui_name", CSTR_TO_OBJ(ui_name)); - PUT(item, "hi_name", - CSTR_TO_OBJ(syn_id2name(e.id2))); + PUT_C(item, "ui_name", CSTR_AS_OBJ(ui_name)); + PUT_C(item, "hi_name", CSTR_AS_OBJ(syn_id2name(e.id2))); break; case kHlTerminal: - PUT(item, "kind", CSTR_TO_OBJ("term")); + item = arena_dict(arena, 2); + PUT_C(item, "kind", CSTR_AS_OBJ("term")); break; case kHlCombine: case kHlBlend: case kHlBlendThrough: // attribute combination is associative, so flatten to an array - hl_inspect_impl(arr, e.id1); - hl_inspect_impl(arr, e.id2); + hl_inspect_impl(arr, e.id1, arena); + hl_inspect_impl(arr, e.id2, arena); return; case kHlUnknown: case kHlInvalid: return; } - PUT(item, "id", INTEGER_OBJ(attr)); - ADD(*arr, DICTIONARY_OBJ(item)); + PUT_C(item, "id", INTEGER_OBJ(attr)); + ADD_C(*arr, DICTIONARY_OBJ(item)); }