This patch doesn't appear to have made it to github; the version number updated but the rest of the patch is MIA.
On Sat, Aug 20, 2022 at 1:55 PM Bram Moolenaar <[email protected]> wrote: > > Patch 9.0.0233 > Problem: Removing multiple text properties takes many calls. > Solution: Pass a list to prop_remove(). (Ben Jackson, closes #10945) > Files: runtime/doc/textprop.txt, src/textprop.c, src/errors.h, > src/testdir/test_textprop.vim > > > *** ../vim-9.0.0232/runtime/doc/textprop.txt 2022-08-05 > 17:04:43.402914763 +0100 > --- runtime/doc/textprop.txt 2022-08-20 20:54:00.459011754 +0100 > *************** > *** 143,154 **** > zero is used > text text to be displayed before {col}, or > after the > line if {col} is zero > text_align when "text" is present and {col} is zero > specifies where to display the text: > after after the end of the line > ! right right aligned in the window > below in the next screen line > ! When omitted "after" is used. > text_wrap when "text" is present and {col} is zero, > specifies what happens if the text doesn't > fit: > --- 143,158 ---- > zero is used > text text to be displayed before {col}, or > after the > line if {col} is zero > + *E1294* > text_align when "text" is present and {col} is zero > specifies where to display the text: > after after the end of the line > ! right right aligned in the window > (unless > ! the text wraps to the next > screen > ! line) > below in the next screen line > ! When omitted "after" is used. Only one > ! "right" property can fit in earch line. > text_wrap when "text" is present and {col} is zero, > specifies what happens if the text doesn't > fit: > *************** > *** 186,194 **** > buffer line, the cursor cannot be placed on it. A mouse > click > in the text will move the cursor to the first character > after > the text, or the last character of the line. > A negative "id" will be chosen and is returned. Once a > - Any Tab in the text will be changed to a space (Rationale: > - otherwise the size of the text is difficult to compute). > property with "text" has been added for a buffer then > using a > negative "id" for any other property will give an error: > *E1293* > --- 190,199 ---- > buffer line, the cursor cannot be placed on it. A mouse > click > in the text will move the cursor to the first character > after > the text, or the last character of the line. > + Any Tab and other control character in the text will be > + changed to a space (Rationale: otherwise the size of the > text > + is difficult to compute). > A negative "id" will be chosen and is returned. Once a > property with "text" has been added for a buffer then > using a > negative "id" for any other property will give an error: > *E1293* > *************** > *** 347,357 **** > {props} is a dictionary with these fields: > id remove text properties with this ID > type remove text properties with this type name > ! both "id" and "type" must both match > bufnr use this buffer instead of the current one > all when TRUE remove all matching text > properties, > not just the first one > ! A property matches when either "id" or "type" matches. > If buffer "bufnr" does not exist you get an error message. > If buffer "bufnr" is not loaded then nothing happens. > > --- 352,367 ---- > {props} is a dictionary with these fields: > id remove text properties with this ID > type remove text properties with this type name > ! types remove text properties with type names in > this > ! List > ! both "id" and "type"/"types" must both match > bufnr use this buffer instead of the current one > all when TRUE remove all matching text > properties, > not just the first one > ! Only one of "type" and "types" may be supplied. *E1295* > ! > ! A property matches when either "id" or one of the supplied > ! types matches. > If buffer "bufnr" does not exist you get an error message. > If buffer "bufnr" is not loaded then nothing happens. > > *** ../vim-9.0.0232/src/textprop.c 2022-08-15 15:54:45.710375583 +0100 > --- src/textprop.c 2022-08-20 20:47:49.903395746 +0100 > *************** > *** 1010,1016 **** > } > if (both && (!id_found || type_id == -1)) > { > ! emsg(_(e_need_id_and_type_with_both)); > return; > } > > --- 1010,1016 ---- > } > if (both && (!id_found || type_id == -1)) > { > ! emsg(_(e_need_id_and_type_or_types_with_both)); > return; > } > > *************** > *** 1378,1384 **** > buf_T *buf = curbuf; > int do_all; > int id = -MAXCOL; > ! int type_id = -1; > int both; > int did_remove_text = FALSE; > > --- 1378,1386 ---- > buf_T *buf = curbuf; > int do_all; > int id = -MAXCOL; > ! 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,1425 **** > --- 1422,1430 ---- > > 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,1445 **** > return; > type_id = type->pt_id; > } > both = dict_get_bool(dict, "both", FALSE); > > ! if (id == -MAXCOL && type_id == -1) > { > emsg(_(e_need_at_least_one_of_id_or_type)); > ! return; > } > ! if (both && (id == -MAXCOL || type_id == -1)) > { > ! emsg(_(e_need_id_and_type_with_both)); > ! return; > } > > if (end == 0) > --- 1434,1481 ---- > 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 && num_type_ids == 0)) > { > emsg(_(e_need_at_least_one_of_id_or_type)); > ! goto cleanup_prop_remove; > } > ! if (both && (id == -MAXCOL || (type_id == -1 && num_type_ids == 0))) > { > ! 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,1473 **** > char_u *cur_prop = buf->b_ml.ml_line_ptr + len > + idx * > sizeof(textprop_T); > size_t taillen; > > 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) > { > if (!(buf->b_ml.ml_flags & ML_LINE_DIRTY)) > { > --- 1500,1525 ---- > 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)); > ! > ! 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,1481 **** > > // need to allocate the line to be able to change > it > if (newptr == NULL) > ! return; > mch_memmove(newptr, buf->b_ml.ml_line_ptr, > > buf->b_ml.ml_line_len); > if (buf->b_ml.ml_flags & ML_ALLOCATED) > --- 1527,1533 ---- > > // need to allocate the line to be able to change > it > if (newptr == NULL) > ! 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,1542 **** > --- 1589,1597 ---- > && ((char_u **)gap->ga_data)[gap->ga_len - 1] == > NULL) > --gap->ga_len; > } > + > + cleanup_prop_remove: > + vim_free(type_ids); > } > > /* > *** ../vim-9.0.0232/src/errors.h 2022-08-20 12:07:55.098022792 +0100 > --- src/errors.h 2022-08-20 20:40:30.507911267 +0100 > *************** > *** 2208,2215 **** > INIT(= N_("E859: Failed to convert returned python object to a Vim > value")); > #endif > #ifdef FEAT_PROP_POPUP > ! EXTERN char e_need_id_and_type_with_both[] > ! INIT(= N_("E860: Need 'id' and 'type' with 'both'")); > # ifdef FEAT_TERMINAL > EXTERN char e_cannot_open_second_popup_with_terminal[] > INIT(= N_("E861: Cannot open a second popup with a terminal")); > --- 2208,2215 ---- > INIT(= N_("E859: Failed to convert returned python object to a Vim > value")); > #endif > #ifdef FEAT_PROP_POPUP > ! EXTERN char e_need_id_and_type_or_types_with_both[] > ! INIT(= N_("E860: Need 'id' and 'type' or 'types' with 'both'")); > # ifdef FEAT_TERMINAL > EXTERN char e_cannot_open_second_popup_with_terminal[] > INIT(= N_("E861: Cannot open a second popup with a terminal")); > *************** > *** 3316,3318 **** > --- 3316,3322 ---- > EXTERN char e_can_only_use_text_align_when_column_is_zero[] > INIT(= N_("E1294: Can only use text_align when column is zero")); > #endif > + #ifdef FEAT_PROP_POPUP > + EXTERN char e_cannot_specify_both_type_and_types[] > + INIT(= N_("E1295: Cannot specify both 'type' and 'types'")); > + #endif > *** ../vim-9.0.0232/src/testdir/test_textprop.vim 2022-08-15 > 15:54:45.710375583 +0100 > --- src/testdir/test_textprop.vim 2022-08-20 20:44:18.895631843 +0100 > *************** > *** 161,167 **** > \ ] > > " Starting at line 5 col 1 this should find the prop at line 5 col 4. > ! call cursor(5,1) > let result = prop_find({'type': 'prop_name'}, 'f') > call assert_equal(expected[2], result) > > --- 161,167 ---- > \ ] > > " Starting at line 5 col 1 this should find the prop at line 5 col 4. > ! call cursor(5, 1) > let result = prop_find({'type': 'prop_name'}, 'f') > call assert_equal(expected[2], result) > > *************** > *** 182,188 **** > " with skipstart set to false, if the start position is anywhere > between the > " start and end lines of a text prop (searching forward or backward), > the > " result should be the prop on the first line (the line with 'start' > set to 1). > ! call cursor(3,1) > let result = prop_find({'type': 'prop_name'}, 'f') > unlet result.length > call assert_equal(expected[1], result) > --- 182,188 ---- > " with skipstart set to false, if the start position is anywhere > between the > " start and end lines of a text prop (searching forward or backward), > the > " result should be the prop on the first line (the line with 'start' > set to 1). > ! call cursor(3, 1) > let result = prop_find({'type': 'prop_name'}, 'f') > unlet result.length > call assert_equal(expected[1], result) > *************** > *** 230,241 **** > endwhile > > " Starting from line 6 col 1 search backwards for prop with id 10. > ! call cursor(6,1) > let result = prop_find({'id': 10, 'skipstart': 1}, 'b') > call assert_equal(expected[0], result) > > " Starting from line 1 col 1 search forwards for prop with id 12. > ! call cursor(1,1) > let result = prop_find({'id': 12}, 'f') > call assert_equal(expected[2], result) > > --- 230,241 ---- > endwhile > > " Starting from line 6 col 1 search backwards for prop with id 10. > ! call cursor(6, 1) > let result = prop_find({'id': 10, 'skipstart': 1}, 'b') > call assert_equal(expected[0], result) > > " Starting from line 1 col 1 search forwards for prop with id 12. > ! call cursor(1, 1) > let result = prop_find({'id': 12}, 'f') > call assert_equal(expected[2], result) > > *************** > *** 426,431 **** > --- 426,462 ---- > > call DeletePropTypes() > bwipe! > + > + new > + call AddPropTypes() > + call SetupPropsInFirstLine() > + let props = Get_expected_props() " [whole, one, two, three] > + call assert_equal(props, prop_list(1)) > + > + " remove one by types > + call assert_equal(1, prop_remove({'types': ['one', 'two', 'three']}, > 1)) > + unlet props[1] " [whole, two, three] > + call assert_equal(props, prop_list(1)) > + > + " remove 'all' by types > + call assert_equal(2, prop_remove({'types': ['three', 'whole'], 'all': > 1}, 1)) > + unlet props[0] " [two, three] > + unlet props[1] " [three] > + call assert_equal(props, prop_list(1)) > + > + " remove none by types > + call assert_equal(0, prop_remove({'types': ['three', 'whole'], 'all': > 1}, 1)) > + call assert_equal(props, prop_list(1)) > + > + " no types > + call assert_fails("call prop_remove({'types': []}, 1)", 'E968:') > + call assert_fails("call prop_remove({'types': ['not_a_real_type']}, > 1)", 'E971:') > + > + " only one of types and type can be supplied > + call assert_fails("call prop_remove({'type': 'one', 'types': > ['three'], 'all': 1}, 1)", 'E1295:') > + > + call DeletePropTypes() > + bwipe! > endfunc > > def Test_prop_add_vim9() > *************** > *** 1396,1402 **** > func Test_textprop_invalid_highlight() > call assert_fails("call prop_type_add('dni', {'highlight': > 'DoesNotExist'})", 'E970:') > new > ! call setline(1, ['asdf','asdf']) > call prop_add(1, 1, {'length': 4, 'type': 'dni'}) > redraw > bwipe! > --- 1427,1433 ---- > func Test_textprop_invalid_highlight() > call assert_fails("call prop_type_add('dni', {'highlight': > 'DoesNotExist'})", 'E970:') > new > ! call setline(1, ['asdf', 'asdf']) > call prop_add(1, 1, {'length': 4, 'type': 'dni'}) > redraw > bwipe! > *************** > *** 2207,2213 **** > call prop_add(1, col, #{type: 'misspell', length: 2}) > endfor > > ! call cursor(1,18) > let expected = [ > \ #{lnum: 1, id: 0, col: 14, end: 1, type: 'misspell', type_bufnr: > 0, length: 2, start: 1}, > \ #{lnum: 1, id: 0, col: 24, end: 1, type: 'misspell', type_bufnr: > 0, length: 2, start: 1} > --- 2238,2244 ---- > call prop_add(1, col, #{type: 'misspell', length: 2}) > endfor > > ! call cursor(1, 18) > let expected = [ > \ #{lnum: 1, id: 0, col: 14, end: 1, type: 'misspell', type_bufnr: > 0, length: 2, start: 1}, > \ #{lnum: 1, id: 0, col: 24, end: 1, type: 'misspell', type_bufnr: > 0, length: 2, start: 1} > *************** > *** 2310,2316 **** > call assert_equal(lines, getline(1, '$')) > let expected = [ > \ {'lnum': 1, 'id': 0, 'col': 4, 'type_bufnr': 0, 'end': 0, > 'type': 'one', > ! \ 'length': 4 ,'start': 1}, > \ {'lnum': 2, 'id': 0, 'col': 1, 'type_bufnr': 0, 'end': 0, > 'type': 'one', > \ 'length': 7, 'start': 0}, > \ {'lnum': 3, 'id': 0, 'col': 1, 'type_bufnr': 0, 'end': 0, > 'type': 'one', > --- 2341,2347 ---- > call assert_equal(lines, getline(1, '$')) > let expected = [ > \ {'lnum': 1, 'id': 0, 'col': 4, 'type_bufnr': 0, 'end': 0, > 'type': 'one', > ! \ 'length': 4 , 'start': 1}, > \ {'lnum': 2, 'id': 0, 'col': 1, 'type_bufnr': 0, 'end': 0, > 'type': 'one', > \ 'length': 7, 'start': 0}, > \ {'lnum': 3, 'id': 0, 'col': 1, 'type_bufnr': 0, 'end': 0, > 'type': 'one', > *** ../vim-9.0.0232/src/version.c 2022-08-20 20:09:10.598693210 +0100 > --- src/version.c 2022-08-20 20:38:36.820063346 +0100 > *************** > *** 733,734 **** > --- 733,736 ---- > { /* Add new patch number below this line */ > + /**/ > + 233, > /**/ > > -- > Be nice to your kids... they'll be the ones choosing your nursing home. > > /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net > \\\ > /// > \\\ > \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ > /// > \\\ help me help AIDS victims -- http://ICCF-Holland.org > /// > > -- > -- > You received this message from the "vim_dev" maillist. > Do not top-post! Type your reply below the text you are replying to. > For more information, visit http://www.vim.org/maillist.php > > --- > You received this message because you are subscribed to the Google Groups > "vim_dev" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To view this discussion on the web visit > https://groups.google.com/d/msgid/vim_dev/20220820195527.7E2261C0ADA%40moolenaar.net > . > -- Christian J. Robinson <[email protected]> -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/vim_dev/CAK14FZJ%3DDAkeYhrgNZpYd_ai%3DY65a%2BTbBV1W5rPFrfShXUooHA%40mail.gmail.com.
