# HG changeset patch # User Bram Moolenaar # Date 1670014804 -3600 # Node ID 243c35fad9cbc0fba0518c65b8f2a2268419f1eb # Parent 23d42fb4e93869772cc19e040cc667143542c3c6 patch 9.0.0993: display errors when adding or removing text property type Commit: https://github.com/vim/vim/commit/89469d157aea01513bde826b4519dd6b5fbceae4 Author: Bram Moolenaar Date: Fri Dec 2 20:46:26 2022 +0000 patch 9.0.0993: display errors when adding or removing text property type Problem: Display errors when adding or removing text property type. Solution: Perform a full redraw. Only use text properties for which the type is defined. (closes #11655) diff --git a/src/charset.c b/src/charset.c --- a/src/charset.c +++ b/src/charset.c @@ -986,11 +986,15 @@ init_chartabsize_arg( mch_memmove(cts->cts_text_props + count, prop_start, count * sizeof(textprop_T)); for (i = 0; i < count; ++i) - if (cts->cts_text_props[i + count].tp_id < 0) + { + textprop_T *tp = cts->cts_text_props + i + count; + if (tp->tp_id < 0 + && text_prop_type_valid(wp->w_buffer, tp)) { cts->cts_has_prop_with_text = TRUE; break; } + } if (!cts->cts_has_prop_with_text) { // won't use the text properties, free them diff --git a/src/move.c b/src/move.c --- a/src/move.c +++ b/src/move.c @@ -646,6 +646,20 @@ changed_window_setting_win(win_T *wp) } /* + * Call changed_window_setting_win() for every window containing "buf". + */ + void +changed_window_setting_buf(buf_T *buf) +{ + tabpage_T *tp; + win_T *wp; + + FOR_ALL_TAB_WINDOWS(tp, wp) + if (wp->w_buffer == buf) + changed_window_setting_win(wp); +} + +/* * Set wp->w_topline to a certain number. */ void diff --git a/src/proto/move.pro b/src/proto/move.pro --- a/src/proto/move.pro +++ b/src/proto/move.pro @@ -7,6 +7,7 @@ void update_curswant(void); void check_cursor_moved(win_T *wp); void changed_window_setting(void); void changed_window_setting_win(win_T *wp); +void changed_window_setting_buf(buf_T *buf); void set_topline(win_T *wp, linenr_T lnum); void changed_cline_bef_curs(void); void changed_cline_bef_curs_win(win_T *wp); diff --git a/src/proto/textprop.pro b/src/proto/textprop.pro --- a/src/proto/textprop.pro +++ b/src/proto/textprop.pro @@ -10,6 +10,7 @@ void sort_text_props(buf_T *buf, textpro int find_visible_prop(win_T *wp, int type_id, int id, textprop_T *prop, linenr_T *found_lnum); void add_text_props(linenr_T lnum, textprop_T *text_props, int text_prop_count); proptype_T *text_prop_type_by_id(buf_T *buf, int id); +int text_prop_type_valid(buf_T *buf, textprop_T *prop); void f_prop_clear(typval_T *argvars, typval_T *rettv); void f_prop_find(typval_T *argvars, typval_T *rettv); void f_prop_list(typval_T *argvars, typval_T *rettv); diff --git a/src/testdir/dumps/Test_prop_delete_updates_1.dump b/src/testdir/dumps/Test_prop_delete_updates_1.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_delete_updates_1.dump @@ -0,0 +1,10 @@ +|s+0&#ffffff0|o|m|e| |t|e|x|t| @50 +@3|T+0&#ffd7ff255|h|e| |q|u|i|c|k| |b|r|o|w|n| |f|o|x| |j|u|m|p|s| |o|v|e|r| |t|h|e| |l|a|z|y| |d|o|g| +0&#ffffff0@13 +@5|T+0&#ffd7ff255|h|e| |q|u|i|c|k| |b|r|o|w|n| |f|o|x| |j|u|m|p|s| |o|v|e|r| |t|h|e| |l|a|z|y| |d|o|g| +0&#ffffff0@11 +|m|o|r|e| |t|e|x|t| @50 +>t|h|e| |e|n|d| @52 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|~| @58 +| +0#0000000&@41|3|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_prop_delete_updates_2.dump b/src/testdir/dumps/Test_prop_delete_updates_2.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_delete_updates_2.dump @@ -0,0 +1,10 @@ +|s+0&#ffffff0|o|m|e| |t|e|x|t| @50 +|m|o|r|e| |t|e|x|t| @50 +>t|h|e| |e|n|d| @52 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|~| @58 +|~| @58 +|~| @58 +| +0#0000000&@41|3|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_prop_delete_updates_3.dump b/src/testdir/dumps/Test_prop_delete_updates_3.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_delete_updates_3.dump @@ -0,0 +1,10 @@ +|s+0&#ffffff0|o|m|e| |t|e|x|t| @50 +>m|o|r|e| |t|e|x|t| @50 +|t|h|e| |e|n|d| @52 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|~| @58 +|~| @58 +|~| @58 +| +0#0000000&@41|2|,|1| @10|A|l@1| diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim --- a/src/testdir/test_textprop.vim +++ b/src/testdir/test_textprop.vim @@ -1700,7 +1700,7 @@ func Test_prop_func_invalid_args() call assert_fails("call prop_type_delete([])", 'E730:') call assert_fails("call prop_type_delete('xyz', [])", 'E715:') call assert_fails("call prop_type_get([])", 'E730:') - call assert_fails("call prop_type_get('', [])", 'E474:') + call assert_fails("call prop_type_get('', [])", 'E475:') call assert_fails("call prop_type_list([])", 'E715:') call assert_fails("call prop_type_add('yyy', 'not_a_dict')", 'E715:') call assert_fails("call prop_add(1, 5, {'type':'missing_type', 'length':1})", 'E971:') @@ -3627,5 +3627,43 @@ def Test_textprop_in_quickfix_window() bwipe! enddef +func Test_text_prop_delete_updates() + CheckRunVimInTerminal + + let lines =<< trim END + vim9script + + setline(1, ['some text', 'more text', 'the end']) + prop_type_add('test', {highlight: 'DiffChange'}) + prop_add(1, 0, { + type: 'test', + text: 'The quick brown fox jumps over the lazy dog', + text_align: 'below', + text_padding_left: 3, + }) + prop_add(1, 0, { + type: 'test', + text: 'The quick brown fox jumps over the lazy dog', + text_align: 'below', + text_padding_left: 5, + }) + + normal! G + END + call writefile(lines, 'XtextPropDelete', 'D') + let buf = RunVimInTerminal('-S XtextPropDelete', #{rows: 10, cols: 60}) + call VerifyScreenDump(buf, 'Test_prop_delete_updates_1', {}) + + " Check that after deleting the text prop type the text properties using + " this type no longer show and are not counted for cursor positioning. + call term_sendkeys(buf, ":call prop_type_delete('test')\") + call VerifyScreenDump(buf, 'Test_prop_delete_updates_2', {}) + + call term_sendkeys(buf, "ggj") + call VerifyScreenDump(buf, 'Test_prop_delete_updates_3', {}) + + call StopVimInTerminal(buf) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -3158,13 +3158,13 @@ enddef def Test_prop_type_add() v9.CheckDefAndScriptFailure(['prop_type_add({"a": 10}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict', 'E1174: String required for argument 1']) v9.CheckDefAndScriptFailure(['prop_type_add("a", "b")'], ['E1013: Argument 2: type mismatch, expected dict but got string', 'E1206: Dictionary required for argument 2']) - assert_fails("prop_type_add('', {highlight: 'Search'})", 'E474:') + assert_fails("prop_type_add('', {highlight: 'Search'})", 'E475:') enddef def Test_prop_type_change() v9.CheckDefAndScriptFailure(['prop_type_change({"a": 10}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict', 'E1174: String required for argument 1']) v9.CheckDefAndScriptFailure(['prop_type_change("a", "b")'], ['E1013: Argument 2: type mismatch, expected dict but got string', 'E1206: Dictionary required for argument 2']) - assert_fails("prop_type_change('', {highlight: 'Search'})", 'E474:') + assert_fails("prop_type_change('', {highlight: 'Search'})", 'E475:') enddef def Test_prop_type_delete() diff --git a/src/textprop.c b/src/textprop.c --- a/src/textprop.c +++ b/src/textprop.c @@ -653,7 +653,7 @@ prop_count_above_below(buf_T *buf, linen for (i = 0; i < count; ++i) { mch_memmove(&prop, props + i * sizeof(prop), sizeof(prop)); - if (prop.tp_col == MAXCOL) + if (prop.tp_col == MAXCOL && text_prop_type_valid(buf, &prop)) { if ((prop.tp_flags & TP_FLAG_ALIGN_BELOW) || (next_right_goes_below @@ -697,7 +697,8 @@ count_props(linenr_T lnum, int only_star // previous line, or when not in the last line and it is virtual text // after the line. if ((only_starting && (prop.tp_flags & TP_FLAG_CONT_PREV)) - || (!last_line && prop.tp_col == MAXCOL)) + || (!last_line && prop.tp_col == MAXCOL) + || !text_prop_type_valid(curbuf, &prop)) --result; } return result; @@ -801,20 +802,24 @@ sort_text_props( * Returns FAIL when not found. */ int -find_visible_prop(win_T *wp, int type_id, int id, textprop_T *prop, - linenr_T *found_lnum) +find_visible_prop( + win_T *wp, + int type_id, + int id, + textprop_T *prop, + linenr_T *found_lnum) { - linenr_T lnum; - char_u *props; - int count; - int i; + // return when "type_id" no longer exists + if (text_prop_type_by_id(wp->w_buffer, type_id) == NULL) + return FAIL; // w_botline may not have been updated yet. validate_botline_win(wp); - for (lnum = wp->w_topline; lnum < wp->w_botline; ++lnum) + for (linenr_T lnum = wp->w_topline; lnum < wp->w_botline; ++lnum) { - count = get_text_props(wp->w_buffer, lnum, &props, FALSE); - for (i = 0; i < count; ++i) + char_u *props; + int count = get_text_props(wp->w_buffer, lnum, &props, FALSE); + for (int i = 0; i < count; ++i) { mch_memmove(prop, props + i * sizeof(textprop_T), sizeof(textprop_T)); @@ -986,6 +991,15 @@ text_prop_type_by_id(buf_T *buf, int id) } /* + * Return TRUE if "prop" is a valid text property type. + */ + int +text_prop_type_valid(buf_T *buf, textprop_T *prop) +{ + return text_prop_type_by_id(buf, prop->tp_type) != NULL; +} + +/* * prop_clear({lnum} [, {lnum_end} [, {bufnr}]]) */ void @@ -1745,7 +1759,7 @@ prop_type_set(typval_T *argvars, int add name = tv_get_string(&argvars[0]); if (*name == NUL) { - emsg(_(e_invalid_argument)); + semsg(_(e_invalid_argument_str), "\"\""); return; } @@ -1898,7 +1912,7 @@ f_prop_type_delete(typval_T *argvars, ty name = tv_get_string(&argvars[0]); if (*name == NUL) { - emsg(_(e_invalid_argument)); + semsg(_(e_invalid_argument_str), "\"\""); return; } @@ -1926,6 +1940,10 @@ f_prop_type_delete(typval_T *argvars, ty } hash_remove(ht, hi, "prop type delete"); vim_free(prop); + + // currently visibile text properties will disappear + redraw_all_later(UPD_CLEAR); + changed_window_setting_buf(buf == NULL ? curbuf : buf); } } @@ -1945,7 +1963,7 @@ f_prop_type_get(typval_T *argvars, typva name = tv_get_string(&argvars[0]); if (*name == NUL) { - emsg(_(e_invalid_argument)); + semsg(_(e_invalid_argument_str), "\"\""); return; } if (rettv_dict_alloc(rettv) == OK) diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -696,6 +696,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 993, +/**/ 992, /**/ 991,