aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/buffer.c
diff options
context:
space:
mode:
authorBjörn Linse <bjorn.linse@gmail.com>2021-08-21 13:55:12 +0200
committerBjörn Linse <bjorn.linse@gmail.com>2021-10-03 10:46:57 +0200
commit32565922efe0d1a6e8e4dddb23295d1a08670b54 (patch)
tree501dd50b3ae199e3b52071d66d307e9d69772f82 /src/nvim/api/buffer.c
parent9337fff8aad610acd5ef619f757686c47f0c118c (diff)
downloadrneovim-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.c371
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) {