Skip to content

Commit

Permalink
patch 8.2.3356: adding many text properties requires a lot of functio…
Browse files Browse the repository at this point in the history
…n calls

Problem:    Adding many text properties requires a lot of function calls.
Solution:   Add the prop_add_list() function. (Yegappan Lakshmanan,
            closes #8751)
  • Loading branch information
yegappan authored and brammool committed Aug 16, 2021
1 parent 434df7a commit ccfb7c6
Show file tree
Hide file tree
Showing 9 changed files with 253 additions and 77 deletions.
4 changes: 3 additions & 1 deletion runtime/doc/eval.txt
Expand Up @@ -2801,7 +2801,9 @@ prompt_getprompt({buf}) String get prompt text
prompt_setcallback({buf}, {expr}) none set prompt callback function
prompt_setinterrupt({buf}, {text}) none set prompt interrupt function
prompt_setprompt({buf}, {text}) none set prompt text
prop_add({lnum}, {col}, {props}) none add a text property
prop_add({lnum}, {col}, {props}) none add one text property
prop_add_list({props}, [[{lnum}, {col}, {end-lnum}, {end-col}], ...])
none add multiple text properties
prop_clear({lnum} [, {lnum-end} [, {props}]])
none remove all text properties
prop_find({props} [, {direction}])
Expand Down
32 changes: 32 additions & 0 deletions runtime/doc/textprop.txt
Expand Up @@ -108,6 +108,9 @@ prop_type_list([{props}]) get list of property types
Manipulating text properties:

prop_add({lnum}, {col}, {props}) add a text property
prop_add_list({props}, [[{lnum}, {col}, {end-lnum}, {end-col}], ...])
add a text property at multiple
positions.
prop_clear({lnum} [, {lnum-end} [, {bufnr}]])
remove all text properties
prop_find({props} [, {direction}]) search for a text property
Expand Down Expand Up @@ -158,6 +161,35 @@ prop_add({lnum}, {col}, {props})
Can also be used as a |method|: >
GetLnum()->prop_add(col, props)
*prop_add_list()*
prop_add_list({props}, [[{lnum}, {col}, {end-lnum}, {end-col}], ...])
Similar to prop_add(), but attaches a text property at
multiple positions in a buffer.

{props} is a dictionary with these fields:
bufnr buffer to add the property to; when omitted
the current buffer is used
id user defined ID for the property; must be a
number; when omitted zero is used
type name of the text property type
All fields except "type" are optional.

The second argument is a List of Lists where each list
specifies the starting and ending position of the text. The
first two items {lnum} and {col} specify the starting position
of the text where the property will be attached and the last
two items {end-lnum} and {end-col} specify the position just
after the text.

Example:
call prop_add_list(#{type: 'MyProp', id: 2},
\ [[1, 4, 1, 7],
\ [1, 15, 1, 20],
\ [2, 30, 3, 30]]

Can also be used as a |method|: >
GetProp()->prop_add_list([[1, 1, 1, 2], [1, 4, 1, 8]])
prop_clear({lnum} [, {lnum-end} [, {props}]]) *prop_clear()*
Remove all text properties from line {lnum}.
Expand Down
1 change: 1 addition & 0 deletions runtime/doc/usr_41.txt
Expand Up @@ -1161,6 +1161,7 @@ Prompt Buffer: *promptbuffer-functions*

Text Properties: *text-property-functions*
prop_add() attach a property at a position
prop_add_list() attach a property at multiple positions
prop_clear() remove all properties from a line or lines
prop_find() search for a property
prop_list() return a list of all properties in a line
Expand Down
3 changes: 3 additions & 0 deletions src/evalfunc.c
Expand Up @@ -708,6 +708,7 @@ static argcheck_T arg2_buffer_number[] = {arg_buffer, arg_number};
static argcheck_T arg2_buffer_string[] = {arg_buffer, arg_string};
static argcheck_T arg2_chan_or_job_dict[] = {arg_chan_or_job, arg_dict_any};
static argcheck_T arg2_chan_or_job_string[] = {arg_chan_or_job, arg_string};
static argcheck_T arg2_dict_any_list_any[] = {arg_dict_any, arg_list_any};
static argcheck_T arg2_dict_any_string_or_nr[] = {arg_dict_any, arg_string_or_nr};
static argcheck_T arg2_dict_string[] = {arg_dict_any, arg_string};
static argcheck_T arg2_float_or_nr[] = {arg_float_or_nr, arg_float_or_nr};
Expand Down Expand Up @@ -1740,6 +1741,8 @@ static funcentry_T global_functions[] =
ret_void, JOB_FUNC(f_prompt_setprompt)},
{"prop_add", 3, 3, FEARG_1, arg3_number_number_dict,
ret_void, PROP_FUNC(f_prop_add)},
{"prop_add_list", 2, 2, FEARG_1, arg2_dict_any_list_any,
ret_void, PROP_FUNC(f_prop_add_list)},
{"prop_clear", 1, 3, FEARG_1, arg3_number_number_dict,
ret_void, PROP_FUNC(f_prop_clear)},
{"prop_find", 1, 2, FEARG_1, arg2_dict_string,
Expand Down
1 change: 1 addition & 0 deletions src/proto/textprop.pro
@@ -1,6 +1,7 @@
/* textprop.c */
int find_prop_type_id(char_u *name, buf_T *buf);
void f_prop_add(typval_T *argvars, typval_T *rettv);
void f_prop_add_list(typval_T *argvars, typval_T *rettv);
void prop_add_common(linenr_T start_lnum, colnr_T start_col, dict_T *dict, buf_T *default_buf, typval_T *dict_arg);
int get_text_props(buf_T *buf, linenr_T lnum, char_u **props, int will_change);
int count_props(linenr_T lnum, int only_starting);
Expand Down
35 changes: 35 additions & 0 deletions src/testdir/test_textprop.vim
Expand Up @@ -339,6 +339,41 @@ func Test_prop_add()
bwipe!
endfunc

" Test for the prop_add_list() function
func Test_prop_add_list()
new
call AddPropTypes()
call setline(1, ['one one one', 'two two two', 'six six six', 'ten ten ten'])
call prop_add_list(#{type: 'one', id: 2},
\ [[1, 1, 1, 3], [2, 5, 2, 7], [3, 6, 4, 6]])
call assert_equal([#{id: 2, col: 1, type_bufnr: 0, end: 1, type: 'one',
\ length: 2, start: 1}], prop_list(1))
call assert_equal([#{id: 2, col: 5, type_bufnr: 0, end: 1, type: 'one',
\ length: 2, start: 1}], prop_list(2))
call assert_equal([#{id: 2, col: 6, type_bufnr: 0, end: 0, type: 'one',
\ length: 7, start: 1}], prop_list(3))
call assert_equal([#{id: 2, col: 1, type_bufnr: 0, end: 1, type: 'one',
\ length: 5, start: 0}], prop_list(4))
call assert_fails('call prop_add_list([1, 2], [[1, 1, 3]])', 'E1206:')
call assert_fails('call prop_add_list({}, {})', 'E1211:')
call assert_fails('call prop_add_list({}, [[1, 1, 3]])', 'E965:')
call assert_fails('call prop_add_list(#{type: "abc"}, [[1, 1, 1, 3]])', 'E971:')
call assert_fails('call prop_add_list(#{type: "one"}, [[]])', 'E474:')
call assert_fails('call prop_add_list(#{type: "one"}, [[1, 1, 1, 1], {}])', 'E714:')
call assert_fails('call prop_add_list(#{type: "one"}, [[1, 1, "a"]])', 'E474:')
call assert_fails('call prop_add_list(#{type: "one"}, [[2, 2]])', 'E474:')
call assert_fails('call prop_add_list(#{type: "one"}, [[1, 1, 2], [2, 2]])', 'E474:')
call assert_fails('call prop_add_list(#{type: "one"}, [[1, 1, 1, 2], [4, 1, 5, 2]])', 'E966:')
call assert_fails('call prop_add_list(#{type: "one"}, [[3, 1, 1, 2]])', 'E966:')
call assert_fails('call prop_add_list(#{type: "one"}, [[2, 2, 2, 2], [3, 20, 3, 22]])', 'E964:')
call assert_fails('eval #{type: "one"}->prop_add_list([[2, 2, 2, 2], [3, 20, 3, 22]])', 'E964:')
call assert_fails('call prop_add_list(test_null_dict(), [[2, 2, 2]])', 'E965:')
call assert_fails('call prop_add_list(#{type: "one"}, test_null_list())', 'E714:')
call assert_fails('call prop_add_list(#{type: "one"}, [test_null_list()])', 'E714:')
call DeletePropTypes()
bw!
endfunc

func Test_prop_remove()
new
call AddPropTypes()
Expand Down
5 changes: 5 additions & 0 deletions src/testdir/test_vim9_builtin.vim
Expand Up @@ -2364,6 +2364,11 @@ def Test_prop_add()
CheckDefAndScriptFailure2(['prop_add(1, 2, [])'], 'E1013: Argument 3: type mismatch, expected dict<any> but got list<unknown>', 'E1206: Dictionary required for argument 3')
enddef

def Test_prop_add_list()
CheckDefAndScriptFailure2(['prop_add_list([], [])'], 'E1013: Argument 1: type mismatch, expected dict<any> but got list<unknown>', 'E1206: Dictionary required for argument 1')
CheckDefAndScriptFailure2(['prop_add_list({}, {})'], 'E1013: Argument 2: type mismatch, expected list<any> but got dict<unknown>', 'E1211: List required for argument 2')
enddef

def Test_prop_clear()
CheckDefAndScriptFailure2(['prop_clear("a")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1')
CheckDefAndScriptFailure2(['prop_clear(1, "b")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2')
Expand Down

0 comments on commit ccfb7c6

Please sign in to comment.