diff options
| author | Björn Linse <bjorn.linse@gmail.com> | 2021-10-03 14:31:53 +0200 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-10-03 14:31:53 +0200 | 
| commit | 3beea1fe1bca5b0cf3f724ab0d06a01a04652297 (patch) | |
| tree | d4049608bcde6e4ff18bcc9aa300832063a1930d /src/nvim/api/buffer.c | |
| parent | 9fe704f88e455f886c8854604b2869c72b28e510 (diff) | |
| parent | 32565922efe0d1a6e8e4dddb23295d1a08670b54 (diff) | |
| download | rneovim-3beea1fe1bca5b0cf3f724ab0d06a01a04652297.tar.gz rneovim-3beea1fe1bca5b0cf3f724ab0d06a01a04652297.tar.bz2 rneovim-3beea1fe1bca5b0cf3f724ab0d06a01a04652297.zip  | |
Merge pull request #15516 from bfredl/keyset
refactor(api): Represent option dicts as a structs in C and reduce conversion overhead from lua
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) {  | 
