1" Tests for defining text property types and adding text properties to the
2" buffer.
3
4if !has('textprop')
5  finish
6endif
7
8source screendump.vim
9
10func Test_proptype_global()
11  call prop_type_add('comment', {'highlight': 'Directory', 'priority': 123, 'start_incl': 1, 'end_incl': 1})
12  let proptypes = prop_type_list()
13  call assert_equal(1, len(proptypes))
14  call assert_equal('comment', proptypes[0])
15
16  let proptype = prop_type_get('comment')
17  call assert_equal('Directory', proptype['highlight'])
18  call assert_equal(123, proptype['priority'])
19  call assert_equal(1, proptype['start_incl'])
20  call assert_equal(1, proptype['end_incl'])
21
22  call prop_type_delete('comment')
23  call assert_equal(0, len(prop_type_list()))
24
25  call prop_type_add('one', {})
26  call assert_equal(1, len(prop_type_list()))
27  let proptype = prop_type_get('one')
28  call assert_false(has_key(proptype, 'highlight'))
29  call assert_equal(0, proptype['priority'])
30  call assert_equal(0, proptype['start_incl'])
31  call assert_equal(0, proptype['end_incl'])
32
33  call prop_type_add('two', {})
34  call assert_equal(2, len(prop_type_list()))
35  call prop_type_delete('one')
36  call assert_equal(1, len(prop_type_list()))
37  call prop_type_delete('two')
38  call assert_equal(0, len(prop_type_list()))
39endfunc
40
41func Test_proptype_buf()
42  let bufnr = bufnr('')
43  call prop_type_add('comment', {'bufnr': bufnr, 'highlight': 'Directory', 'priority': 123, 'start_incl': 1, 'end_incl': 1})
44  let proptypes = prop_type_list({'bufnr': bufnr})
45  call assert_equal(1, len(proptypes))
46  call assert_equal('comment', proptypes[0])
47
48  let proptype = prop_type_get('comment', {'bufnr': bufnr})
49  call assert_equal('Directory', proptype['highlight'])
50  call assert_equal(123, proptype['priority'])
51  call assert_equal(1, proptype['start_incl'])
52  call assert_equal(1, proptype['end_incl'])
53
54  call prop_type_delete('comment', {'bufnr': bufnr})
55  call assert_equal(0, len(prop_type_list({'bufnr': bufnr})))
56
57  call prop_type_add('one', {'bufnr': bufnr})
58  let proptype = prop_type_get('one', {'bufnr': bufnr})
59  call assert_false(has_key(proptype, 'highlight'))
60  call assert_equal(0, proptype['priority'])
61  call assert_equal(0, proptype['start_incl'])
62  call assert_equal(0, proptype['end_incl'])
63
64  call prop_type_add('two', {'bufnr': bufnr})
65  call assert_equal(2, len(prop_type_list({'bufnr': bufnr})))
66  call prop_type_delete('one', {'bufnr': bufnr})
67  call assert_equal(1, len(prop_type_list({'bufnr': bufnr})))
68  call prop_type_delete('two', {'bufnr': bufnr})
69  call assert_equal(0, len(prop_type_list({'bufnr': bufnr})))
70endfunc
71
72func AddPropTypes()
73  call prop_type_add('one', {})
74  call prop_type_add('two', {})
75  call prop_type_add('three', {})
76  call prop_type_add('whole', {})
77endfunc
78
79func DeletePropTypes()
80  call prop_type_delete('one')
81  call prop_type_delete('two')
82  call prop_type_delete('three')
83  call prop_type_delete('whole')
84endfunc
85
86func SetupPropsInFirstLine()
87  call setline(1, 'one two three')
88  call prop_add(1, 1, {'length': 3, 'id': 11, 'type': 'one'})
89  call prop_add(1, 5, {'length': 3, 'id': 12, 'type': 'two'})
90  call prop_add(1, 8, {'length': 5, 'id': 13, 'type': 'three'})
91  call prop_add(1, 1, {'length': 13, 'id': 14, 'type': 'whole'})
92endfunc
93
94let s:expected_props = [{'col': 1, 'length': 13, 'id': 14, 'type': 'whole', 'start': 1, 'end': 1},
95      \ {'col': 1, 'length': 3, 'id': 11, 'type': 'one', 'start': 1, 'end': 1},
96      \ {'col': 5, 'length': 3, 'id': 12, 'type': 'two', 'start': 1, 'end': 1},
97      \ {'col': 8, 'length': 5, 'id': 13, 'type': 'three', 'start': 1, 'end': 1},
98      \ ]
99
100func Test_prop_add()
101  new
102  call AddPropTypes()
103  call SetupPropsInFirstLine()
104  call assert_equal(s:expected_props, prop_list(1))
105  call assert_fails("call prop_add(10, 1, {'length': 1, 'id': 14, 'type': 'whole'})", 'E966:')
106  call assert_fails("call prop_add(1, 22, {'length': 1, 'id': 14, 'type': 'whole'})", 'E964:')
107
108  " Insert a line above, text props must still be there.
109  call append(0, 'empty')
110  call assert_equal(s:expected_props, prop_list(2))
111  " Delete a line above, text props must still be there.
112  1del
113  call assert_equal(s:expected_props, prop_list(1))
114
115  call DeletePropTypes()
116  bwipe!
117endfunc
118
119func Test_prop_remove()
120  new
121  call AddPropTypes()
122  call SetupPropsInFirstLine()
123  let props = deepcopy(s:expected_props)
124  call assert_equal(props, prop_list(1))
125
126  " remove by id
127  call prop_remove({'id': 12}, 1)
128  unlet props[2]
129  call assert_equal(props, prop_list(1))
130
131  " remove by type
132  call prop_remove({'type': 'one'}, 1)
133  unlet props[1]
134  call assert_equal(props, prop_list(1))
135
136  call DeletePropTypes()
137  bwipe!
138endfunc
139
140func Test_prop_add_remove_buf()
141  new
142  let bufnr = bufnr('')
143  call AddPropTypes()
144  call setline(1, 'one two three')
145  wincmd w
146  call prop_add(1, 1, {'length': 3, 'id': 11, 'type': 'one', 'bufnr': bufnr})
147  call prop_add(1, 5, {'length': 3, 'id': 12, 'type': 'two', 'bufnr': bufnr})
148  call prop_add(1, 11, {'length': 3, 'id': 13, 'type': 'three', 'bufnr': bufnr})
149
150  let props = [
151	\ {'col': 1, 'length': 3, 'id': 11, 'type': 'one', 'start': 1, 'end': 1},
152	\ {'col': 5, 'length': 3, 'id': 12, 'type': 'two', 'start': 1, 'end': 1},
153	\ {'col': 11, 'length': 3, 'id': 13, 'type': 'three', 'start': 1, 'end': 1},
154	\]
155  call assert_equal(props, prop_list(1, {'bufnr': bufnr}))
156
157  " remove by id
158  call prop_remove({'id': 12, 'bufnr': bufnr}, 1)
159  unlet props[1]
160  call assert_equal(props, prop_list(1, {'bufnr': bufnr}))
161
162  " remove by type
163  call prop_remove({'type': 'one', 'bufnr': bufnr}, 1)
164  unlet props[0]
165  call assert_equal(props, prop_list(1, {'bufnr': bufnr}))
166
167  call DeletePropTypes()
168  wincmd w
169  bwipe!
170endfunc
171
172
173func Test_prop_clear()
174  new
175  call AddPropTypes()
176  call SetupPropsInFirstLine()
177  call assert_equal(s:expected_props, prop_list(1))
178
179  call prop_clear(1)
180  call assert_equal([], prop_list(1))
181
182  call DeletePropTypes()
183  bwipe!
184endfunc
185
186func Test_prop_clear_buf()
187  new
188  call AddPropTypes()
189  call SetupPropsInFirstLine()
190  let bufnr = bufnr('')
191  wincmd w
192  call assert_equal(s:expected_props, prop_list(1, {'bufnr': bufnr}))
193
194  call prop_clear(1, 1, {'bufnr': bufnr})
195  call assert_equal([], prop_list(1, {'bufnr': bufnr}))
196
197  wincmd w
198  call DeletePropTypes()
199  bwipe!
200endfunc
201
202" Setup a three line prop in lines 2 - 4.
203" Add short props in line 1 and 5.
204func Setup_three_line_prop()
205  new
206  call setline(1, ['one', 'twotwo', 'three', 'fourfour', 'five'])
207  call prop_add(1, 2, {'length': 1, 'type': 'comment'})
208  call prop_add(2, 4, {'end_lnum': 4, 'end_col': 5, 'type': 'comment'})
209  call prop_add(5, 2, {'length': 1, 'type': 'comment'})
210endfunc
211
212func Test_prop_multiline()
213  call prop_type_add('comment', {'highlight': 'Directory'})
214  new
215  call setline(1, ['xxxxxxx', 'yyyyyyyyy', 'zzzzzzzz'])
216
217  " start halfway line 1, end halfway line 3
218  call prop_add(1, 3, {'end_lnum': 3, 'end_col': 5, 'type': 'comment'})
219  let expect1 = {'col': 3, 'length': 6, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0}
220  call assert_equal([expect1], prop_list(1))
221  let expect2 = {'col': 1, 'length': 10, 'type': 'comment', 'start': 0, 'end': 0, 'id': 0}
222  call assert_equal([expect2], prop_list(2))
223  let expect3 = {'col': 1, 'length': 5, 'type': 'comment', 'start': 0, 'end': 1, 'id': 0}
224  call assert_equal([expect3], prop_list(3))
225  call prop_clear(1, 3)
226
227  " include all three lines
228  call prop_add(1, 1, {'end_lnum': 3, 'end_col': 999, 'type': 'comment'})
229  let expect1.col = 1
230  let expect1.length = 8
231  call assert_equal([expect1], prop_list(1))
232  call assert_equal([expect2], prop_list(2))
233  let expect3.length = 9
234  call assert_equal([expect3], prop_list(3))
235  call prop_clear(1, 3)
236
237  bwipe!
238
239  " Test deleting the first line with a prop.
240  call Setup_three_line_prop()
241  let expect2 = {'col': 4, 'length': 4, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0}
242  call assert_equal([expect2], prop_list(2))
243  2del
244  let expect_short = {'col': 2, 'length': 1, 'type': 'comment', 'start': 1, 'end': 1, 'id': 0}
245  call assert_equal([expect_short], prop_list(1))
246  let expect2 = {'col': 1, 'length': 6, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0}
247  call assert_equal([expect2], prop_list(2))
248  bwipe!
249
250  " Test deleting the last line with a prop.
251  call Setup_three_line_prop()
252  let expect3 = {'col': 1, 'length': 6, 'type': 'comment', 'start': 0, 'end': 0, 'id': 0}
253  call assert_equal([expect3], prop_list(3))
254  let expect4 = {'col': 1, 'length': 5, 'type': 'comment', 'start': 0, 'end': 1, 'id': 0}
255  call assert_equal([expect4], prop_list(4))
256  4del
257  let expect3 = {'col': 1, 'length': 6, 'type': 'comment', 'start': 0, 'end': 1, 'id': 0}
258  call assert_equal([expect3], prop_list(3))
259  call assert_equal([expect_short], prop_list(4))
260  bwipe!
261
262  " Test appending a line below the text prop start.
263  call Setup_three_line_prop()
264  let expect2 = {'col': 4, 'length': 4, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0}
265  call assert_equal([expect2], prop_list(2))
266  call append(2, "new line")
267  call assert_equal([expect2], prop_list(2))
268  let expect3 = {'col': 1, 'length': 9, 'type': 'comment', 'start': 0, 'end': 0, 'id': 0}
269  call assert_equal([expect3], prop_list(3))
270  bwipe!
271
272  call prop_type_delete('comment')
273endfunc
274
275func Test_prop_byteoff()
276  call prop_type_add('comment', {'highlight': 'Directory'})
277  new
278  call setline(1, ['line1', 'second line', ''])
279  set ff=unix
280  call assert_equal(19, line2byte(3))
281  call prop_add(1, 1, {'end_col': 3, 'type': 'comment'})
282  call assert_equal(19, line2byte(3))
283
284  bwipe!
285  call prop_type_delete('comment')
286endfunc
287
288" screenshot test with textprop highlighting
289funct Test_textprop_screenshots()
290  if !CanRunVimInTerminal()
291    return
292  endif
293  call writefile([
294	\ "call setline(1, ['One two', 'Number 123 and then 4567.', 'Three'])",
295	\ "hi NumberProp ctermfg=blue",
296	\ "hi LongProp ctermbg=yellow",
297	\ "call prop_type_add('number', {'highlight': 'NumberProp'})",
298	\ "call prop_type_add('long', {'highlight': 'LongProp'})",
299	\ "call prop_add(1, 4, {'end_lnum': 3, 'end_col': 3, 'type': 'long'})",
300	\ "call prop_add(2, 8, {'length': 3, 'type': 'number'})",
301	\ "call prop_add(2, 21, {'length': 4, 'type': 'number'})",
302	\ "set number",
303	\ "set spell",
304	\], 'XtestProp')
305  let buf = RunVimInTerminal('-S XtestProp', {})
306  call VerifyScreenDump(buf, 'Test_textprop_01', {})
307
308  " clean up
309  call StopVimInTerminal(buf)
310  call delete('XtestProp')
311endfunc
312