diff options
Diffstat (limited to 'src/nvim/api')
-rw-r--r-- | src/nvim/api/extmark.c | 81 | ||||
-rw-r--r-- | src/nvim/api/private/helpers.c | 48 | ||||
-rw-r--r-- | src/nvim/api/private/helpers.h | 4 | ||||
-rw-r--r-- | src/nvim/api/win_config.c | 92 |
4 files changed, 142 insertions, 83 deletions
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index 4e84b41a02..0948abf065 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -105,73 +105,81 @@ 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 (mt_paired(start)) { - 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)); + 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)); } - 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; @@ -190,7 +198,7 @@ static Array extmark_to_array(MTPair extmark, bool id, bool add_dict, bool hl_na /// absent ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id, Integer id, Dict(get_extmark) *opts, - Error *err) + Arena *arena, Error *err) FUNC_API_SINCE(7) { Array rv = ARRAY_DICT_INIT; @@ -213,7 +221,7 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_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| in "traversal order" from a |charwise| region defined by @@ -272,7 +280,7 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id, /// @param[out] err Error details, if any /// @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; @@ -336,8 +344,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(rv, ARRAY_OBJ(extmark_to_array(kv_A(marks, i), true, details, hl_name, arena))); } kv_destroy(marks); diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 9ce1786fa0..cc95f46baf 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -1014,6 +1014,54 @@ bool api_dict_to_keydict(void *retval, FieldHashfn hashy, Dictionary dict, Error return true; } +Dictionary api_keydict_to_dict(void *value, KeySetLink *table, size_t max_size, Arena *arena) +{ + Dictionary rv = arena_dict(arena, max_size); + for (size_t i = 0; table[i].str; i++) { + KeySetLink *field = &table[i]; + bool is_set = true; + if (field->opt_index >= 0) { + OptKeySet *ks = (OptKeySet *)value; + is_set = ks->is_set_ & (1ULL << field->opt_index); + } + + if (!is_set) { + continue; + } + + char *mem = ((char *)value + field->ptr_off); + Object val = NIL; + + if (field->type == kObjectTypeNil) { + val = *(Object *)mem; + } else if (field->type == kObjectTypeInteger) { + val = INTEGER_OBJ(*(Integer *)mem); + } else if (field->type == kObjectTypeFloat) { + val = FLOAT_OBJ(*(Float *)mem); + } else if (field->type == kObjectTypeBoolean) { + val = BOOLEAN_OBJ(*(Boolean *)mem); + } else if (field->type == kObjectTypeString) { + val = STRING_OBJ(*(String *)mem); + } else if (field->type == kObjectTypeArray) { + val = ARRAY_OBJ(*(Array *)mem); + } else if (field->type == kObjectTypeDictionary) { + val = DICTIONARY_OBJ(*(Dictionary *)mem); + } else if (field->type == kObjectTypeBuffer || field->type == kObjectTypeWindow + || field->type == kObjectTypeTabpage) { + val.data.integer = *(Integer *)mem; + val.type = field->type; + } else if (field->type == kObjectTypeLuaRef) { + // do nothing + } else { + abort(); + } + + PUT_C(rv, field->str, val); + } + + return rv; +} + void api_free_keydict(void *dict, KeySetLink *table) { for (size_t i = 0; table[i].str; i++) { diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h index 8a56d1704f..0dbe3d2fb6 100644 --- a/src/nvim/api/private/helpers.h +++ b/src/nvim/api/private/helpers.h @@ -32,6 +32,7 @@ #define CSTR_AS_OBJ(s) STRING_OBJ(cstr_as_string(s)) #define CSTR_TO_OBJ(s) STRING_OBJ(cstr_to_string(s)) +#define CSTR_TO_ARENA_OBJ(arena, s) STRING_OBJ(arena_string(arena, cstr_as_string(s))) #define BUFFER_OBJ(s) ((Object) { \ .type = kObjectTypeBuffer, \ @@ -70,6 +71,9 @@ #define PUT_C(dict, k, v) \ kv_push_c(dict, ((KeyValuePair) { .key = cstr_as_string(k), .value = v })) +#define PUT_KEY(d, typ, key, v) \ + do { (d).is_set__##typ##_ |= (1 << KEYSET_OPTIDX_##typ##__##key); (d).key = v; } while (0) + #define ADD(array, item) \ kv_push(array, item) diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c index 041aaed976..a9d7a8d05c 100644 --- a/src/nvim/api/win_config.c +++ b/src/nvim/api/win_config.c @@ -539,30 +539,24 @@ void nvim_win_set_config(Window window, Dict(float_config) *config, Error *err) #undef HAS_KEY_X } -static Dictionary config_put_bordertext(Dictionary config, FloatConfig *fconfig, - BorderTextType bordertext_type) +#define PUT_KEY_X(d, key, value) PUT_KEY(d, float_config, key, value) +static void config_put_bordertext(Dict(float_config) *config, FloatConfig *fconfig, + BorderTextType bordertext_type, Arena *arena) { VirtText vt; AlignTextPos align; - char *field_name; - char *field_pos_name; switch (bordertext_type) { case kBorderTextTitle: vt = fconfig->title_chunks; align = fconfig->title_pos; - field_name = "title"; - field_pos_name = "title_pos"; break; case kBorderTextFooter: vt = fconfig->footer_chunks; align = fconfig->footer_pos; - field_name = "footer"; - field_pos_name = "footer_pos"; break; } - Array bordertext = virt_text_to_array(vt, true); - PUT(config, field_name, ARRAY_OBJ(bordertext)); + Array bordertext = virt_text_to_array(vt, true, arena); char *pos; switch (align) { @@ -576,9 +570,16 @@ static Dictionary config_put_bordertext(Dictionary config, FloatConfig *fconfig, pos = "right"; break; } - PUT(config, field_pos_name, CSTR_TO_OBJ(pos)); - return config; + switch (bordertext_type) { + case kBorderTextTitle: + PUT_KEY_X(*config, title, ARRAY_OBJ(bordertext)); + PUT_KEY_X(*config, title_pos, cstr_as_string(pos)); + break; + case kBorderTextFooter: + PUT_KEY_X(*config, footer, ARRAY_OBJ(bordertext)); + PUT_KEY_X(*config, footer_pos, cstr_as_string(pos)); + } } /// Gets window configuration. @@ -590,7 +591,7 @@ static Dictionary config_put_bordertext(Dictionary config, FloatConfig *fconfig, /// @param window Window handle, or 0 for current window /// @param[out] err Error details, if any /// @return Map defining the window configuration, see |nvim_open_win()| -Dictionary nvim_win_get_config(Window window, Error *err) +Dict(float_config) nvim_win_get_config(Window window, Arena *arena, Error *err) FUNC_API_SINCE(6) { /// Keep in sync with FloatRelative in buffer_defs.h @@ -599,7 +600,7 @@ Dictionary nvim_win_get_config(Window window, Error *err) /// Keep in sync with WinSplit in buffer_defs.h static const char *const win_split_str[] = { "left", "right", "above", "below" }; - Dictionary rv = ARRAY_DICT_INIT; + Dict(float_config) rv = { 0 }; win_T *wp = find_window_by_handle(window, err); if (!wp) { @@ -608,65 +609,62 @@ Dictionary nvim_win_get_config(Window window, Error *err) FloatConfig *config = &wp->w_float_config; - PUT(rv, "focusable", BOOLEAN_OBJ(config->focusable)); - PUT(rv, "external", BOOLEAN_OBJ(config->external)); - PUT(rv, "hide", BOOLEAN_OBJ(config->hide)); + PUT_KEY_X(rv, focusable, config->focusable); + PUT_KEY_X(rv, external, config->external); + PUT_KEY_X(rv, hide, config->hide); if (wp->w_floating) { - PUT(rv, "width", INTEGER_OBJ(config->width)); - PUT(rv, "height", INTEGER_OBJ(config->height)); + PUT_KEY_X(rv, width, config->width); + PUT_KEY_X(rv, height, config->height); if (!config->external) { if (config->relative == kFloatRelativeWindow) { - PUT(rv, "win", INTEGER_OBJ(config->window)); + PUT_KEY_X(rv, win, config->window); if (config->bufpos.lnum >= 0) { - Array pos = ARRAY_DICT_INIT; - ADD(pos, INTEGER_OBJ(config->bufpos.lnum)); - ADD(pos, INTEGER_OBJ(config->bufpos.col)); - PUT(rv, "bufpos", ARRAY_OBJ(pos)); + Array pos = arena_array(arena, 2); + ADD_C(pos, INTEGER_OBJ(config->bufpos.lnum)); + ADD_C(pos, INTEGER_OBJ(config->bufpos.col)); + PUT_KEY_X(rv, bufpos, pos); } } - PUT(rv, "anchor", CSTR_TO_OBJ(float_anchor_str[config->anchor])); - PUT(rv, "row", FLOAT_OBJ(config->row)); - PUT(rv, "col", FLOAT_OBJ(config->col)); - PUT(rv, "zindex", INTEGER_OBJ(config->zindex)); + PUT_KEY_X(rv, anchor, cstr_as_string((char *)float_anchor_str[config->anchor])); + PUT_KEY_X(rv, row, config->row); + PUT_KEY_X(rv, col, config->col); + PUT_KEY_X(rv, zindex, config->zindex); } if (config->border) { - Array border = ARRAY_DICT_INIT; + Array border = arena_array(arena, 8); for (size_t i = 0; i < 8; i++) { - Array tuple = ARRAY_DICT_INIT; - - String s = cstrn_to_string(config->border_chars[i], MAX_SCHAR_SIZE); + String s = cstrn_as_string(config->border_chars[i], MAX_SCHAR_SIZE); int hi_id = config->border_hl_ids[i]; char *hi_name = syn_id2name(hi_id); if (hi_name[0]) { - ADD(tuple, STRING_OBJ(s)); - ADD(tuple, CSTR_TO_OBJ(hi_name)); - ADD(border, ARRAY_OBJ(tuple)); + Array tuple = arena_array(arena, 2); + ADD_C(tuple, STRING_OBJ(s)); + ADD_C(tuple, CSTR_AS_OBJ(hi_name)); + ADD_C(border, ARRAY_OBJ(tuple)); } else { - ADD(border, STRING_OBJ(s)); + ADD_C(border, STRING_OBJ(s)); } } - PUT(rv, "border", ARRAY_OBJ(border)); + PUT_KEY_X(rv, border, ARRAY_OBJ(border)); if (config->title) { - rv = config_put_bordertext(rv, config, kBorderTextTitle); + config_put_bordertext(&rv, config, kBorderTextTitle, arena); } if (config->footer) { - rv = config_put_bordertext(rv, config, kBorderTextFooter); + config_put_bordertext(&rv, config, kBorderTextFooter, arena); } } } else if (!config->external) { - PUT(rv, "width", INTEGER_OBJ(wp->w_width)); - PUT(rv, "height", INTEGER_OBJ(wp->w_height)); + PUT_KEY_X(rv, width, wp->w_width); + PUT_KEY_X(rv, height, wp->w_height); WinSplit split = win_split_dir(wp); - PUT(rv, "split", CSTR_TO_OBJ(win_split_str[split])); + PUT_KEY_X(rv, split, cstr_as_string((char *)win_split_str[split])); } - if (wp->w_floating && !config->external) { - PUT(rv, "relative", CSTR_TO_OBJ(float_relative_str[config->relative])); - } else { - PUT(rv, "relative", CSTR_TO_OBJ("")); - } + const char *rel = (wp->w_floating && !config->external + ? float_relative_str[config->relative] : ""); + PUT_KEY_X(rv, relative, cstr_as_string((char *)rel)); return rv; } |