diff options
author | Ben Jackson <puremourning@gmail.com> | 2022-08-20 20:54:51 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2022-08-20 20:54:51 +0100 |
commit | a7704226a26b95b15bf87d3a3a5128e23e4aaa06 (patch) | |
tree | c0f1d18d5e6afd512a9f5dbeb1e5b0e1d9837f07 /src/textprop.c | |
parent | 38ea5bda2b699d91e339fb116d96e3a4f2e69c89 (diff) |
patch 9.0.0233: removing multiple text properties takes many callsv9.0.0233
Problem: Removing multiple text properties takes many calls.
Solution: Pass a list to prop_remove(). (Ben Jackson, closes #10945)
Diffstat (limited to 'src/textprop.c')
-rw-r--r-- | src/textprop.c | 75 |
1 files changed, 65 insertions, 10 deletions
diff --git a/src/textprop.c b/src/textprop.c index d90d57fac3..2fb8a53122 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -1010,7 +1010,7 @@ f_prop_find(typval_T *argvars, typval_T *rettv) } if (both && (!id_found || type_id == -1)) { - emsg(_(e_need_id_and_type_with_both)); + emsg(_(e_need_id_and_type_or_types_with_both)); return; } @@ -1378,7 +1378,9 @@ f_prop_remove(typval_T *argvars, typval_T *rettv) buf_T *buf = curbuf; int do_all; int id = -MAXCOL; - int type_id = -1; + int type_id = -1; // for a single "type" + int *type_ids = NULL; // array, for a list of "types", allocated + int num_type_ids = 0; // number of elements in "type_ids" int both; int did_remove_text = FALSE; @@ -1420,6 +1422,9 @@ f_prop_remove(typval_T *argvars, typval_T *rettv) if (dict_has_key(dict, "id")) id = dict_get_number(dict, "id"); + + // if a specific type was supplied "type": check that (and ignore "types". + // Otherwise check against the list of "types". if (dict_has_key(dict, "type")) { char_u *name = dict_get_string(dict, "type", FALSE); @@ -1429,17 +1434,48 @@ f_prop_remove(typval_T *argvars, typval_T *rettv) return; type_id = type->pt_id; } + if (dict_has_key(dict, "types")) + { + typval_T types; + listitem_T *li = NULL; + + dict_get_tv(dict, "types", &types); + if (types.v_type == VAR_LIST && types.vval.v_list->lv_len > 0) + { + type_ids = alloc( sizeof(int) * types.vval.v_list->lv_len ); + + FOR_ALL_LIST_ITEMS(types.vval.v_list, li) + { + proptype_T *prop_type; + + if (li->li_tv.v_type != VAR_STRING) + continue; + + prop_type = lookup_prop_type(li->li_tv.vval.v_string, buf); + + if (!prop_type) + goto cleanup_prop_remove; + + type_ids[num_type_ids++] = prop_type->pt_id; + } + } + } both = dict_get_bool(dict, "both", FALSE); - if (id == -MAXCOL && type_id == -1) + if (id == -MAXCOL && (type_id == -1 && num_type_ids == 0)) { emsg(_(e_need_at_least_one_of_id_or_type)); - return; + goto cleanup_prop_remove; } - if (both && (id == -MAXCOL || type_id == -1)) + if (both && (id == -MAXCOL || (type_id == -1 && num_type_ids == 0))) { - emsg(_(e_need_id_and_type_with_both)); - return; + emsg(_(e_need_id_and_type_or_types_with_both)); + goto cleanup_prop_remove; + } + if (type_id != -1 && num_type_ids > 0) + { + emsg(_(e_cannot_specify_both_type_and_types)); + goto cleanup_prop_remove; } if (end == 0) @@ -1464,10 +1500,26 @@ f_prop_remove(typval_T *argvars, typval_T *rettv) char_u *cur_prop = buf->b_ml.ml_line_ptr + len + idx * sizeof(textprop_T); size_t taillen; + int matches_id = 0; + int matches_type = 0; mch_memmove(&textprop, cur_prop, sizeof(textprop_T)); - if (both ? textprop.tp_id == id && textprop.tp_type == type_id - : textprop.tp_id == id || textprop.tp_type == type_id) + + matches_id = textprop.tp_id == id; + if (num_type_ids > 0) + { + int idx2; + + for (idx2 = 0; !matches_type && idx2 < num_type_ids; ++idx2) + matches_type = textprop.tp_type == type_ids[idx2]; + } + else + { + matches_type = textprop.tp_type == type_id; + } + + if (both ? matches_id && matches_type + : matches_id || matches_type) { if (!(buf->b_ml.ml_flags & ML_LINE_DIRTY)) { @@ -1475,7 +1527,7 @@ f_prop_remove(typval_T *argvars, typval_T *rettv) // need to allocate the line to be able to change it if (newptr == NULL) - return; + goto cleanup_prop_remove; mch_memmove(newptr, buf->b_ml.ml_line_ptr, buf->b_ml.ml_line_len); if (buf->b_ml.ml_flags & ML_ALLOCATED) @@ -1537,6 +1589,9 @@ f_prop_remove(typval_T *argvars, typval_T *rettv) && ((char_u **)gap->ga_data)[gap->ga_len - 1] == NULL) --gap->ga_len; } + +cleanup_prop_remove: + vim_free(type_ids); } /* |