blob: f91597ff5108e144cd8b01728d679f9054816574 [file] [log] [blame]
Bram Moolenaar98aefe72018-12-13 22:20:09 +01001" Tests for defining text property types and adding text properties to the
2" buffer.
3
Bram Moolenaarb46fecd2019-06-15 17:58:09 +02004source check.vim
5CheckFeature textprop
Bram Moolenaar98aefe72018-12-13 22:20:09 +01006
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +01007source screendump.vim
8
Bram Moolenaar98aefe72018-12-13 22:20:09 +01009func Test_proptype_global()
10 call prop_type_add('comment', {'highlight': 'Directory', 'priority': 123, 'start_incl': 1, 'end_incl': 1})
11 let proptypes = prop_type_list()
12 call assert_equal(1, len(proptypes))
13 call assert_equal('comment', proptypes[0])
14
15 let proptype = prop_type_get('comment')
16 call assert_equal('Directory', proptype['highlight'])
17 call assert_equal(123, proptype['priority'])
18 call assert_equal(1, proptype['start_incl'])
19 call assert_equal(1, proptype['end_incl'])
20
21 call prop_type_delete('comment')
22 call assert_equal(0, len(prop_type_list()))
23
24 call prop_type_add('one', {})
25 call assert_equal(1, len(prop_type_list()))
Bram Moolenaara5a78822019-09-04 21:57:18 +020026 let proptype = 'one'->prop_type_get()
Bram Moolenaar98aefe72018-12-13 22:20:09 +010027 call assert_false(has_key(proptype, 'highlight'))
28 call assert_equal(0, proptype['priority'])
29 call assert_equal(0, proptype['start_incl'])
30 call assert_equal(0, proptype['end_incl'])
31
32 call prop_type_add('two', {})
33 call assert_equal(2, len(prop_type_list()))
34 call prop_type_delete('one')
35 call assert_equal(1, len(prop_type_list()))
36 call prop_type_delete('two')
37 call assert_equal(0, len(prop_type_list()))
38endfunc
39
40func Test_proptype_buf()
41 let bufnr = bufnr('')
42 call prop_type_add('comment', {'bufnr': bufnr, 'highlight': 'Directory', 'priority': 123, 'start_incl': 1, 'end_incl': 1})
43 let proptypes = prop_type_list({'bufnr': bufnr})
44 call assert_equal(1, len(proptypes))
45 call assert_equal('comment', proptypes[0])
46
47 let proptype = prop_type_get('comment', {'bufnr': bufnr})
48 call assert_equal('Directory', proptype['highlight'])
49 call assert_equal(123, proptype['priority'])
50 call assert_equal(1, proptype['start_incl'])
51 call assert_equal(1, proptype['end_incl'])
52
53 call prop_type_delete('comment', {'bufnr': bufnr})
Bram Moolenaara5a78822019-09-04 21:57:18 +020054 call assert_equal(0, len({'bufnr': bufnr}->prop_type_list()))
Bram Moolenaar98aefe72018-12-13 22:20:09 +010055
56 call prop_type_add('one', {'bufnr': bufnr})
57 let proptype = prop_type_get('one', {'bufnr': bufnr})
58 call assert_false(has_key(proptype, 'highlight'))
59 call assert_equal(0, proptype['priority'])
60 call assert_equal(0, proptype['start_incl'])
61 call assert_equal(0, proptype['end_incl'])
62
63 call prop_type_add('two', {'bufnr': bufnr})
64 call assert_equal(2, len(prop_type_list({'bufnr': bufnr})))
65 call prop_type_delete('one', {'bufnr': bufnr})
66 call assert_equal(1, len(prop_type_list({'bufnr': bufnr})))
67 call prop_type_delete('two', {'bufnr': bufnr})
68 call assert_equal(0, len(prop_type_list({'bufnr': bufnr})))
Bram Moolenaarf0884c52019-05-24 21:22:29 +020069
70 call assert_fails("call prop_type_add('one', {'bufnr': 98764})", "E158:")
Bram Moolenaar98aefe72018-12-13 22:20:09 +010071endfunc
72
73func AddPropTypes()
74 call prop_type_add('one', {})
75 call prop_type_add('two', {})
76 call prop_type_add('three', {})
77 call prop_type_add('whole', {})
78endfunc
79
80func DeletePropTypes()
81 call prop_type_delete('one')
82 call prop_type_delete('two')
83 call prop_type_delete('three')
84 call prop_type_delete('whole')
85endfunc
86
87func SetupPropsInFirstLine()
88 call setline(1, 'one two three')
89 call prop_add(1, 1, {'length': 3, 'id': 11, 'type': 'one'})
Bram Moolenaara5a78822019-09-04 21:57:18 +020090 eval 1->prop_add(5, {'length': 3, 'id': 12, 'type': 'two'})
Bram Moolenaar4164bb22019-01-04 23:09:49 +010091 call prop_add(1, 9, {'length': 5, 'id': 13, 'type': 'three'})
Bram Moolenaar98aefe72018-12-13 22:20:09 +010092 call prop_add(1, 1, {'length': 13, 'id': 14, 'type': 'whole'})
93endfunc
94
Bram Moolenaar4164bb22019-01-04 23:09:49 +010095func Get_expected_props()
96 return [
97 \ {'col': 1, 'length': 13, 'id': 14, 'type': 'whole', 'start': 1, 'end': 1},
Bram Moolenaar98aefe72018-12-13 22:20:09 +010098 \ {'col': 1, 'length': 3, 'id': 11, 'type': 'one', 'start': 1, 'end': 1},
99 \ {'col': 5, 'length': 3, 'id': 12, 'type': 'two', 'start': 1, 'end': 1},
Bram Moolenaar4164bb22019-01-04 23:09:49 +0100100 \ {'col': 9, 'length': 5, 'id': 13, 'type': 'three', 'start': 1, 'end': 1},
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100101 \ ]
Bram Moolenaar4164bb22019-01-04 23:09:49 +0100102endfunc
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100103
Bram Moolenaare05a89a2020-01-10 19:56:46 +0100104func Test_prop_find()
105 new
106 call setline(1, ['one one one', 'twotwo', 'three', 'fourfour', 'five', 'sixsix'])
107
108 " Add two text props on lines 1 and 5, and one spanning lines 2 to 4.
109 call prop_type_add('prop_name', {'highlight': 'Directory'})
110 call prop_add(1, 5, {'type': 'prop_name', 'id': 10, 'length': 3})
111 call prop_add(2, 4, {'type': 'prop_name', 'id': 11, 'end_lnum': 4, 'end_col': 9})
112 call prop_add(5, 4, {'type': 'prop_name', 'id': 12, 'length': 1})
113
114 let expected = [
115 \ {'lnum': 1, 'col': 5, 'length': 3, 'id': 10, 'type': 'prop_name', 'start': 1, 'end': 1},
116 \ {'lnum': 2, 'col': 4, 'id': 11, 'type': 'prop_name', 'start': 1, 'end': 0},
117 \ {'lnum': 5, 'col': 4, 'length': 1, 'id': 12, 'type': 'prop_name', 'start': 1, 'end': 1}
118 \ ]
119
120 " Starting at line 5 col 1 this should find the prop at line 5 col 4.
121 call cursor(5,1)
122 let result = prop_find({'type': 'prop_name'}, 'f')
123 call assert_equal(expected[2], result)
124
125 " With skipstart left at false (default), this should find the prop at line
126 " 5 col 4.
127 let result = prop_find({'type': 'prop_name', 'lnum': 5, 'col': 4}, 'b')
128 call assert_equal(expected[2], result)
129
130 " With skipstart set to true, this should skip the prop at line 5 col 4.
131 let result = prop_find({'type': 'prop_name', 'lnum': 5, 'col': 4, 'skipstart': 1}, 'b')
132 unlet result.length
133 call assert_equal(expected[1], result)
134
135 " Search backwards from line 1 col 10 to find the prop on the same line.
136 let result = prop_find({'type': 'prop_name', 'lnum': 1, 'col': 10}, 'b')
137 call assert_equal(expected[0], result)
138
139 " with skipstart set to false, if the start position is anywhere between the
140 " start and end lines of a text prop (searching forward or backward), the
141 " result should be the prop on the first line (the line with 'start' set to 1).
142 call cursor(3,1)
143 let result = prop_find({'type': 'prop_name'}, 'f')
144 unlet result.length
145 call assert_equal(expected[1], result)
146 let result = prop_find({'type': 'prop_name'}, 'b')
147 unlet result.length
148 call assert_equal(expected[1], result)
149
150 " with skipstart set to true, if the start position is anywhere between the
151 " start and end lines of a text prop (searching forward or backward), all lines
152 " of the prop will be skipped.
153 let result = prop_find({'type': 'prop_name', 'skipstart': 1}, 'b')
154 call assert_equal(expected[0], result)
155 let result = prop_find({'type': 'prop_name', 'skipstart': 1}, 'f')
156 call assert_equal(expected[2], result)
157
158 " Use skipstart to search through all props with type name 'prop_name'.
159 " First forward...
160 let lnum = 1
161 let col = 1
162 let i = 0
163 for exp in expected
164 let result = prop_find({'type': 'prop_name', 'lnum': lnum, 'col': col, 'skipstart': 1}, 'f')
165 if !has_key(exp, "length")
166 unlet result.length
167 endif
168 call assert_equal(exp, result)
169 let lnum = result.lnum
170 let col = result.col
171 let i = i + 1
172 endfor
173
174 " ...then backwards.
175 let lnum = 6
176 let col = 4
177 let i = 2
178 while i >= 0
179 let result = prop_find({'type': 'prop_name', 'lnum': lnum, 'col': col, 'skipstart': 1}, 'b')
180 if !has_key(expected[i], "length")
181 unlet result.length
182 endif
183 call assert_equal(expected[i], result)
184 let lnum = result.lnum
185 let col = result.col
186 let i = i - 1
187 endwhile
188
189 " Starting from line 6 col 1 search backwards for prop with id 10.
190 call cursor(6,1)
191 let result = prop_find({'id': 10, 'skipstart': 1}, 'b')
192 call assert_equal(expected[0], result)
193
194 " Starting from line 1 col 1 search forwards for prop with id 12.
195 call cursor(1,1)
196 let result = prop_find({'id': 12}, 'f')
197 call assert_equal(expected[2], result)
198
199 " Search for a prop with an unknown id.
200 let result = prop_find({'id': 999}, 'f')
201 call assert_equal({}, result)
202
203 " Search backwards from the proceeding position of the prop with id 11
204 " (at line num 2 col 4). This should return an empty dict.
205 let result = prop_find({'id': 11, 'lnum': 2, 'col': 3}, 'b')
206 call assert_equal({}, result)
207
208 " When lnum is given and col is omitted, use column 1.
209 let result = prop_find({'type': 'prop_name', 'lnum': 1}, 'f')
210 call assert_equal(expected[0], result)
211
212 call prop_clear(1,6)
213 call prop_type_delete('prop_name')
214endfunc
215
Bram Moolenaar346f18e2020-03-13 21:36:40 +0100216func Test_prop_find_smaller_len_than_match_col()
217 new
218 call prop_type_add('test', {'highlight': 'ErrorMsg'})
219 call setline(1, ['xxxx', 'x'])
220 call prop_add(1, 4, {'type': 'test'})
221 call assert_equal({'id': 0, 'lnum': 1, 'col': 4, 'type': 'test', 'length': 0, 'start': 1, 'end': 1},
222 \ prop_find({'type': 'test', 'lnum': 2, 'col': 1}, 'b'))
223 bwipe!
224 call prop_type_delete('test')
225endfunc
226
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100227func Test_prop_add()
228 new
229 call AddPropTypes()
230 call SetupPropsInFirstLine()
Bram Moolenaar4164bb22019-01-04 23:09:49 +0100231 let expected_props = Get_expected_props()
232 call assert_equal(expected_props, prop_list(1))
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100233 call assert_fails("call prop_add(10, 1, {'length': 1, 'id': 14, 'type': 'whole'})", 'E966:')
234 call assert_fails("call prop_add(1, 22, {'length': 1, 'id': 14, 'type': 'whole'})", 'E964:')
235
236 " Insert a line above, text props must still be there.
237 call append(0, 'empty')
Bram Moolenaar4164bb22019-01-04 23:09:49 +0100238 call assert_equal(expected_props, prop_list(2))
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100239 " Delete a line above, text props must still be there.
240 1del
Bram Moolenaar4164bb22019-01-04 23:09:49 +0100241 call assert_equal(expected_props, prop_list(1))
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100242
Bram Moolenaarb9c67a52019-01-01 19:49:20 +0100243 " Prop without length or end column is zero length
244 call prop_clear(1)
Bram Moolenaar12f20032020-02-26 22:06:00 +0100245 call prop_type_add('included', {'start_incl': 1, 'end_incl': 1})
246 call prop_add(1, 5, #{type: 'included'})
247 let expected = [#{col: 5, length: 0, type: 'included', id: 0, start: 1, end: 1}]
248 call assert_equal(expected, prop_list(1))
249
250 " Inserting text makes the prop bigger.
251 exe "normal 5|ixx\<Esc>"
252 let expected = [#{col: 5, length: 2, type: 'included', id: 0, start: 1, end: 1}]
Bram Moolenaarb9c67a52019-01-01 19:49:20 +0100253 call assert_equal(expected, prop_list(1))
254
Bram Moolenaarf0884c52019-05-24 21:22:29 +0200255 call assert_fails("call prop_add(1, 5, {'type': 'two', 'bufnr': 234343})", 'E158:')
256
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100257 call DeletePropTypes()
Bram Moolenaar12f20032020-02-26 22:06:00 +0100258 call prop_type_delete('included')
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100259 bwipe!
260endfunc
261
262func Test_prop_remove()
263 new
264 call AddPropTypes()
265 call SetupPropsInFirstLine()
Bram Moolenaar4164bb22019-01-04 23:09:49 +0100266 let props = Get_expected_props()
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100267 call assert_equal(props, prop_list(1))
268
269 " remove by id
Bram Moolenaara5a78822019-09-04 21:57:18 +0200270 call assert_equal(1, {'id': 12}->prop_remove(1))
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100271 unlet props[2]
272 call assert_equal(props, prop_list(1))
273
274 " remove by type
Bram Moolenaarf0884c52019-05-24 21:22:29 +0200275 call assert_equal(1, prop_remove({'type': 'one'}, 1))
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100276 unlet props[1]
277 call assert_equal(props, prop_list(1))
278
Bram Moolenaarf0884c52019-05-24 21:22:29 +0200279 " remove from unknown buffer
280 call assert_fails("call prop_remove({'type': 'one', 'bufnr': 123456}, 1)", 'E158:')
281
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100282 call DeletePropTypes()
283 bwipe!
Bram Moolenaar49b79bd2020-03-05 21:52:55 +0100284
285 new
286 call AddPropTypes()
287 call SetupPropsInFirstLine()
288 call prop_add(1, 6, {'length': 2, 'id': 11, 'type': 'three'})
289 let props = Get_expected_props()
290 call insert(props, {'col': 6, 'length': 2, 'id': 11, 'type': 'three', 'start': 1, 'end': 1}, 3)
291 call assert_equal(props, prop_list(1))
292 call assert_equal(1, prop_remove({'type': 'three', 'id': 11, 'both': 1, 'all': 1}, 1))
293 unlet props[3]
294 call assert_equal(props, prop_list(1))
295
296 call assert_fails("call prop_remove({'id': 11, 'both': 1})", 'E860')
297 call assert_fails("call prop_remove({'type': 'three', 'both': 1})", 'E860')
298
299 call DeletePropTypes()
300 bwipe!
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100301endfunc
302
Bram Moolenaar196d1572019-01-02 23:47:18 +0100303func SetupOneLine()
304 call setline(1, 'xonex xtwoxx')
Bram Moolenaar45dd07f2019-05-15 22:45:37 +0200305 normal gg0
Bram Moolenaar196d1572019-01-02 23:47:18 +0100306 call AddPropTypes()
307 call prop_add(1, 2, {'length': 3, 'id': 11, 'type': 'one'})
308 call prop_add(1, 8, {'length': 3, 'id': 12, 'type': 'two'})
309 let expected = [
310 \ {'col': 2, 'length': 3, 'id': 11, 'type': 'one', 'start': 1, 'end': 1},
311 \ {'col': 8, 'length': 3, 'id': 12, 'type': 'two', 'start': 1, 'end': 1},
312 \]
313 call assert_equal(expected, prop_list(1))
314 return expected
315endfunc
316
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100317func Test_prop_add_remove_buf()
318 new
319 let bufnr = bufnr('')
320 call AddPropTypes()
Bram Moolenaar0a2f5782019-03-22 13:20:43 +0100321 for lnum in range(1, 4)
322 call setline(lnum, 'one two three')
323 endfor
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100324 wincmd w
Bram Moolenaar0a2f5782019-03-22 13:20:43 +0100325 for lnum in range(1, 4)
326 call prop_add(lnum, 1, {'length': 3, 'id': 11, 'type': 'one', 'bufnr': bufnr})
327 call prop_add(lnum, 5, {'length': 3, 'id': 12, 'type': 'two', 'bufnr': bufnr})
328 call prop_add(lnum, 11, {'length': 3, 'id': 13, 'type': 'three', 'bufnr': bufnr})
329 endfor
330
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100331 let props = [
332 \ {'col': 1, 'length': 3, 'id': 11, 'type': 'one', 'start': 1, 'end': 1},
333 \ {'col': 5, 'length': 3, 'id': 12, 'type': 'two', 'start': 1, 'end': 1},
334 \ {'col': 11, 'length': 3, 'id': 13, 'type': 'three', 'start': 1, 'end': 1},
335 \]
336 call assert_equal(props, prop_list(1, {'bufnr': bufnr}))
Bram Moolenaar0a2f5782019-03-22 13:20:43 +0100337
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100338 " remove by id
Bram Moolenaar0a2f5782019-03-22 13:20:43 +0100339 let before_props = deepcopy(props)
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100340 unlet props[1]
Bram Moolenaar0a2f5782019-03-22 13:20:43 +0100341
342 call prop_remove({'id': 12, 'bufnr': bufnr}, 1)
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100343 call assert_equal(props, prop_list(1, {'bufnr': bufnr}))
Bram Moolenaar0a2f5782019-03-22 13:20:43 +0100344 call assert_equal(before_props, prop_list(2, {'bufnr': bufnr}))
345 call assert_equal(before_props, prop_list(3, {'bufnr': bufnr}))
346 call assert_equal(before_props, prop_list(4, {'bufnr': bufnr}))
347
348 call prop_remove({'id': 12, 'bufnr': bufnr}, 3, 4)
349 call assert_equal(props, prop_list(1, {'bufnr': bufnr}))
350 call assert_equal(before_props, prop_list(2, {'bufnr': bufnr}))
351 call assert_equal(props, prop_list(3, {'bufnr': bufnr}))
352 call assert_equal(props, prop_list(4, {'bufnr': bufnr}))
353
354 call prop_remove({'id': 12, 'bufnr': bufnr})
355 for lnum in range(1, 4)
356 call assert_equal(props, prop_list(lnum, {'bufnr': bufnr}))
357 endfor
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100358
359 " remove by type
Bram Moolenaar0a2f5782019-03-22 13:20:43 +0100360 let before_props = deepcopy(props)
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100361 unlet props[0]
Bram Moolenaar0a2f5782019-03-22 13:20:43 +0100362
363 call prop_remove({'type': 'one', 'bufnr': bufnr}, 1)
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100364 call assert_equal(props, prop_list(1, {'bufnr': bufnr}))
Bram Moolenaar0a2f5782019-03-22 13:20:43 +0100365 call assert_equal(before_props, prop_list(2, {'bufnr': bufnr}))
366 call assert_equal(before_props, prop_list(3, {'bufnr': bufnr}))
367 call assert_equal(before_props, prop_list(4, {'bufnr': bufnr}))
368
369 call prop_remove({'type': 'one', 'bufnr': bufnr}, 3, 4)
370 call assert_equal(props, prop_list(1, {'bufnr': bufnr}))
371 call assert_equal(before_props, prop_list(2, {'bufnr': bufnr}))
372 call assert_equal(props, prop_list(3, {'bufnr': bufnr}))
373 call assert_equal(props, prop_list(4, {'bufnr': bufnr}))
374
375 call prop_remove({'type': 'one', 'bufnr': bufnr})
376 for lnum in range(1, 4)
377 call assert_equal(props, prop_list(lnum, {'bufnr': bufnr}))
378 endfor
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100379
380 call DeletePropTypes()
381 wincmd w
382 bwipe!
383endfunc
384
Bram Moolenaar33c8ca92019-01-02 18:00:27 +0100385func Test_prop_backspace()
386 new
387 set bs=2
Bram Moolenaar196d1572019-01-02 23:47:18 +0100388 let expected = SetupOneLine() " 'xonex xtwoxx'
Bram Moolenaar33c8ca92019-01-02 18:00:27 +0100389
390 exe "normal 0li\<BS>\<Esc>fxli\<BS>\<Esc>"
391 call assert_equal('one xtwoxx', getline(1))
392 let expected[0].col = 1
393 let expected[1].col = 6
394 call assert_equal(expected, prop_list(1))
395
396 call DeletePropTypes()
397 bwipe!
398 set bs&
399endfunc
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100400
Bram Moolenaar196d1572019-01-02 23:47:18 +0100401func Test_prop_replace()
402 new
403 set bs=2
404 let expected = SetupOneLine() " 'xonex xtwoxx'
405
406 exe "normal 0Ryyy\<Esc>"
407 call assert_equal('yyyex xtwoxx', getline(1))
408 call assert_equal(expected, prop_list(1))
409
410 exe "normal ftRyy\<BS>"
411 call assert_equal('yyyex xywoxx', getline(1))
412 call assert_equal(expected, prop_list(1))
413
414 exe "normal 0fwRyy\<BS>"
415 call assert_equal('yyyex xyyoxx', getline(1))
416 call assert_equal(expected, prop_list(1))
417
418 exe "normal 0foRyy\<BS>\<BS>"
419 call assert_equal('yyyex xyyoxx', getline(1))
420 call assert_equal(expected, prop_list(1))
421
422 call DeletePropTypes()
423 bwipe!
424 set bs&
425endfunc
426
Bram Moolenaar45dd07f2019-05-15 22:45:37 +0200427func Test_prop_open_line()
428 new
429
430 " open new line, props stay in top line
431 let expected = SetupOneLine() " 'xonex xtwoxx'
432 exe "normal o\<Esc>"
433 call assert_equal('xonex xtwoxx', getline(1))
434 call assert_equal('', getline(2))
435 call assert_equal(expected, prop_list(1))
436 call DeletePropTypes()
437
438 " move all props to next line
439 let expected = SetupOneLine() " 'xonex xtwoxx'
440 exe "normal 0i\<CR>\<Esc>"
441 call assert_equal('', getline(1))
442 call assert_equal('xonex xtwoxx', getline(2))
443 call assert_equal(expected, prop_list(2))
444 call DeletePropTypes()
445
446 " split just before prop, move all props to next line
447 let expected = SetupOneLine() " 'xonex xtwoxx'
448 exe "normal 0li\<CR>\<Esc>"
449 call assert_equal('x', getline(1))
450 call assert_equal('onex xtwoxx', getline(2))
451 let expected[0].col -= 1
452 let expected[1].col -= 1
453 call assert_equal(expected, prop_list(2))
454 call DeletePropTypes()
455
456 " split inside prop, split first prop
457 let expected = SetupOneLine() " 'xonex xtwoxx'
458 exe "normal 0lli\<CR>\<Esc>"
459 call assert_equal('xo', getline(1))
460 call assert_equal('nex xtwoxx', getline(2))
461 let exp_first = [deepcopy(expected[0])]
462 let exp_first[0].length = 1
463 call assert_equal(exp_first, prop_list(1))
464 let expected[0].col = 1
465 let expected[0].length = 2
466 let expected[1].col -= 2
467 call assert_equal(expected, prop_list(2))
468 call DeletePropTypes()
469
Bram Moolenaar5c65e6a2019-05-17 11:08:56 +0200470 " split just after first prop, second prop move to next line
Bram Moolenaar45dd07f2019-05-15 22:45:37 +0200471 let expected = SetupOneLine() " 'xonex xtwoxx'
472 exe "normal 0fea\<CR>\<Esc>"
473 call assert_equal('xone', getline(1))
474 call assert_equal('x xtwoxx', getline(2))
475 let exp_first = expected[0:0]
476 call assert_equal(exp_first, prop_list(1))
Bram Moolenaar5c65e6a2019-05-17 11:08:56 +0200477 let expected = expected[1:1]
478 let expected[0].col -= 4
Bram Moolenaar45dd07f2019-05-15 22:45:37 +0200479 call assert_equal(expected, prop_list(2))
480 call DeletePropTypes()
481
482 bwipe!
483 set bs&
484endfunc
485
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100486func Test_prop_clear()
487 new
488 call AddPropTypes()
489 call SetupPropsInFirstLine()
Bram Moolenaar4164bb22019-01-04 23:09:49 +0100490 call assert_equal(Get_expected_props(), prop_list(1))
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100491
Bram Moolenaara5a78822019-09-04 21:57:18 +0200492 eval 1->prop_clear()
493 call assert_equal([], 1->prop_list())
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100494
495 call DeletePropTypes()
496 bwipe!
497endfunc
498
499func Test_prop_clear_buf()
500 new
501 call AddPropTypes()
502 call SetupPropsInFirstLine()
503 let bufnr = bufnr('')
504 wincmd w
Bram Moolenaar4164bb22019-01-04 23:09:49 +0100505 call assert_equal(Get_expected_props(), prop_list(1, {'bufnr': bufnr}))
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100506
507 call prop_clear(1, 1, {'bufnr': bufnr})
508 call assert_equal([], prop_list(1, {'bufnr': bufnr}))
509
510 wincmd w
511 call DeletePropTypes()
512 bwipe!
513endfunc
514
Bram Moolenaar21b50382019-01-04 18:07:24 +0100515func Test_prop_setline()
516 new
517 call AddPropTypes()
518 call SetupPropsInFirstLine()
Bram Moolenaar4164bb22019-01-04 23:09:49 +0100519 call assert_equal(Get_expected_props(), prop_list(1))
Bram Moolenaar21b50382019-01-04 18:07:24 +0100520
521 call setline(1, 'foobar')
522 call assert_equal([], prop_list(1))
523
524 call DeletePropTypes()
525 bwipe!
526endfunc
527
528func Test_prop_setbufline()
529 new
530 call AddPropTypes()
531 call SetupPropsInFirstLine()
532 let bufnr = bufnr('')
533 wincmd w
Bram Moolenaar4164bb22019-01-04 23:09:49 +0100534 call assert_equal(Get_expected_props(), prop_list(1, {'bufnr': bufnr}))
Bram Moolenaar21b50382019-01-04 18:07:24 +0100535
536 call setbufline(bufnr, 1, 'foobar')
537 call assert_equal([], prop_list(1, {'bufnr': bufnr}))
538
539 wincmd w
540 call DeletePropTypes()
541 bwipe!
542endfunc
543
Bram Moolenaar4164bb22019-01-04 23:09:49 +0100544func Test_prop_substitute()
545 new
546 " Set first line to 'one two three'
547 call AddPropTypes()
548 call SetupPropsInFirstLine()
549 let expected_props = Get_expected_props()
550 call assert_equal(expected_props, prop_list(1))
551
552 " Change "n" in "one" to XX: 'oXXe two three'
553 s/n/XX/
554 let expected_props[0].length += 1
555 let expected_props[1].length += 1
556 let expected_props[2].col += 1
557 let expected_props[3].col += 1
558 call assert_equal(expected_props, prop_list(1))
559
560 " Delete "t" in "two" and "three" to XX: 'oXXe wo hree'
561 s/t//g
562 let expected_props[0].length -= 2
563 let expected_props[2].length -= 1
564 let expected_props[3].length -= 1
565 let expected_props[3].col -= 1
566 call assert_equal(expected_props, prop_list(1))
567
568 " Split the line by changing w to line break: 'oXXe ', 'o hree'
569 " The long prop is split and spans both lines.
570 " The props on "two" and "three" move to the next line.
571 s/w/\r/
572 let new_props = [
573 \ copy(expected_props[0]),
574 \ copy(expected_props[2]),
575 \ copy(expected_props[3]),
576 \ ]
577 let expected_props[0].length = 5
578 unlet expected_props[3]
579 unlet expected_props[2]
580 call assert_equal(expected_props, prop_list(1))
581
582 let new_props[0].length = 6
583 let new_props[1].col = 1
584 let new_props[1].length = 1
585 let new_props[2].col = 3
586 call assert_equal(new_props, prop_list(2))
587
588 call DeletePropTypes()
589 bwipe!
590endfunc
591
Bram Moolenaar663bc892019-01-08 23:07:24 +0100592func Test_prop_change_indent()
593 call prop_type_add('comment', {'highlight': 'Directory'})
594 new
595 call setline(1, [' xxx', 'yyyyy'])
596 call prop_add(2, 2, {'length': 2, 'type': 'comment'})
597 let expect = {'col': 2, 'length': 2, 'type': 'comment', 'start': 1, 'end': 1, 'id': 0}
598 call assert_equal([expect], prop_list(2))
599
600 set shiftwidth=3
601 normal 2G>>
602 call assert_equal(' yyyyy', getline(2))
603 let expect.col += 3
604 call assert_equal([expect], prop_list(2))
605
606 normal 2G==
607 call assert_equal(' yyyyy', getline(2))
608 let expect.col = 6
609 call assert_equal([expect], prop_list(2))
610
611 call prop_clear(2)
612 call prop_add(2, 2, {'length': 5, 'type': 'comment'})
613 let expect.col = 2
614 let expect.length = 5
615 call assert_equal([expect], prop_list(2))
616
617 normal 2G<<
618 call assert_equal(' yyyyy', getline(2))
619 let expect.length = 2
620 call assert_equal([expect], prop_list(2))
621
622 set shiftwidth&
623 call prop_type_delete('comment')
624endfunc
625
Bram Moolenaarc1a9bc12018-12-28 21:59:29 +0100626" Setup a three line prop in lines 2 - 4.
627" Add short props in line 1 and 5.
628func Setup_three_line_prop()
629 new
630 call setline(1, ['one', 'twotwo', 'three', 'fourfour', 'five'])
631 call prop_add(1, 2, {'length': 1, 'type': 'comment'})
632 call prop_add(2, 4, {'end_lnum': 4, 'end_col': 5, 'type': 'comment'})
633 call prop_add(5, 2, {'length': 1, 'type': 'comment'})
634endfunc
635
Bram Moolenaare3d31b02018-12-24 23:07:04 +0100636func Test_prop_multiline()
Bram Moolenaara5a78822019-09-04 21:57:18 +0200637 eval 'comment'->prop_type_add({'highlight': 'Directory'})
Bram Moolenaare3d31b02018-12-24 23:07:04 +0100638 new
639 call setline(1, ['xxxxxxx', 'yyyyyyyyy', 'zzzzzzzz'])
640
641 " start halfway line 1, end halfway line 3
642 call prop_add(1, 3, {'end_lnum': 3, 'end_col': 5, 'type': 'comment'})
643 let expect1 = {'col': 3, 'length': 6, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0}
644 call assert_equal([expect1], prop_list(1))
645 let expect2 = {'col': 1, 'length': 10, 'type': 'comment', 'start': 0, 'end': 0, 'id': 0}
646 call assert_equal([expect2], prop_list(2))
Bram Moolenaarb9c67a52019-01-01 19:49:20 +0100647 let expect3 = {'col': 1, 'length': 4, 'type': 'comment', 'start': 0, 'end': 1, 'id': 0}
Bram Moolenaare3d31b02018-12-24 23:07:04 +0100648 call assert_equal([expect3], prop_list(3))
649 call prop_clear(1, 3)
650
651 " include all three lines
652 call prop_add(1, 1, {'end_lnum': 3, 'end_col': 999, 'type': 'comment'})
653 let expect1.col = 1
654 let expect1.length = 8
655 call assert_equal([expect1], prop_list(1))
656 call assert_equal([expect2], prop_list(2))
657 let expect3.length = 9
658 call assert_equal([expect3], prop_list(3))
659 call prop_clear(1, 3)
660
661 bwipe!
Bram Moolenaarc1a9bc12018-12-28 21:59:29 +0100662
Bram Moolenaarb9c67a52019-01-01 19:49:20 +0100663 " Test deleting the first line of a multi-line prop.
Bram Moolenaarc1a9bc12018-12-28 21:59:29 +0100664 call Setup_three_line_prop()
Bram Moolenaarb9c67a52019-01-01 19:49:20 +0100665 let expect_short = {'col': 2, 'length': 1, 'type': 'comment', 'start': 1, 'end': 1, 'id': 0}
666 call assert_equal([expect_short], prop_list(1))
Bram Moolenaarc1a9bc12018-12-28 21:59:29 +0100667 let expect2 = {'col': 4, 'length': 4, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0}
668 call assert_equal([expect2], prop_list(2))
669 2del
Bram Moolenaarc1a9bc12018-12-28 21:59:29 +0100670 call assert_equal([expect_short], prop_list(1))
671 let expect2 = {'col': 1, 'length': 6, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0}
672 call assert_equal([expect2], prop_list(2))
673 bwipe!
674
Bram Moolenaarb9c67a52019-01-01 19:49:20 +0100675 " Test deleting the last line of a multi-line prop.
Bram Moolenaarc1a9bc12018-12-28 21:59:29 +0100676 call Setup_three_line_prop()
677 let expect3 = {'col': 1, 'length': 6, 'type': 'comment', 'start': 0, 'end': 0, 'id': 0}
678 call assert_equal([expect3], prop_list(3))
Bram Moolenaarb9c67a52019-01-01 19:49:20 +0100679 let expect4 = {'col': 1, 'length': 4, 'type': 'comment', 'start': 0, 'end': 1, 'id': 0}
Bram Moolenaarc1a9bc12018-12-28 21:59:29 +0100680 call assert_equal([expect4], prop_list(4))
681 4del
Bram Moolenaarb9c67a52019-01-01 19:49:20 +0100682 let expect3.end = 1
Bram Moolenaarc1a9bc12018-12-28 21:59:29 +0100683 call assert_equal([expect3], prop_list(3))
684 call assert_equal([expect_short], prop_list(4))
685 bwipe!
686
Bram Moolenaarb9c67a52019-01-01 19:49:20 +0100687 " Test appending a line below the multi-line text prop start.
Bram Moolenaarb56ac042018-12-28 23:22:40 +0100688 call Setup_three_line_prop()
689 let expect2 = {'col': 4, 'length': 4, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0}
690 call assert_equal([expect2], prop_list(2))
691 call append(2, "new line")
692 call assert_equal([expect2], prop_list(2))
693 let expect3 = {'col': 1, 'length': 9, 'type': 'comment', 'start': 0, 'end': 0, 'id': 0}
694 call assert_equal([expect3], prop_list(3))
695 bwipe!
696
Bram Moolenaare3d31b02018-12-24 23:07:04 +0100697 call prop_type_delete('comment')
698endfunc
699
Bram Moolenaar9df53b62020-01-13 20:40:51 +0100700func Test_prop_line2byte()
Bram Moolenaarb413d2e2018-12-25 23:15:46 +0100701 call prop_type_add('comment', {'highlight': 'Directory'})
702 new
Bram Moolenaar00b1e042018-12-26 23:42:10 +0100703 call setline(1, ['line1', 'second line', ''])
Bram Moolenaar8cf734e2018-12-26 01:09:00 +0100704 set ff=unix
Bram Moolenaar00b1e042018-12-26 23:42:10 +0100705 call assert_equal(19, line2byte(3))
Bram Moolenaarb413d2e2018-12-25 23:15:46 +0100706 call prop_add(1, 1, {'end_col': 3, 'type': 'comment'})
Bram Moolenaar00b1e042018-12-26 23:42:10 +0100707 call assert_equal(19, line2byte(3))
Bram Moolenaarb413d2e2018-12-25 23:15:46 +0100708
709 bwipe!
710 call prop_type_delete('comment')
711endfunc
712
Bram Moolenaar9df53b62020-01-13 20:40:51 +0100713func Test_prop_byte2line()
714 new
715 set ff=unix
716 call setline(1, ['one one', 'two two', 'three three', 'four four', 'five'])
717 call assert_equal(4, byte2line(line2byte(4)))
718 call assert_equal(5, byte2line(line2byte(5)))
719
720 call prop_type_add('prop', {'highlight': 'Directory'})
721 call prop_add(3, 1, {'length': 5, 'type': 'prop'})
722 call assert_equal(4, byte2line(line2byte(4)))
723 call assert_equal(5, byte2line(line2byte(5)))
724
725 bwipe!
726 call prop_type_delete('prop')
727endfunc
728
Bram Moolenaar7f1664e2019-01-04 17:21:24 +0100729func Test_prop_undo()
730 new
731 call prop_type_add('comment', {'highlight': 'Directory'})
732 call setline(1, ['oneone', 'twotwo', 'three'])
733 " Set 'undolevels' to break changes into undo-able pieces.
734 set ul&
735
736 call prop_add(1, 3, {'end_col': 5, 'type': 'comment'})
737 let expected = [{'col': 3, 'length': 2, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ]
738 call assert_equal(expected, prop_list(1))
739
740 " Insert a character, then undo.
741 exe "normal 0lllix\<Esc>"
742 set ul&
743 let expected[0].length = 3
744 call assert_equal(expected, prop_list(1))
745 undo
746 let expected[0].length = 2
747 call assert_equal(expected, prop_list(1))
748
749 " Delete a character, then undo
750 exe "normal 0lllx"
751 set ul&
752 let expected[0].length = 1
753 call assert_equal(expected, prop_list(1))
754 undo
755 let expected[0].length = 2
756 call assert_equal(expected, prop_list(1))
757
758 " Delete the line, then undo
759 1d
760 set ul&
761 call assert_equal([], prop_list(1))
762 undo
763 call assert_equal(expected, prop_list(1))
764
765 " Insert a character, delete two characters, then undo with "U"
766 exe "normal 0lllix\<Esc>"
767 set ul&
768 let expected[0].length = 3
769 call assert_equal(expected, prop_list(1))
770 exe "normal 0lllxx"
771 set ul&
772 let expected[0].length = 1
773 call assert_equal(expected, prop_list(1))
774 normal U
775 let expected[0].length = 2
776 call assert_equal(expected, prop_list(1))
777
Bram Moolenaar338dfda2019-05-19 15:19:57 +0200778 " substitute a word, then undo
779 call setline(1, 'the number 123 is highlighted.')
780 call prop_add(1, 12, {'length': 3, 'type': 'comment'})
781 let expected = [{'col': 12, 'length': 3, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ]
782 call assert_equal(expected, prop_list(1))
783 set ul&
784 1s/number/foo
785 let expected[0].col = 9
786 call assert_equal(expected, prop_list(1))
787 undo
788 let expected[0].col = 12
789 call assert_equal(expected, prop_list(1))
Bram Moolenaarf3333b02019-05-19 22:53:40 +0200790 call prop_clear(1)
791
792 " substitute with backslash
793 call setline(1, 'the number 123 is highlighted.')
794 call prop_add(1, 12, {'length': 3, 'type': 'comment'})
795 let expected = [{'col': 12, 'length': 3, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ]
796 call assert_equal(expected, prop_list(1))
797 1s/the/\The
798 call assert_equal(expected, prop_list(1))
799 1s/^/\\
800 let expected[0].col += 1
801 call assert_equal(expected, prop_list(1))
802 1s/^/\~
803 let expected[0].col += 1
804 call assert_equal(expected, prop_list(1))
805 1s/123/12\\3
806 let expected[0].length += 1
807 call assert_equal(expected, prop_list(1))
808 call prop_clear(1)
Bram Moolenaar338dfda2019-05-19 15:19:57 +0200809
Bram Moolenaar7f1664e2019-01-04 17:21:24 +0100810 bwipe!
811 call prop_type_delete('comment')
812endfunc
813
Bram Moolenaarecafcc12019-11-16 20:41:51 +0100814func Test_prop_delete_text()
815 new
816 call prop_type_add('comment', {'highlight': 'Directory'})
817 call setline(1, ['oneone', 'twotwo', 'three'])
818
819 " zero length property
820 call prop_add(1, 3, {'type': 'comment'})
821 let expected = [{'col': 3, 'length': 0, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ]
822 call assert_equal(expected, prop_list(1))
823
824 " delete one char moves the property
825 normal! x
826 let expected = [{'col': 2, 'length': 0, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ]
827 call assert_equal(expected, prop_list(1))
828
829 " delete char of the property has no effect
830 normal! lx
831 let expected = [{'col': 2, 'length': 0, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ]
832 call assert_equal(expected, prop_list(1))
833
834 " delete more chars moves property to first column, is not deleted
835 normal! 0xxxx
836 let expected = [{'col': 1, 'length': 0, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ]
837 call assert_equal(expected, prop_list(1))
838
839 bwipe!
840 call prop_type_delete('comment')
841endfunc
842
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +0100843" screenshot test with textprop highlighting
Bram Moolenaar8055d172019-05-17 22:57:26 +0200844func Test_textprop_screenshot_various()
Bram Moolenaar34390282019-10-16 14:38:26 +0200845 CheckScreendump
Bram Moolenaared79d1e2019-02-22 14:38:58 +0100846 " The Vim running in the terminal needs to use utf-8.
Bram Moolenaar34390282019-10-16 14:38:26 +0200847 if g:orig_encoding != 'utf-8'
848 throw 'Skipped: not using utf-8'
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +0100849 endif
850 call writefile([
Bram Moolenaarde24a872019-05-05 15:48:00 +0200851 \ "call setline(1, ["
852 \ .. "'One two',"
853 \ .. "'Numbér 123 änd thœn 4¾7.',"
854 \ .. "'--aa--bb--cc--dd--',"
855 \ .. "'// comment with error in it',"
Bram Moolenaar80e737c2019-05-17 19:56:34 +0200856 \ .. "'first line',"
857 \ .. "' second line ',"
858 \ .. "'third line',"
859 \ .. "' fourth line',"
Bram Moolenaarde24a872019-05-05 15:48:00 +0200860 \ .. "])",
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +0100861 \ "hi NumberProp ctermfg=blue",
862 \ "hi LongProp ctermbg=yellow",
Bram Moolenaarde24a872019-05-05 15:48:00 +0200863 \ "hi BackgroundProp ctermbg=lightgrey",
864 \ "hi UnderlineProp cterm=underline",
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +0100865 \ "call prop_type_add('number', {'highlight': 'NumberProp'})",
Bram Moolenaara5a78822019-09-04 21:57:18 +0200866 \ "call prop_type_add('long', {'highlight': 'NumberProp'})",
867 \ "call prop_type_change('long', {'highlight': 'LongProp'})",
Bram Moolenaar44746aa2019-01-02 00:02:11 +0100868 \ "call prop_type_add('start', {'highlight': 'NumberProp', 'start_incl': 1})",
869 \ "call prop_type_add('end', {'highlight': 'NumberProp', 'end_incl': 1})",
870 \ "call prop_type_add('both', {'highlight': 'NumberProp', 'start_incl': 1, 'end_incl': 1})",
Bram Moolenaardbd43162019-11-09 21:28:14 +0100871 \ "call prop_type_add('background', {'highlight': 'BackgroundProp', 'combine': 0})",
872 \ "call prop_type_add('backgroundcomb', {'highlight': 'NumberProp', 'combine': 1})",
873 \ "eval 'backgroundcomb'->prop_type_change({'highlight': 'BackgroundProp'})",
Bram Moolenaar58e32ab2019-11-12 22:44:22 +0100874 \ "call prop_type_add('error', {'highlight': 'UnderlineProp'})",
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +0100875 \ "call prop_add(1, 4, {'end_lnum': 3, 'end_col': 3, 'type': 'long'})",
Bram Moolenaarb9c67a52019-01-01 19:49:20 +0100876 \ "call prop_add(2, 9, {'length': 3, 'type': 'number'})",
877 \ "call prop_add(2, 24, {'length': 4, 'type': 'number'})",
Bram Moolenaar44746aa2019-01-02 00:02:11 +0100878 \ "call prop_add(3, 3, {'length': 2, 'type': 'number'})",
879 \ "call prop_add(3, 7, {'length': 2, 'type': 'start'})",
880 \ "call prop_add(3, 11, {'length': 2, 'type': 'end'})",
881 \ "call prop_add(3, 15, {'length': 2, 'type': 'both'})",
Bram Moolenaardbd43162019-11-09 21:28:14 +0100882 \ "call prop_add(4, 6, {'length': 3, 'type': 'background'})",
883 \ "call prop_add(4, 12, {'length': 10, 'type': 'backgroundcomb'})",
Bram Moolenaarde24a872019-05-05 15:48:00 +0200884 \ "call prop_add(4, 17, {'length': 5, 'type': 'error'})",
Bram Moolenaar80e737c2019-05-17 19:56:34 +0200885 \ "call prop_add(5, 7, {'length': 4, 'type': 'long'})",
886 \ "call prop_add(6, 1, {'length': 8, 'type': 'long'})",
887 \ "call prop_add(8, 1, {'length': 1, 'type': 'long'})",
888 \ "call prop_add(8, 11, {'length': 4, 'type': 'long'})",
Bram Moolenaarbfd45122019-05-17 13:05:07 +0200889 \ "set number cursorline",
Bram Moolenaarb9c67a52019-01-01 19:49:20 +0100890 \ "hi clear SpellBad",
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +0100891 \ "set spell",
Bram Moolenaarde24a872019-05-05 15:48:00 +0200892 \ "syn match Comment '//.*'",
893 \ "hi Comment ctermfg=green",
Bram Moolenaar44746aa2019-01-02 00:02:11 +0100894 \ "normal 3G0llix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>",
Bram Moolenaar33c8ca92019-01-02 18:00:27 +0100895 \ "normal 3G0lli\<BS>\<Esc>",
Bram Moolenaar80e737c2019-05-17 19:56:34 +0200896 \ "normal 6G0i\<BS>\<Esc>",
897 \ "normal 3J",
898 \ "normal 3G",
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +0100899 \], 'XtestProp')
Bram Moolenaar80e737c2019-05-17 19:56:34 +0200900 let buf = RunVimInTerminal('-S XtestProp', {'rows': 8})
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +0100901 call VerifyScreenDump(buf, 'Test_textprop_01', {})
Bram Moolenaare3d31b02018-12-24 23:07:04 +0100902
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +0100903 " clean up
904 call StopVimInTerminal(buf)
Bram Moolenaar2f21fa82018-12-31 20:05:56 +0100905 call delete('XtestProp')
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +0100906endfunc
Bram Moolenaar8055d172019-05-17 22:57:26 +0200907
908func RunTestVisualBlock(width, dump)
909 call writefile([
910 \ "call setline(1, ["
911 \ .. "'xxxxxxxxx 123 x',"
912 \ .. "'xxxxxxxx 123 x',"
913 \ .. "'xxxxxxx 123 x',"
914 \ .. "'xxxxxx 123 x',"
915 \ .. "'xxxxx 123 x',"
916 \ .. "'xxxx 123 xx',"
917 \ .. "'xxx 123 xxx',"
918 \ .. "'xx 123 xxxx',"
919 \ .. "'x 123 xxxxx',"
920 \ .. "' 123 xxxxxx',"
921 \ .. "])",
922 \ "hi SearchProp ctermbg=yellow",
923 \ "call prop_type_add('search', {'highlight': 'SearchProp'})",
924 \ "call prop_add(1, 11, {'length': 3, 'type': 'search'})",
925 \ "call prop_add(2, 10, {'length': 3, 'type': 'search'})",
926 \ "call prop_add(3, 9, {'length': 3, 'type': 'search'})",
927 \ "call prop_add(4, 8, {'length': 3, 'type': 'search'})",
928 \ "call prop_add(5, 7, {'length': 3, 'type': 'search'})",
929 \ "call prop_add(6, 6, {'length': 3, 'type': 'search'})",
930 \ "call prop_add(7, 5, {'length': 3, 'type': 'search'})",
931 \ "call prop_add(8, 4, {'length': 3, 'type': 'search'})",
932 \ "call prop_add(9, 3, {'length': 3, 'type': 'search'})",
933 \ "call prop_add(10, 2, {'length': 3, 'type': 'search'})",
934 \ "normal 1G6|\<C-V>" .. repeat('l', a:width - 1) .. "10jx",
935 \], 'XtestPropVis')
936 let buf = RunVimInTerminal('-S XtestPropVis', {'rows': 12})
937 call VerifyScreenDump(buf, 'Test_textprop_vis_' .. a:dump, {})
938
939 " clean up
940 call StopVimInTerminal(buf)
941 call delete('XtestPropVis')
942endfunc
943
944" screenshot test with Visual block mode operations
945func Test_textprop_screenshot_visual()
Bram Moolenaar34390282019-10-16 14:38:26 +0200946 CheckScreendump
Bram Moolenaar8055d172019-05-17 22:57:26 +0200947
948 " Delete two columns while text props are three chars wide.
949 call RunTestVisualBlock(2, '01')
950
951 " Same, but delete four columns
952 call RunTestVisualBlock(4, '02')
953endfunc
Bram Moolenaard79eef22019-05-24 20:41:55 +0200954
Bram Moolenaara956bf62019-06-19 17:34:24 +0200955func Test_textprop_after_tab()
Bram Moolenaar34390282019-10-16 14:38:26 +0200956 CheckScreendump
Bram Moolenaar37e66cf2019-06-19 18:16:10 +0200957
Bram Moolenaara956bf62019-06-19 17:34:24 +0200958 let lines =<< trim END
959 call setline(1, [
960 \ "\txxx",
961 \ "x\txxx",
962 \ ])
963 hi SearchProp ctermbg=yellow
964 call prop_type_add('search', {'highlight': 'SearchProp'})
965 call prop_add(1, 2, {'length': 3, 'type': 'search'})
966 call prop_add(2, 3, {'length': 3, 'type': 'search'})
967 END
968 call writefile(lines, 'XtestPropTab')
969 let buf = RunVimInTerminal('-S XtestPropTab', {'rows': 6})
970 call VerifyScreenDump(buf, 'Test_textprop_tab', {})
971
972 " clean up
973 call StopVimInTerminal(buf)
974 call delete('XtestPropTab')
975endfunc
976
Bram Moolenaar34390282019-10-16 14:38:26 +0200977func Test_textprop_with_syntax()
978 CheckScreendump
979
980 let lines =<< trim END
981 call setline(1, [
982 \ "(abc)",
983 \ ])
984 syn match csParens "[()]" display
985 hi! link csParens MatchParen
986
987 call prop_type_add('TPTitle', #{ highlight: 'Title' })
988 call prop_add(1, 2, #{type: 'TPTitle', end_col: 5})
989 END
990 call writefile(lines, 'XtestPropSyn')
991 let buf = RunVimInTerminal('-S XtestPropSyn', {'rows': 6})
992 call VerifyScreenDump(buf, 'Test_textprop_syn_1', {})
993
994 " clean up
995 call StopVimInTerminal(buf)
996 call delete('XtestPropSyn')
997endfunc
998
Bram Moolenaard79eef22019-05-24 20:41:55 +0200999" Adding a text property to a new buffer should not fail
1000func Test_textprop_empty_buffer()
1001 call prop_type_add('comment', {'highlight': 'Search'})
1002 new
1003 call prop_add(1, 1, {'type': 'comment'})
1004 close
Bram Moolenaaradfde112019-05-25 22:11:45 +02001005 call prop_type_delete('comment')
1006endfunc
1007
Bram Moolenaard74af422019-06-28 21:38:00 +02001008" Adding a text property with invalid highlight should be ignored.
1009func Test_textprop_invalid_highlight()
1010 call assert_fails("call prop_type_add('dni', {'highlight': 'DoesNotExist'})", 'E970:')
1011 new
1012 call setline(1, ['asdf','asdf'])
1013 call prop_add(1, 1, {'length': 4, 'type': 'dni'})
1014 redraw
1015 bwipe!
1016 call prop_type_delete('dni')
1017endfunc
1018
Bram Moolenaaradfde112019-05-25 22:11:45 +02001019" Adding a text property to an empty buffer and then editing another
1020func Test_textprop_empty_buffer_next()
1021 call prop_type_add("xxx", {})
1022 call prop_add(1, 1, {"type": "xxx"})
1023 next X
1024 call prop_type_delete('xxx')
Bram Moolenaard79eef22019-05-24 20:41:55 +02001025endfunc
Bram Moolenaarf0884c52019-05-24 21:22:29 +02001026
1027func Test_textprop_remove_from_buf()
1028 new
1029 let buf = bufnr('')
1030 call prop_type_add('one', {'bufnr': buf})
1031 call prop_add(1, 1, {'type': 'one', 'id': 234})
1032 file x
1033 edit y
1034 call prop_remove({'id': 234, 'bufnr': buf}, 1)
1035 call prop_type_delete('one', {'bufnr': buf})
1036 bwipe! x
1037 close
1038endfunc
Bram Moolenaar45311b52019-08-13 22:27:32 +02001039
1040func Test_textprop_in_unloaded_buf()
1041 edit Xaaa
1042 call setline(1, 'aaa')
1043 write
1044 edit Xbbb
1045 call setline(1, 'bbb')
1046 write
1047 let bnr = bufnr('')
1048 edit Xaaa
1049
1050 call prop_type_add('ErrorMsg', #{highlight:'ErrorMsg'})
1051 call assert_fails("call prop_add(1, 1, #{end_lnum: 1, endcol: 2, type: 'ErrorMsg', bufnr: bnr})", 'E275:')
1052 exe 'buf ' .. bnr
1053 call assert_equal('bbb', getline(1))
1054 call assert_equal(0, prop_list(1)->len())
1055
1056 bwipe! Xaaa
1057 bwipe! Xbbb
1058 cal delete('Xaaa')
1059 cal delete('Xbbb')
1060endfunc
Bram Moolenaar1fd30d72019-10-25 22:13:29 +02001061
1062func Test_proptype_substitute2()
1063 new
1064 " text_prop.vim
1065 call setline(1, [
1066 \ 'The num 123 is smaller than 4567.',
1067 \ '123 The number 123 is smaller than 4567.',
1068 \ '123 The number 123 is smaller than 4567.'])
1069
1070 call prop_type_add('number', {'highlight': 'ErrorMsg'})
1071
1072 call prop_add(1, 12, {'length': 3, 'type': 'number'})
1073 call prop_add(2, 1, {'length': 3, 'type': 'number'})
1074 call prop_add(3, 36, {'length': 4, 'type': 'number'})
1075 set ul&
1076 let expected = [{'id': 0, 'col': 13, 'end': 1, 'type': 'number', 'length': 3, 'start': 1},
1077 \ {'id': 0, 'col': 1, 'end': 1, 'type': 'number', 'length': 3, 'start': 1},
1078 \ {'id': 0, 'col': 50, 'end': 1, 'type': 'number', 'length': 4, 'start': 1}]
1079 " Add some text in between
1080 %s/\s\+/ /g
1081 call assert_equal(expected, prop_list(1) + prop_list(2) + prop_list(3))
1082
1083 " remove some text
1084 :1s/[a-z]\{3\}//g
1085 let expected = [{'id': 0, 'col': 10, 'end': 1, 'type': 'number', 'length': 3, 'start': 1}]
1086 call assert_equal(expected, prop_list(1))
1087 bwipe!
1088endfunc
Bram Moolenaar5cb0b932020-01-03 21:25:59 +01001089
Bram Moolenaarac15fd82020-01-09 21:35:48 +01001090func SaveOptions()
1091 let d = #{tabstop: &tabstop,
1092 \ softtabstop: &softtabstop,
1093 \ shiftwidth: &shiftwidth,
1094 \ expandtab: &expandtab,
1095 \ foldmethod: '"' .. &foldmethod .. '"',
1096 \ }
1097 return d
1098endfunc
1099
1100func RestoreOptions(dict)
1101 for name in keys(a:dict)
1102 exe 'let &' .. name .. ' = ' .. a:dict[name]
1103 endfor
1104endfunc
1105
Bram Moolenaar5cb0b932020-01-03 21:25:59 +01001106func Test_textprop_noexpandtab()
Bram Moolenaar5cb0b932020-01-03 21:25:59 +01001107 new
Bram Moolenaarac15fd82020-01-09 21:35:48 +01001108 let save_dict = SaveOptions()
1109
Bram Moolenaar5cb0b932020-01-03 21:25:59 +01001110 set tabstop=8
Bram Moolenaar5cb0b932020-01-03 21:25:59 +01001111 set softtabstop=4
Bram Moolenaar5cb0b932020-01-03 21:25:59 +01001112 set shiftwidth=4
Bram Moolenaar5cb0b932020-01-03 21:25:59 +01001113 set noexpandtab
Bram Moolenaar5cb0b932020-01-03 21:25:59 +01001114 set foldmethod=marker
Bram Moolenaarac15fd82020-01-09 21:35:48 +01001115
Bram Moolenaar5cb0b932020-01-03 21:25:59 +01001116 call feedkeys("\<esc>\<esc>0Ca\<cr>\<esc>\<up>", "tx")
1117 call prop_type_add('test', {'highlight': 'ErrorMsg'})
1118 call prop_add(1, 1, {'end_col': 2, 'type': 'test'})
1119 call feedkeys("0i\<tab>", "tx")
1120 call prop_remove({'type': 'test'})
1121 call prop_add(1, 2, {'end_col': 3, 'type': 'test'})
1122 call feedkeys("A\<left>\<tab>", "tx")
1123 call prop_remove({'type': 'test'})
1124 try
1125 " It is correct that this does not pass
1126 call prop_add(1, 6, {'end_col': 7, 'type': 'test'})
1127 " Has already collapsed here, start_col:6 does not result in an error
1128 call feedkeys("A\<left>\<tab>", "tx")
1129 catch /^Vim\%((\a\+)\)\=:E964/
1130 endtry
1131 call prop_remove({'type': 'test'})
Bram Moolenaarac15fd82020-01-09 21:35:48 +01001132 call prop_type_delete('test')
1133
1134 call RestoreOptions(save_dict)
1135 bwipe!
1136endfunc
1137
1138func Test_textprop_noexpandtab_redraw()
1139 new
1140 let save_dict = SaveOptions()
1141
1142 set tabstop=8
1143 set softtabstop=4
1144 set shiftwidth=4
1145 set noexpandtab
1146 set foldmethod=marker
1147
1148 call feedkeys("\<esc>\<esc>0Ca\<cr>\<space>\<esc>\<up>", "tx")
1149 call prop_type_add('test', {'highlight': 'ErrorMsg'})
1150 call prop_add(1, 1, {'end_col': 2, 'type': 'test'})
1151 call feedkeys("0i\<tab>", "tx")
1152 " Internally broken at the next line
1153 call feedkeys("A\<left>\<tab>", "tx")
1154 redraw
1155 " Index calculation failed internally on next line
1156 call prop_add(1, 1, {'end_col': 2, 'type': 'test'})
1157 call prop_remove({'type': 'test', 'all': v:true})
1158 call prop_type_delete('test')
1159 call prop_type_delete('test')
1160
1161 call RestoreOptions(save_dict)
1162 bwipe!
1163endfunc
1164
1165func Test_textprop_ins_str()
1166 new
1167 call setline(1, 'just some text')
1168 call prop_type_add('test', {'highlight': 'ErrorMsg'})
1169 call prop_add(1, 1, {'end_col': 2, 'type': 'test'})
1170 call assert_equal([{'id': 0, 'col': 1, 'end': 1, 'type': 'test', 'length': 1, 'start': 1}], prop_list(1))
1171
1172 call feedkeys("foi\<F8>\<Esc>", "tx")
1173 call assert_equal('just s<F8>ome text', getline(1))
1174 call assert_equal([{'id': 0, 'col': 1, 'end': 1, 'type': 'test', 'length': 1, 'start': 1}], prop_list(1))
1175
1176 bwipe!
1177 call prop_remove({'type': 'test'})
1178 call prop_type_delete('test')
Bram Moolenaar5cb0b932020-01-03 21:25:59 +01001179endfunc
Bram Moolenaar66b98852020-03-11 19:15:52 +01001180
1181func Test_find_prop_later_in_line()
1182 new
1183 call prop_type_add('test', {'highlight': 'ErrorMsg'})
1184 call setline(1, 'just some text')
1185 call prop_add(1, 1, {'length': 4, 'type': 'test'})
1186 call prop_add(1, 10, {'length': 3, 'type': 'test'})
1187
1188 call assert_equal({'id': 0, 'lnum': 1, 'col': 10, 'end': 1, 'type': 'test', 'length': 3, 'start': 1},
1189 \ prop_find(#{type: 'test', lnum: 1, col: 6}))
1190
1191 bwipe!
1192 call prop_type_delete('test')
1193endfunc
1194
1195func Test_find_zerowidth_prop_sol()
1196 new
1197 call prop_type_add('test', {'highlight': 'ErrorMsg'})
1198 call setline(1, 'just some text')
1199 call prop_add(1, 1, {'length': 0, 'type': 'test'})
1200
1201 call assert_equal({'id': 0, 'lnum': 1, 'col': 1, 'end': 1, 'type': 'test', 'length': 0, 'start': 1},
1202 \ prop_find(#{type: 'test', lnum: 1}))
1203
1204 bwipe!
1205 call prop_type_delete('test')
1206endfunc
Bram Moolenaar99fa7212020-04-26 15:59:55 +02001207
1208" Test for passing invalid arguments to prop_xxx() functions
1209func Test_prop_func_invalid_args()
1210 call assert_fails('call prop_clear(1, 2, [])', 'E715:')
1211 call assert_fails('call prop_clear(-1, 2)', 'E16:')
1212 call assert_fails('call prop_find(test_null_dict())', 'E474:')
1213 call assert_fails('call prop_find({"bufnr" : []})', 'E158:')
1214 call assert_fails('call prop_find({})', 'E968:')
1215 call assert_fails('call prop_find({}, "x")', 'E474:')
1216 call assert_fails('call prop_find({"lnum" : -2})', 'E16:')
1217 call assert_fails('call prop_list(1, [])', 'E715:')
1218 call assert_fails('call prop_list(-1 , {})', 'E16:')
1219 call assert_fails('call prop_remove([])', 'E474:')
1220 call assert_fails('call prop_remove({}, -2)', 'E16:')
1221 call assert_fails('call prop_remove({})', 'E968:')
1222 call assert_fails('call prop_type_add([], {})', 'E474:')
1223 call assert_fails("call prop_type_change('long', {'xyz' : 10})", 'E971:')
1224 call assert_fails("call prop_type_delete([])", 'E474:')
1225 call assert_fails("call prop_type_delete('xyz', [])", 'E715:')
1226 call assert_fails("call prop_type_get([])", 'E474:')
1227 call assert_fails("call prop_type_get('', [])", 'E474:')
1228 call assert_fails("call prop_type_list([])", 'E715:')
1229endfunc
1230
1231" vim: shiftwidth=2 sts=2 expandtab