diff options
author | Björn Linse <bjorn.linse@gmail.com> | 2021-08-21 13:55:12 +0200 |
---|---|---|
committer | Björn Linse <bjorn.linse@gmail.com> | 2021-10-03 10:46:57 +0200 |
commit | 32565922efe0d1a6e8e4dddb23295d1a08670b54 (patch) | |
tree | 501dd50b3ae199e3b52071d66d307e9d69772f82 /src/nvim/api/buffer.c | |
parent | 9337fff8aad610acd5ef619f757686c47f0c118c (diff) | |
download | rneovim-32565922efe0d1a6e8e4dddb23295d1a08670b54.tar.gz rneovim-32565922efe0d1a6e8e4dddb23295d1a08670b54.tar.bz2 rneovim-32565922efe0d1a6e8e4dddb23295d1a08670b54.zip |
refactor(api): handle option dicts properly
Do not copy a lot of lua strings (dict keys) to just strequal() them
Just compare them directly to a dedicated hash function.
feat(generators): HASHY McHASHFACE
Diffstat (limited to 'src/nvim/api/buffer.c')
-rw-r--r-- | src/nvim/api/buffer.c | 371 |
1 files changed, 153 insertions, 218 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 0ef2776263..34d7f6e32d 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -858,7 +858,7 @@ ArrayOf(Dictionary) nvim_buf_get_keymap(Buffer buffer, String mode, Error *err) /// @see |nvim_set_keymap()| /// /// @param buffer Buffer handle, or 0 for current buffer -void nvim_buf_set_keymap(Buffer buffer, String mode, String lhs, String rhs, Dictionary opts, +void nvim_buf_set_keymap(Buffer buffer, String mode, String lhs, String rhs, Dict(keymap) *opts, Error *err) FUNC_API_SINCE(6) { @@ -874,8 +874,7 @@ void nvim_buf_del_keymap(Buffer buffer, String mode, String lhs, Error *err) FUNC_API_SINCE(6) { String rhs = { .data = "", .size = 0 }; - Dictionary opts = ARRAY_DICT_INIT; - modify_keymap(buffer, true, mode, lhs, rhs, opts, err); + modify_keymap(buffer, true, mode, lhs, rhs, NULL, err); } /// Gets a map of buffer-local |user-commands|. @@ -885,22 +884,13 @@ void nvim_buf_del_keymap(Buffer buffer, String mode, String lhs, Error *err) /// @param[out] err Error details, if any. /// /// @returns Map of maps describing commands. -Dictionary nvim_buf_get_commands(Buffer buffer, Dictionary opts, Error *err) +Dictionary nvim_buf_get_commands(Buffer buffer, Dict(get_commands) *opts, Error *err) FUNC_API_SINCE(4) { bool global = (buffer == -1); - bool builtin = false; - - for (size_t i = 0; i < opts.size; i++) { - String k = opts.items[i].key; - Object v = opts.items[i].value; - if (!strequal("builtin", k.data)) { - api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); - return (Dictionary)ARRAY_DICT_INIT; - } - if (strequal("builtin", k.data)) { - builtin = v.data.boolean; - } + bool builtin = api_object_to_bool(opts->builtin, "builtin", false, err); + if (ERROR_SET(err)) { + return (Dictionary)ARRAY_DICT_INIT; } if (global) { @@ -1485,7 +1475,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e /// @param[out] err Error details, if any /// @return Id of the created/updated extmark Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer col, - Dictionary opts, Error *err) + Dict(set_extmark) *opts, Error *err) FUNC_API_SINCE(7) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -1498,211 +1488,174 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer return 0; } - bool ephemeral = false; uint64_t id = 0; + if (opts->id.type == kObjectTypeInteger && opts->id.data.integer > 0) { + id = (uint64_t)opts->id.data.integer; + } else if (HAS_KEY(opts->id)) { + api_set_error(err, kErrorTypeValidation, "id is not a positive integer"); + goto error; + } + int line2 = -1; - Decoration decor = DECORATION_INIT; + if (opts->end_line.type == kObjectTypeInteger) { + Integer val = opts->end_line.data.integer; + if (val < 0 || val > buf->b_ml.ml_line_count) { + api_set_error(err, kErrorTypeValidation, "end_line value outside range"); + goto error; + } else { + line2 = (int)val; + } + } else if (HAS_KEY(opts->end_line)) { + api_set_error(err, kErrorTypeValidation, "end_line is not an integer"); + goto error; + } + colnr_T col2 = -1; + if (opts->end_col.type == kObjectTypeInteger) { + Integer val = opts->end_col.data.integer; + if (val < 0 || val > MAXCOL) { + api_set_error(err, kErrorTypeValidation, "end_col value outside range"); + goto error; + } else { + col2 = (int)val; + } + } else if (HAS_KEY(opts->end_col)) { + api_set_error(err, kErrorTypeValidation, "end_col is not an integer"); + goto error; + } - bool right_gravity = true; - bool end_right_gravity = false; - bool end_gravity_set = false; + Decoration decor = DECORATION_INIT; - VirtLines virt_lines = KV_INITIAL_VALUE; - bool virt_lines_above = false; - bool virt_lines_leftcol = false; + if (HAS_KEY(opts->hl_group)) { + decor.hl_id = object_to_hl_id(opts->hl_group, "hl_group", err); + if (ERROR_SET(err)) { + goto error; + } + } - for (size_t i = 0; i < opts.size; i++) { - String k = opts.items[i].key; - Object *v = &opts.items[i].value; - if (strequal("id", k.data)) { - if (v->type != kObjectTypeInteger || v->data.integer <= 0) { - api_set_error(err, kErrorTypeValidation, - "id is not a positive integer"); - goto error; - } + if (opts->virt_text.type == kObjectTypeArray) { + decor.virt_text = parse_virt_text(opts->virt_text.data.array, err, + &decor.virt_text_width); + if (ERROR_SET(err)) { + goto error; + } + } else if (HAS_KEY(opts->virt_text)) { + api_set_error(err, kErrorTypeValidation, "virt_text is not an Array"); + goto error; + } + + if (opts->virt_text_pos.type == kObjectTypeString) { + String str = opts->virt_text_pos.data.string; + if (strequal("eol", str.data)) { + decor.virt_text_pos = kVTEndOfLine; + } else if (strequal("overlay", str.data)) { + decor.virt_text_pos = kVTOverlay; + } else if (strequal("right_align", str.data)) { + decor.virt_text_pos = kVTRightAlign; + } else { + api_set_error(err, kErrorTypeValidation, "virt_text_pos: invalid value"); + goto error; + } + } else if (HAS_KEY(opts->virt_text_pos)) { + api_set_error(err, kErrorTypeValidation, "virt_text_pos is not a String"); + goto error; + } - id = (uint64_t)v->data.integer; - } else if (strequal("end_line", k.data)) { - if (v->type != kObjectTypeInteger) { - api_set_error(err, kErrorTypeValidation, - "end_line is not an integer"); - goto error; - } - if (v->data.integer < 0 || v->data.integer > buf->b_ml.ml_line_count) { - api_set_error(err, kErrorTypeValidation, - "end_line value outside range"); - goto error; - } + if (opts->virt_text_win_col.type == kObjectTypeInteger) { + decor.col = (int)opts->virt_text_win_col.data.integer; + decor.virt_text_pos = kVTWinCol; + } else if (HAS_KEY(opts->virt_text_win_col)) { + api_set_error(err, kErrorTypeValidation, + "virt_text_win_col is not a Number of the correct size"); + goto error; + } - line2 = (int)v->data.integer; - } else if (strequal("end_col", k.data)) { - if (v->type != kObjectTypeInteger) { - api_set_error(err, kErrorTypeValidation, - "end_col is not an integer"); - goto error; - } - if (v->data.integer < 0 || v->data.integer > MAXCOL) { - api_set_error(err, kErrorTypeValidation, - "end_col value outside range"); - goto error; - } +#define OPTION_TO_BOOL(target, name, val) \ + target = api_object_to_bool(opts-> name, #name, val, err); \ + if (ERROR_SET(err)) { \ + goto error; \ + } - col2 = (colnr_T)v->data.integer; - } else if (strequal("hl_group", k.data)) { - String hl_group; - switch (v->type) { - case kObjectTypeString: - hl_group = v->data.string; - decor.hl_id = syn_check_group((char_u *)(hl_group.data), - (int)hl_group.size); - break; - case kObjectTypeInteger: - decor.hl_id = (int)v->data.integer; - break; - default: - api_set_error(err, kErrorTypeValidation, - "hl_group is not valid."); - goto error; - } - } else if (strequal("virt_text", k.data)) { - if (v->type != kObjectTypeArray) { - api_set_error(err, kErrorTypeValidation, - "virt_text is not an Array"); - goto error; - } - decor.virt_text = parse_virt_text(v->data.array, err, - &decor.virt_text_width); - if (ERROR_SET(err)) { - goto error; - } - } else if (strequal("virt_text_pos", k.data)) { - if (v->type != kObjectTypeString) { - api_set_error(err, kErrorTypeValidation, - "virt_text_pos is not a String"); - goto error; - } - String str = v->data.string; - if (strequal("eol", str.data)) { - decor.virt_text_pos = kVTEndOfLine; - } else if (strequal("overlay", str.data)) { - decor.virt_text_pos = kVTOverlay; - } else if (strequal("right_align", str.data)) { - decor.virt_text_pos = kVTRightAlign; - } else { - api_set_error(err, kErrorTypeValidation, - "virt_text_pos: invalid value"); - goto error; - } - } else if (strequal("virt_text_win_col", k.data)) { - if (v->type != kObjectTypeInteger) { - api_set_error(err, kErrorTypeValidation, - "virt_text_win_col is not a Number of the correct size"); - goto error; - } + OPTION_TO_BOOL(decor.virt_text_hide, virt_text_hide, false); + OPTION_TO_BOOL(decor.hl_eol, hl_eol, false); + + if (opts->hl_mode.type == kObjectTypeString) { + String str = opts->hl_mode.data.string; + if (strequal("replace", str.data)) { + decor.hl_mode = kHlModeReplace; + } else if (strequal("combine", str.data)) { + decor.hl_mode = kHlModeCombine; + } else if (strequal("blend", str.data)) { + decor.hl_mode = kHlModeBlend; + } else { + api_set_error(err, kErrorTypeValidation, + "virt_text_pos: invalid value"); + goto error; + } + } else if (HAS_KEY(opts->hl_mode)) { + api_set_error(err, kErrorTypeValidation, "hl_mode is not a String"); + goto error; + } - decor.col = (int)v->data.integer; - decor.virt_text_pos = kVTWinCol; - } else if (strequal("virt_text_hide", k.data)) { - decor.virt_text_hide = api_object_to_bool(*v, - "virt_text_hide", false, err); - if (ERROR_SET(err)) { - goto error; - } - } else if (strequal("virt_lines", k.data)) { - if (v->type != kObjectTypeArray) { - api_set_error(err, kErrorTypeValidation, - "virt_lines is not an Array"); - goto error; - } - Array a = v->data.array; - for (size_t j = 0; j < a.size; j++) { - if (a.items[j].type != kObjectTypeArray) { - api_set_error(err, kErrorTypeValidation, - "virt_text_line item is not an Array"); - goto error; - } - int dummig; - VirtText jtem = parse_virt_text(a.items[j].data.array, err, &dummig); - kv_push(virt_lines, jtem); - if (ERROR_SET(err)) { - goto error; - } - } - } else if (strequal("virt_lines_above", k.data)) { - virt_lines_above = api_object_to_bool(*v, "virt_lines_above", false, err); - if (ERROR_SET(err)) { - goto error; - } - } else if (strequal("virt_lines_leftcol", k.data)) { - virt_lines_leftcol = api_object_to_bool(*v, "virt_lines_leftcol", false, err); - if (ERROR_SET(err)) { - goto error; - } - } else if (strequal("hl_eol", k.data)) { - decor.hl_eol = api_object_to_bool(*v, "hl_eol", false, err); - if (ERROR_SET(err)) { - goto error; - } - } else if (strequal("hl_mode", k.data)) { - if (v->type != kObjectTypeString) { - api_set_error(err, kErrorTypeValidation, - "hl_mode is not a String"); - goto error; - } - String str = v->data.string; - if (strequal("replace", str.data)) { - decor.hl_mode = kHlModeReplace; - } else if (strequal("combine", str.data)) { - decor.hl_mode = kHlModeCombine; - } else if (strequal("blend", str.data)) { - decor.hl_mode = kHlModeBlend; - } else { - api_set_error(err, kErrorTypeValidation, - "virt_text_pos: invalid value"); + VirtLines virt_lines = KV_INITIAL_VALUE; + bool virt_lines_above = false; + bool virt_lines_leftcol = false; + + if (opts->virt_lines.type == kObjectTypeArray) { + Array a = opts->virt_lines.data.array; + for (size_t j = 0; j < a.size; j++) { + if (a.items[j].type != kObjectTypeArray) { + api_set_error(err, kErrorTypeValidation, "virt_text_line item is not an Array"); goto error; } - } else if (strequal("ephemeral", k.data)) { - ephemeral = api_object_to_bool(*v, "ephemeral", false, err); + int dummig; + VirtText jtem = parse_virt_text(a.items[j].data.array, err, &dummig); + kv_push(virt_lines, jtem); if (ERROR_SET(err)) { goto error; } - } else if (strequal("priority", k.data)) { - if (v->type != kObjectTypeInteger) { - api_set_error(err, kErrorTypeValidation, - "priority is not a Number of the correct size"); - goto error; - } + } + } else if (HAS_KEY(opts->virt_lines)) { + api_set_error(err, kErrorTypeValidation, "virt_lines is not an Array"); + goto error; + } - if (v->data.integer < 0 || v->data.integer > UINT16_MAX) { - api_set_error(err, kErrorTypeValidation, - "priority is not a valid value"); - goto error; - } - decor.priority = (DecorPriority)v->data.integer; - } else if (strequal("right_gravity", k.data)) { - if (v->type != kObjectTypeBoolean) { - api_set_error(err, kErrorTypeValidation, - "right_gravity must be a boolean"); - goto error; - } - right_gravity = v->data.boolean; - } else if (strequal("end_right_gravity", k.data)) { - if (v->type != kObjectTypeBoolean) { - api_set_error(err, kErrorTypeValidation, - "end_right_gravity must be a boolean"); - goto error; - } - end_right_gravity = v->data.boolean; - end_gravity_set = true; - } else { - api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); + OPTION_TO_BOOL(virt_lines_above, virt_lines_above, false); + OPTION_TO_BOOL(virt_lines_leftcol, virt_lines_leftcol, false); + + if (opts->priority.type == kObjectTypeInteger) { + Integer val = opts->priority.data.integer; + + if (val < 0 || val > UINT16_MAX) { + api_set_error(err, kErrorTypeValidation, "priority is not a valid value"); goto error; } + decor.priority = (DecorPriority)val; + } else if (HAS_KEY(opts->priority)) { + api_set_error(err, kErrorTypeValidation, "priority is not a Number of the correct size"); + goto error; } + bool right_gravity = true; + OPTION_TO_BOOL(right_gravity, right_gravity, true); + + // Only error out if they try to set end_right_gravity without + // setting end_col or end_line + if (line2 == -1 && col2 == -1 && HAS_KEY(opts->end_right_gravity)) { + api_set_error(err, kErrorTypeValidation, + "cannot set end_right_gravity without setting end_line or end_col"); + goto error; + } + + bool end_right_gravity = false; + OPTION_TO_BOOL(end_right_gravity, end_right_gravity, false); + size_t len = 0; + + bool ephemeral = false; + OPTION_TO_BOOL(ephemeral, ephemeral, false); + if (line < 0 || line > buf->b_ml.ml_line_count) { api_set_error(err, kErrorTypeValidation, "line value outside range"); return 0; @@ -1717,15 +1670,6 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer return 0; } - - // Only error out if they try to set end_right_gravity without - // setting end_col or end_line - if (line2 == -1 && col2 == -1 && end_gravity_set) { - api_set_error(err, kErrorTypeValidation, - "cannot set end_right_gravity " - "without setting end_line or end_col"); - } - if (col2 >= 0) { if (line2 >= 0 && line2 < buf->b_ml.ml_line_count) { len = ephemeral ? MAXCOL : STRLEN(ml_get_buf(buf, (linenr_T)line2 + 1, false)); @@ -1744,15 +1688,6 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer col2 = 0; } - if (decor.virt_text_pos == kVTRightAlign) { - decor.col = 0; - for (size_t i = 0; i < kv_size(decor.virt_text); i++) { - decor.col - += (int)mb_string2cells((char_u *)kv_A(decor.virt_text, i).text); - } - } - - Decoration *d = NULL; if (ephemeral) { |