blob: 5dddd16910196292f46aefeee5f752d362c24224 [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
Bram Moolenaar87be9be2020-05-30 15:32:02 +0200463 let exp_first[0].end = 0
Bram Moolenaar45dd07f2019-05-15 22:45:37 +0200464 call assert_equal(exp_first, prop_list(1))
465 let expected[0].col = 1
466 let expected[0].length = 2
Bram Moolenaar87be9be2020-05-30 15:32:02 +0200467 let expected[0].start = 0
Bram Moolenaar45dd07f2019-05-15 22:45:37 +0200468 let expected[1].col -= 2
469 call assert_equal(expected, prop_list(2))
470 call DeletePropTypes()
471
Bram Moolenaar5c65e6a2019-05-17 11:08:56 +0200472 " split just after first prop, second prop move to next line
Bram Moolenaar45dd07f2019-05-15 22:45:37 +0200473 let expected = SetupOneLine() " 'xonex xtwoxx'
474 exe "normal 0fea\<CR>\<Esc>"
475 call assert_equal('xone', getline(1))
476 call assert_equal('x xtwoxx', getline(2))
477 let exp_first = expected[0:0]
478 call assert_equal(exp_first, prop_list(1))
Bram Moolenaar5c65e6a2019-05-17 11:08:56 +0200479 let expected = expected[1:1]
480 let expected[0].col -= 4
Bram Moolenaar45dd07f2019-05-15 22:45:37 +0200481 call assert_equal(expected, prop_list(2))
482 call DeletePropTypes()
483
484 bwipe!
485 set bs&
486endfunc
487
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100488func Test_prop_clear()
489 new
490 call AddPropTypes()
491 call SetupPropsInFirstLine()
Bram Moolenaar4164bb22019-01-04 23:09:49 +0100492 call assert_equal(Get_expected_props(), prop_list(1))
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100493
Bram Moolenaara5a78822019-09-04 21:57:18 +0200494 eval 1->prop_clear()
495 call assert_equal([], 1->prop_list())
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100496
497 call DeletePropTypes()
498 bwipe!
499endfunc
500
501func Test_prop_clear_buf()
502 new
503 call AddPropTypes()
504 call SetupPropsInFirstLine()
505 let bufnr = bufnr('')
506 wincmd w
Bram Moolenaar4164bb22019-01-04 23:09:49 +0100507 call assert_equal(Get_expected_props(), prop_list(1, {'bufnr': bufnr}))
Bram Moolenaar98aefe72018-12-13 22:20:09 +0100508
509 call prop_clear(1, 1, {'bufnr': bufnr})
510 call assert_equal([], prop_list(1, {'bufnr': bufnr}))
511
512 wincmd w
513 call DeletePropTypes()
514 bwipe!
515endfunc
516
Bram Moolenaar21b50382019-01-04 18:07:24 +0100517func Test_prop_setline()
518 new
519 call AddPropTypes()
520 call SetupPropsInFirstLine()
Bram Moolenaar4164bb22019-01-04 23:09:49 +0100521 call assert_equal(Get_expected_props(), prop_list(1))
Bram Moolenaar21b50382019-01-04 18:07:24 +0100522
523 call setline(1, 'foobar')
524 call assert_equal([], prop_list(1))
525
526 call DeletePropTypes()
527 bwipe!
528endfunc
529
530func Test_prop_setbufline()
531 new
532 call AddPropTypes()
533 call SetupPropsInFirstLine()
534 let bufnr = bufnr('')
535 wincmd w
Bram Moolenaar4164bb22019-01-04 23:09:49 +0100536 call assert_equal(Get_expected_props(), prop_list(1, {'bufnr': bufnr}))
Bram Moolenaar21b50382019-01-04 18:07:24 +0100537
538 call setbufline(bufnr, 1, 'foobar')
539 call assert_equal([], prop_list(1, {'bufnr': bufnr}))
540
541 wincmd w
542 call DeletePropTypes()
543 bwipe!
544endfunc
545
Bram Moolenaar4164bb22019-01-04 23:09:49 +0100546func Test_prop_substitute()
547 new
548 " Set first line to 'one two three'
549 call AddPropTypes()
550 call SetupPropsInFirstLine()
551 let expected_props = Get_expected_props()
552 call assert_equal(expected_props, prop_list(1))
553
554 " Change "n" in "one" to XX: 'oXXe two three'
555 s/n/XX/
556 let expected_props[0].length += 1
557 let expected_props[1].length += 1
558 let expected_props[2].col += 1
559 let expected_props[3].col += 1
560 call assert_equal(expected_props, prop_list(1))
561
562 " Delete "t" in "two" and "three" to XX: 'oXXe wo hree'
563 s/t//g
564 let expected_props[0].length -= 2
565 let expected_props[2].length -= 1
566 let expected_props[3].length -= 1
567 let expected_props[3].col -= 1
568 call assert_equal(expected_props, prop_list(1))
569
570 " Split the line by changing w to line break: 'oXXe ', 'o hree'
571 " The long prop is split and spans both lines.
572 " The props on "two" and "three" move to the next line.
573 s/w/\r/
574 let new_props = [
575 \ copy(expected_props[0]),
576 \ copy(expected_props[2]),
577 \ copy(expected_props[3]),
578 \ ]
579 let expected_props[0].length = 5
Bram Moolenaar87be9be2020-05-30 15:32:02 +0200580 let expected_props[0].end = 0
Bram Moolenaar4164bb22019-01-04 23:09:49 +0100581 unlet expected_props[3]
582 unlet expected_props[2]
583 call assert_equal(expected_props, prop_list(1))
584
585 let new_props[0].length = 6
Bram Moolenaar87be9be2020-05-30 15:32:02 +0200586 let new_props[0].start = 0
Bram Moolenaar4164bb22019-01-04 23:09:49 +0100587 let new_props[1].col = 1
588 let new_props[1].length = 1
589 let new_props[2].col = 3
590 call assert_equal(new_props, prop_list(2))
591
592 call DeletePropTypes()
593 bwipe!
594endfunc
595
Bram Moolenaar663bc892019-01-08 23:07:24 +0100596func Test_prop_change_indent()
597 call prop_type_add('comment', {'highlight': 'Directory'})
598 new
599 call setline(1, [' xxx', 'yyyyy'])
600 call prop_add(2, 2, {'length': 2, 'type': 'comment'})
601 let expect = {'col': 2, 'length': 2, 'type': 'comment', 'start': 1, 'end': 1, 'id': 0}
602 call assert_equal([expect], prop_list(2))
603
604 set shiftwidth=3
605 normal 2G>>
606 call assert_equal(' yyyyy', getline(2))
607 let expect.col += 3
608 call assert_equal([expect], prop_list(2))
609
610 normal 2G==
611 call assert_equal(' yyyyy', getline(2))
612 let expect.col = 6
613 call assert_equal([expect], prop_list(2))
614
615 call prop_clear(2)
616 call prop_add(2, 2, {'length': 5, 'type': 'comment'})
617 let expect.col = 2
618 let expect.length = 5
619 call assert_equal([expect], prop_list(2))
620
621 normal 2G<<
622 call assert_equal(' yyyyy', getline(2))
623 let expect.length = 2
624 call assert_equal([expect], prop_list(2))
625
626 set shiftwidth&
627 call prop_type_delete('comment')
628endfunc
629
Bram Moolenaarc1a9bc12018-12-28 21:59:29 +0100630" Setup a three line prop in lines 2 - 4.
631" Add short props in line 1 and 5.
632func Setup_three_line_prop()
633 new
634 call setline(1, ['one', 'twotwo', 'three', 'fourfour', 'five'])
635 call prop_add(1, 2, {'length': 1, 'type': 'comment'})
636 call prop_add(2, 4, {'end_lnum': 4, 'end_col': 5, 'type': 'comment'})
637 call prop_add(5, 2, {'length': 1, 'type': 'comment'})
638endfunc
639
Bram Moolenaare3d31b02018-12-24 23:07:04 +0100640func Test_prop_multiline()
Bram Moolenaara5a78822019-09-04 21:57:18 +0200641 eval 'comment'->prop_type_add({'highlight': 'Directory'})
Bram Moolenaare3d31b02018-12-24 23:07:04 +0100642 new
643 call setline(1, ['xxxxxxx', 'yyyyyyyyy', 'zzzzzzzz'])
644
645 " start halfway line 1, end halfway line 3
646 call prop_add(1, 3, {'end_lnum': 3, 'end_col': 5, 'type': 'comment'})
647 let expect1 = {'col': 3, 'length': 6, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0}
648 call assert_equal([expect1], prop_list(1))
649 let expect2 = {'col': 1, 'length': 10, 'type': 'comment', 'start': 0, 'end': 0, 'id': 0}
650 call assert_equal([expect2], prop_list(2))
Bram Moolenaarb9c67a52019-01-01 19:49:20 +0100651 let expect3 = {'col': 1, 'length': 4, 'type': 'comment', 'start': 0, 'end': 1, 'id': 0}
Bram Moolenaare3d31b02018-12-24 23:07:04 +0100652 call assert_equal([expect3], prop_list(3))
653 call prop_clear(1, 3)
654
655 " include all three lines
656 call prop_add(1, 1, {'end_lnum': 3, 'end_col': 999, 'type': 'comment'})
657 let expect1.col = 1
658 let expect1.length = 8
659 call assert_equal([expect1], prop_list(1))
660 call assert_equal([expect2], prop_list(2))
661 let expect3.length = 9
662 call assert_equal([expect3], prop_list(3))
663 call prop_clear(1, 3)
664
665 bwipe!
Bram Moolenaarc1a9bc12018-12-28 21:59:29 +0100666
Bram Moolenaarb9c67a52019-01-01 19:49:20 +0100667 " Test deleting the first line of a multi-line prop.
Bram Moolenaarc1a9bc12018-12-28 21:59:29 +0100668 call Setup_three_line_prop()
Bram Moolenaarb9c67a52019-01-01 19:49:20 +0100669 let expect_short = {'col': 2, 'length': 1, 'type': 'comment', 'start': 1, 'end': 1, 'id': 0}
670 call assert_equal([expect_short], prop_list(1))
Bram Moolenaarc1a9bc12018-12-28 21:59:29 +0100671 let expect2 = {'col': 4, 'length': 4, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0}
672 call assert_equal([expect2], prop_list(2))
673 2del
Bram Moolenaarc1a9bc12018-12-28 21:59:29 +0100674 call assert_equal([expect_short], prop_list(1))
675 let expect2 = {'col': 1, 'length': 6, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0}
676 call assert_equal([expect2], prop_list(2))
677 bwipe!
678
Bram Moolenaarb9c67a52019-01-01 19:49:20 +0100679 " Test deleting the last line of a multi-line prop.
Bram Moolenaarc1a9bc12018-12-28 21:59:29 +0100680 call Setup_three_line_prop()
681 let expect3 = {'col': 1, 'length': 6, 'type': 'comment', 'start': 0, 'end': 0, 'id': 0}
682 call assert_equal([expect3], prop_list(3))
Bram Moolenaarb9c67a52019-01-01 19:49:20 +0100683 let expect4 = {'col': 1, 'length': 4, 'type': 'comment', 'start': 0, 'end': 1, 'id': 0}
Bram Moolenaarc1a9bc12018-12-28 21:59:29 +0100684 call assert_equal([expect4], prop_list(4))
685 4del
Bram Moolenaarb9c67a52019-01-01 19:49:20 +0100686 let expect3.end = 1
Bram Moolenaarc1a9bc12018-12-28 21:59:29 +0100687 call assert_equal([expect3], prop_list(3))
688 call assert_equal([expect_short], prop_list(4))
689 bwipe!
690
Bram Moolenaarb9c67a52019-01-01 19:49:20 +0100691 " Test appending a line below the multi-line text prop start.
Bram Moolenaarb56ac042018-12-28 23:22:40 +0100692 call Setup_three_line_prop()
693 let expect2 = {'col': 4, 'length': 4, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0}
694 call assert_equal([expect2], prop_list(2))
695 call append(2, "new line")
696 call assert_equal([expect2], prop_list(2))
697 let expect3 = {'col': 1, 'length': 9, 'type': 'comment', 'start': 0, 'end': 0, 'id': 0}
698 call assert_equal([expect3], prop_list(3))
699 bwipe!
700
Bram Moolenaare3d31b02018-12-24 23:07:04 +0100701 call prop_type_delete('comment')
702endfunc
703
Bram Moolenaar9df53b62020-01-13 20:40:51 +0100704func Test_prop_line2byte()
Bram Moolenaarb413d2e2018-12-25 23:15:46 +0100705 call prop_type_add('comment', {'highlight': 'Directory'})
706 new
Bram Moolenaar00b1e042018-12-26 23:42:10 +0100707 call setline(1, ['line1', 'second line', ''])
Bram Moolenaar8cf734e2018-12-26 01:09:00 +0100708 set ff=unix
Bram Moolenaar00b1e042018-12-26 23:42:10 +0100709 call assert_equal(19, line2byte(3))
Bram Moolenaarb413d2e2018-12-25 23:15:46 +0100710 call prop_add(1, 1, {'end_col': 3, 'type': 'comment'})
Bram Moolenaar00b1e042018-12-26 23:42:10 +0100711 call assert_equal(19, line2byte(3))
Bram Moolenaarb413d2e2018-12-25 23:15:46 +0100712
713 bwipe!
714 call prop_type_delete('comment')
715endfunc
716
Bram Moolenaar9df53b62020-01-13 20:40:51 +0100717func Test_prop_byte2line()
718 new
719 set ff=unix
720 call setline(1, ['one one', 'two two', 'three three', 'four four', 'five'])
721 call assert_equal(4, byte2line(line2byte(4)))
722 call assert_equal(5, byte2line(line2byte(5)))
723
724 call prop_type_add('prop', {'highlight': 'Directory'})
725 call prop_add(3, 1, {'length': 5, 'type': 'prop'})
726 call assert_equal(4, byte2line(line2byte(4)))
727 call assert_equal(5, byte2line(line2byte(5)))
728
729 bwipe!
730 call prop_type_delete('prop')
731endfunc
732
Bram Moolenaar7f1664e2019-01-04 17:21:24 +0100733func Test_prop_undo()
734 new
735 call prop_type_add('comment', {'highlight': 'Directory'})
736 call setline(1, ['oneone', 'twotwo', 'three'])
737 " Set 'undolevels' to break changes into undo-able pieces.
738 set ul&
739
740 call prop_add(1, 3, {'end_col': 5, 'type': 'comment'})
741 let expected = [{'col': 3, 'length': 2, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ]
742 call assert_equal(expected, prop_list(1))
743
744 " Insert a character, then undo.
745 exe "normal 0lllix\<Esc>"
746 set ul&
747 let expected[0].length = 3
748 call assert_equal(expected, prop_list(1))
749 undo
750 let expected[0].length = 2
751 call assert_equal(expected, prop_list(1))
752
753 " Delete a character, then undo
754 exe "normal 0lllx"
755 set ul&
756 let expected[0].length = 1
757 call assert_equal(expected, prop_list(1))
758 undo
759 let expected[0].length = 2
760 call assert_equal(expected, prop_list(1))
761
762 " Delete the line, then undo
763 1d
764 set ul&
765 call assert_equal([], prop_list(1))
766 undo
767 call assert_equal(expected, prop_list(1))
768
769 " Insert a character, delete two characters, then undo with "U"
770 exe "normal 0lllix\<Esc>"
771 set ul&
772 let expected[0].length = 3
773 call assert_equal(expected, prop_list(1))
774 exe "normal 0lllxx"
775 set ul&
776 let expected[0].length = 1
777 call assert_equal(expected, prop_list(1))
778 normal U
779 let expected[0].length = 2
780 call assert_equal(expected, prop_list(1))
781
Bram Moolenaar338dfda2019-05-19 15:19:57 +0200782 " substitute a word, then undo
783 call setline(1, 'the number 123 is highlighted.')
784 call prop_add(1, 12, {'length': 3, 'type': 'comment'})
785 let expected = [{'col': 12, 'length': 3, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ]
786 call assert_equal(expected, prop_list(1))
787 set ul&
788 1s/number/foo
789 let expected[0].col = 9
790 call assert_equal(expected, prop_list(1))
791 undo
792 let expected[0].col = 12
793 call assert_equal(expected, prop_list(1))
Bram Moolenaarf3333b02019-05-19 22:53:40 +0200794 call prop_clear(1)
795
796 " substitute with backslash
797 call setline(1, 'the number 123 is highlighted.')
798 call prop_add(1, 12, {'length': 3, 'type': 'comment'})
799 let expected = [{'col': 12, 'length': 3, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ]
800 call assert_equal(expected, prop_list(1))
801 1s/the/\The
802 call assert_equal(expected, prop_list(1))
803 1s/^/\\
804 let expected[0].col += 1
805 call assert_equal(expected, prop_list(1))
806 1s/^/\~
807 let expected[0].col += 1
808 call assert_equal(expected, prop_list(1))
809 1s/123/12\\3
810 let expected[0].length += 1
811 call assert_equal(expected, prop_list(1))
812 call prop_clear(1)
Bram Moolenaar338dfda2019-05-19 15:19:57 +0200813
Bram Moolenaar7f1664e2019-01-04 17:21:24 +0100814 bwipe!
815 call prop_type_delete('comment')
816endfunc
817
Bram Moolenaarecafcc12019-11-16 20:41:51 +0100818func Test_prop_delete_text()
819 new
820 call prop_type_add('comment', {'highlight': 'Directory'})
821 call setline(1, ['oneone', 'twotwo', 'three'])
822
823 " zero length property
824 call prop_add(1, 3, {'type': 'comment'})
825 let expected = [{'col': 3, 'length': 0, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ]
826 call assert_equal(expected, prop_list(1))
827
828 " delete one char moves the property
829 normal! x
830 let expected = [{'col': 2, 'length': 0, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ]
831 call assert_equal(expected, prop_list(1))
832
833 " delete char of the property has no effect
834 normal! lx
835 let expected = [{'col': 2, 'length': 0, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ]
836 call assert_equal(expected, prop_list(1))
837
838 " delete more chars moves property to first column, is not deleted
839 normal! 0xxxx
840 let expected = [{'col': 1, 'length': 0, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ]
841 call assert_equal(expected, prop_list(1))
842
843 bwipe!
844 call prop_type_delete('comment')
845endfunc
846
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +0100847" screenshot test with textprop highlighting
Bram Moolenaar8055d172019-05-17 22:57:26 +0200848func Test_textprop_screenshot_various()
Bram Moolenaar34390282019-10-16 14:38:26 +0200849 CheckScreendump
Bram Moolenaared79d1e2019-02-22 14:38:58 +0100850 " The Vim running in the terminal needs to use utf-8.
Bram Moolenaar34390282019-10-16 14:38:26 +0200851 if g:orig_encoding != 'utf-8'
852 throw 'Skipped: not using utf-8'
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +0100853 endif
854 call writefile([
Bram Moolenaarde24a872019-05-05 15:48:00 +0200855 \ "call setline(1, ["
856 \ .. "'One two',"
857 \ .. "'Numbér 123 änd thœn 4¾7.',"
858 \ .. "'--aa--bb--cc--dd--',"
859 \ .. "'// comment with error in it',"
Bram Moolenaar80e737c2019-05-17 19:56:34 +0200860 \ .. "'first line',"
861 \ .. "' second line ',"
862 \ .. "'third line',"
863 \ .. "' fourth line',"
Bram Moolenaarde24a872019-05-05 15:48:00 +0200864 \ .. "])",
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +0100865 \ "hi NumberProp ctermfg=blue",
866 \ "hi LongProp ctermbg=yellow",
Bram Moolenaarde24a872019-05-05 15:48:00 +0200867 \ "hi BackgroundProp ctermbg=lightgrey",
868 \ "hi UnderlineProp cterm=underline",
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +0100869 \ "call prop_type_add('number', {'highlight': 'NumberProp'})",
Bram Moolenaara5a78822019-09-04 21:57:18 +0200870 \ "call prop_type_add('long', {'highlight': 'NumberProp'})",
871 \ "call prop_type_change('long', {'highlight': 'LongProp'})",
Bram Moolenaar44746aa2019-01-02 00:02:11 +0100872 \ "call prop_type_add('start', {'highlight': 'NumberProp', 'start_incl': 1})",
873 \ "call prop_type_add('end', {'highlight': 'NumberProp', 'end_incl': 1})",
874 \ "call prop_type_add('both', {'highlight': 'NumberProp', 'start_incl': 1, 'end_incl': 1})",
Bram Moolenaardbd43162019-11-09 21:28:14 +0100875 \ "call prop_type_add('background', {'highlight': 'BackgroundProp', 'combine': 0})",
876 \ "call prop_type_add('backgroundcomb', {'highlight': 'NumberProp', 'combine': 1})",
877 \ "eval 'backgroundcomb'->prop_type_change({'highlight': 'BackgroundProp'})",
Bram Moolenaar58e32ab2019-11-12 22:44:22 +0100878 \ "call prop_type_add('error', {'highlight': 'UnderlineProp'})",
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +0100879 \ "call prop_add(1, 4, {'end_lnum': 3, 'end_col': 3, 'type': 'long'})",
Bram Moolenaarb9c67a52019-01-01 19:49:20 +0100880 \ "call prop_add(2, 9, {'length': 3, 'type': 'number'})",
881 \ "call prop_add(2, 24, {'length': 4, 'type': 'number'})",
Bram Moolenaar44746aa2019-01-02 00:02:11 +0100882 \ "call prop_add(3, 3, {'length': 2, 'type': 'number'})",
883 \ "call prop_add(3, 7, {'length': 2, 'type': 'start'})",
884 \ "call prop_add(3, 11, {'length': 2, 'type': 'end'})",
885 \ "call prop_add(3, 15, {'length': 2, 'type': 'both'})",
Bram Moolenaardbd43162019-11-09 21:28:14 +0100886 \ "call prop_add(4, 6, {'length': 3, 'type': 'background'})",
887 \ "call prop_add(4, 12, {'length': 10, 'type': 'backgroundcomb'})",
Bram Moolenaarde24a872019-05-05 15:48:00 +0200888 \ "call prop_add(4, 17, {'length': 5, 'type': 'error'})",
Bram Moolenaar80e737c2019-05-17 19:56:34 +0200889 \ "call prop_add(5, 7, {'length': 4, 'type': 'long'})",
890 \ "call prop_add(6, 1, {'length': 8, 'type': 'long'})",
891 \ "call prop_add(8, 1, {'length': 1, 'type': 'long'})",
892 \ "call prop_add(8, 11, {'length': 4, 'type': 'long'})",
Bram Moolenaarbfd45122019-05-17 13:05:07 +0200893 \ "set number cursorline",
Bram Moolenaarb9c67a52019-01-01 19:49:20 +0100894 \ "hi clear SpellBad",
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +0100895 \ "set spell",
Bram Moolenaarde24a872019-05-05 15:48:00 +0200896 \ "syn match Comment '//.*'",
897 \ "hi Comment ctermfg=green",
Bram Moolenaar44746aa2019-01-02 00:02:11 +0100898 \ "normal 3G0llix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>",
Bram Moolenaar33c8ca92019-01-02 18:00:27 +0100899 \ "normal 3G0lli\<BS>\<Esc>",
Bram Moolenaar80e737c2019-05-17 19:56:34 +0200900 \ "normal 6G0i\<BS>\<Esc>",
901 \ "normal 3J",
902 \ "normal 3G",
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +0100903 \], 'XtestProp')
Bram Moolenaar80e737c2019-05-17 19:56:34 +0200904 let buf = RunVimInTerminal('-S XtestProp', {'rows': 8})
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +0100905 call VerifyScreenDump(buf, 'Test_textprop_01', {})
Bram Moolenaare3d31b02018-12-24 23:07:04 +0100906
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +0100907 " clean up
908 call StopVimInTerminal(buf)
Bram Moolenaar2f21fa82018-12-31 20:05:56 +0100909 call delete('XtestProp')
Bram Moolenaarc6d86dc2018-12-31 13:57:36 +0100910endfunc
Bram Moolenaar8055d172019-05-17 22:57:26 +0200911
912func RunTestVisualBlock(width, dump)
913 call writefile([
914 \ "call setline(1, ["
915 \ .. "'xxxxxxxxx 123 x',"
916 \ .. "'xxxxxxxx 123 x',"
917 \ .. "'xxxxxxx 123 x',"
918 \ .. "'xxxxxx 123 x',"
919 \ .. "'xxxxx 123 x',"
920 \ .. "'xxxx 123 xx',"
921 \ .. "'xxx 123 xxx',"
922 \ .. "'xx 123 xxxx',"
923 \ .. "'x 123 xxxxx',"
924 \ .. "' 123 xxxxxx',"
925 \ .. "])",
926 \ "hi SearchProp ctermbg=yellow",
927 \ "call prop_type_add('search', {'highlight': 'SearchProp'})",
928 \ "call prop_add(1, 11, {'length': 3, 'type': 'search'})",
929 \ "call prop_add(2, 10, {'length': 3, 'type': 'search'})",
930 \ "call prop_add(3, 9, {'length': 3, 'type': 'search'})",
931 \ "call prop_add(4, 8, {'length': 3, 'type': 'search'})",
932 \ "call prop_add(5, 7, {'length': 3, 'type': 'search'})",
933 \ "call prop_add(6, 6, {'length': 3, 'type': 'search'})",
934 \ "call prop_add(7, 5, {'length': 3, 'type': 'search'})",
935 \ "call prop_add(8, 4, {'length': 3, 'type': 'search'})",
936 \ "call prop_add(9, 3, {'length': 3, 'type': 'search'})",
937 \ "call prop_add(10, 2, {'length': 3, 'type': 'search'})",
938 \ "normal 1G6|\<C-V>" .. repeat('l', a:width - 1) .. "10jx",
939 \], 'XtestPropVis')
940 let buf = RunVimInTerminal('-S XtestPropVis', {'rows': 12})
941 call VerifyScreenDump(buf, 'Test_textprop_vis_' .. a:dump, {})
942
943 " clean up
944 call StopVimInTerminal(buf)
945 call delete('XtestPropVis')
946endfunc
947
948" screenshot test with Visual block mode operations
949func Test_textprop_screenshot_visual()
Bram Moolenaar34390282019-10-16 14:38:26 +0200950 CheckScreendump
Bram Moolenaar8055d172019-05-17 22:57:26 +0200951
952 " Delete two columns while text props are three chars wide.
953 call RunTestVisualBlock(2, '01')
954
955 " Same, but delete four columns
956 call RunTestVisualBlock(4, '02')
957endfunc
Bram Moolenaard79eef22019-05-24 20:41:55 +0200958
Bram Moolenaara956bf62019-06-19 17:34:24 +0200959func Test_textprop_after_tab()
Bram Moolenaar34390282019-10-16 14:38:26 +0200960 CheckScreendump
Bram Moolenaar37e66cf2019-06-19 18:16:10 +0200961
Bram Moolenaara956bf62019-06-19 17:34:24 +0200962 let lines =<< trim END
963 call setline(1, [
964 \ "\txxx",
965 \ "x\txxx",
966 \ ])
967 hi SearchProp ctermbg=yellow
968 call prop_type_add('search', {'highlight': 'SearchProp'})
969 call prop_add(1, 2, {'length': 3, 'type': 'search'})
970 call prop_add(2, 3, {'length': 3, 'type': 'search'})
971 END
972 call writefile(lines, 'XtestPropTab')
973 let buf = RunVimInTerminal('-S XtestPropTab', {'rows': 6})
974 call VerifyScreenDump(buf, 'Test_textprop_tab', {})
975
976 " clean up
977 call StopVimInTerminal(buf)
978 call delete('XtestPropTab')
979endfunc
980
Bram Moolenaar34390282019-10-16 14:38:26 +0200981func Test_textprop_with_syntax()
982 CheckScreendump
983
984 let lines =<< trim END
985 call setline(1, [
986 \ "(abc)",
987 \ ])
988 syn match csParens "[()]" display
989 hi! link csParens MatchParen
990
991 call prop_type_add('TPTitle', #{ highlight: 'Title' })
992 call prop_add(1, 2, #{type: 'TPTitle', end_col: 5})
993 END
994 call writefile(lines, 'XtestPropSyn')
995 let buf = RunVimInTerminal('-S XtestPropSyn', {'rows': 6})
996 call VerifyScreenDump(buf, 'Test_textprop_syn_1', {})
997
998 " clean up
999 call StopVimInTerminal(buf)
1000 call delete('XtestPropSyn')
1001endfunc
1002
Bram Moolenaard79eef22019-05-24 20:41:55 +02001003" Adding a text property to a new buffer should not fail
1004func Test_textprop_empty_buffer()
1005 call prop_type_add('comment', {'highlight': 'Search'})
1006 new
1007 call prop_add(1, 1, {'type': 'comment'})
1008 close
Bram Moolenaaradfde112019-05-25 22:11:45 +02001009 call prop_type_delete('comment')
1010endfunc
1011
Bram Moolenaard74af422019-06-28 21:38:00 +02001012" Adding a text property with invalid highlight should be ignored.
1013func Test_textprop_invalid_highlight()
1014 call assert_fails("call prop_type_add('dni', {'highlight': 'DoesNotExist'})", 'E970:')
1015 new
1016 call setline(1, ['asdf','asdf'])
1017 call prop_add(1, 1, {'length': 4, 'type': 'dni'})
1018 redraw
1019 bwipe!
1020 call prop_type_delete('dni')
1021endfunc
1022
Bram Moolenaaradfde112019-05-25 22:11:45 +02001023" Adding a text property to an empty buffer and then editing another
1024func Test_textprop_empty_buffer_next()
1025 call prop_type_add("xxx", {})
1026 call prop_add(1, 1, {"type": "xxx"})
1027 next X
1028 call prop_type_delete('xxx')
Bram Moolenaard79eef22019-05-24 20:41:55 +02001029endfunc
Bram Moolenaarf0884c52019-05-24 21:22:29 +02001030
1031func Test_textprop_remove_from_buf()
1032 new
1033 let buf = bufnr('')
1034 call prop_type_add('one', {'bufnr': buf})
1035 call prop_add(1, 1, {'type': 'one', 'id': 234})
1036 file x
1037 edit y
1038 call prop_remove({'id': 234, 'bufnr': buf}, 1)
1039 call prop_type_delete('one', {'bufnr': buf})
1040 bwipe! x
1041 close
1042endfunc
Bram Moolenaar45311b52019-08-13 22:27:32 +02001043
1044func Test_textprop_in_unloaded_buf()
1045 edit Xaaa
1046 call setline(1, 'aaa')
1047 write
1048 edit Xbbb
1049 call setline(1, 'bbb')
1050 write
1051 let bnr = bufnr('')
1052 edit Xaaa
1053
1054 call prop_type_add('ErrorMsg', #{highlight:'ErrorMsg'})
1055 call assert_fails("call prop_add(1, 1, #{end_lnum: 1, endcol: 2, type: 'ErrorMsg', bufnr: bnr})", 'E275:')
1056 exe 'buf ' .. bnr
1057 call assert_equal('bbb', getline(1))
1058 call assert_equal(0, prop_list(1)->len())
1059
1060 bwipe! Xaaa
1061 bwipe! Xbbb
1062 cal delete('Xaaa')
1063 cal delete('Xbbb')
1064endfunc
Bram Moolenaar1fd30d72019-10-25 22:13:29 +02001065
1066func Test_proptype_substitute2()
1067 new
1068 " text_prop.vim
1069 call setline(1, [
1070 \ 'The num 123 is smaller than 4567.',
1071 \ '123 The number 123 is smaller than 4567.',
1072 \ '123 The number 123 is smaller than 4567.'])
1073
1074 call prop_type_add('number', {'highlight': 'ErrorMsg'})
1075
1076 call prop_add(1, 12, {'length': 3, 'type': 'number'})
1077 call prop_add(2, 1, {'length': 3, 'type': 'number'})
1078 call prop_add(3, 36, {'length': 4, 'type': 'number'})
1079 set ul&
1080 let expected = [{'id': 0, 'col': 13, 'end': 1, 'type': 'number', 'length': 3, 'start': 1},
1081 \ {'id': 0, 'col': 1, 'end': 1, 'type': 'number', 'length': 3, 'start': 1},
1082 \ {'id': 0, 'col': 50, 'end': 1, 'type': 'number', 'length': 4, 'start': 1}]
1083 " Add some text in between
1084 %s/\s\+/ /g
1085 call assert_equal(expected, prop_list(1) + prop_list(2) + prop_list(3))
1086
1087 " remove some text
1088 :1s/[a-z]\{3\}//g
1089 let expected = [{'id': 0, 'col': 10, 'end': 1, 'type': 'number', 'length': 3, 'start': 1}]
1090 call assert_equal(expected, prop_list(1))
1091 bwipe!
1092endfunc
Bram Moolenaar5cb0b932020-01-03 21:25:59 +01001093
Bram Moolenaarac15fd82020-01-09 21:35:48 +01001094func SaveOptions()
1095 let d = #{tabstop: &tabstop,
1096 \ softtabstop: &softtabstop,
1097 \ shiftwidth: &shiftwidth,
1098 \ expandtab: &expandtab,
1099 \ foldmethod: '"' .. &foldmethod .. '"',
1100 \ }
1101 return d
1102endfunc
1103
1104func RestoreOptions(dict)
1105 for name in keys(a:dict)
1106 exe 'let &' .. name .. ' = ' .. a:dict[name]
1107 endfor
1108endfunc
1109
Bram Moolenaar5cb0b932020-01-03 21:25:59 +01001110func Test_textprop_noexpandtab()
Bram Moolenaar5cb0b932020-01-03 21:25:59 +01001111 new
Bram Moolenaarac15fd82020-01-09 21:35:48 +01001112 let save_dict = SaveOptions()
1113
Bram Moolenaar5cb0b932020-01-03 21:25:59 +01001114 set tabstop=8
Bram Moolenaar5cb0b932020-01-03 21:25:59 +01001115 set softtabstop=4
Bram Moolenaar5cb0b932020-01-03 21:25:59 +01001116 set shiftwidth=4
Bram Moolenaar5cb0b932020-01-03 21:25:59 +01001117 set noexpandtab
Bram Moolenaar5cb0b932020-01-03 21:25:59 +01001118 set foldmethod=marker
Bram Moolenaarac15fd82020-01-09 21:35:48 +01001119
Bram Moolenaar5cb0b932020-01-03 21:25:59 +01001120 call feedkeys("\<esc>\<esc>0Ca\<cr>\<esc>\<up>", "tx")
1121 call prop_type_add('test', {'highlight': 'ErrorMsg'})
1122 call prop_add(1, 1, {'end_col': 2, 'type': 'test'})
1123 call feedkeys("0i\<tab>", "tx")
1124 call prop_remove({'type': 'test'})
1125 call prop_add(1, 2, {'end_col': 3, 'type': 'test'})
1126 call feedkeys("A\<left>\<tab>", "tx")
1127 call prop_remove({'type': 'test'})
1128 try
1129 " It is correct that this does not pass
1130 call prop_add(1, 6, {'end_col': 7, 'type': 'test'})
1131 " Has already collapsed here, start_col:6 does not result in an error
1132 call feedkeys("A\<left>\<tab>", "tx")
1133 catch /^Vim\%((\a\+)\)\=:E964/
1134 endtry
1135 call prop_remove({'type': 'test'})
Bram Moolenaarac15fd82020-01-09 21:35:48 +01001136 call prop_type_delete('test')
1137
1138 call RestoreOptions(save_dict)
1139 bwipe!
1140endfunc
1141
1142func Test_textprop_noexpandtab_redraw()
1143 new
1144 let save_dict = SaveOptions()
1145
1146 set tabstop=8
1147 set softtabstop=4
1148 set shiftwidth=4
1149 set noexpandtab
1150 set foldmethod=marker
1151
1152 call feedkeys("\<esc>\<esc>0Ca\<cr>\<space>\<esc>\<up>", "tx")
1153 call prop_type_add('test', {'highlight': 'ErrorMsg'})
1154 call prop_add(1, 1, {'end_col': 2, 'type': 'test'})
1155 call feedkeys("0i\<tab>", "tx")
1156 " Internally broken at the next line
1157 call feedkeys("A\<left>\<tab>", "tx")
1158 redraw
1159 " Index calculation failed internally on next line
1160 call prop_add(1, 1, {'end_col': 2, 'type': 'test'})
1161 call prop_remove({'type': 'test', 'all': v:true})
1162 call prop_type_delete('test')
1163 call prop_type_delete('test')
1164
1165 call RestoreOptions(save_dict)
1166 bwipe!
1167endfunc
1168
1169func Test_textprop_ins_str()
1170 new
1171 call setline(1, 'just some text')
1172 call prop_type_add('test', {'highlight': 'ErrorMsg'})
1173 call prop_add(1, 1, {'end_col': 2, 'type': 'test'})
1174 call assert_equal([{'id': 0, 'col': 1, 'end': 1, 'type': 'test', 'length': 1, 'start': 1}], prop_list(1))
1175
1176 call feedkeys("foi\<F8>\<Esc>", "tx")
1177 call assert_equal('just s<F8>ome text', getline(1))
1178 call assert_equal([{'id': 0, 'col': 1, 'end': 1, 'type': 'test', 'length': 1, 'start': 1}], prop_list(1))
1179
1180 bwipe!
1181 call prop_remove({'type': 'test'})
1182 call prop_type_delete('test')
Bram Moolenaar5cb0b932020-01-03 21:25:59 +01001183endfunc
Bram Moolenaar66b98852020-03-11 19:15:52 +01001184
1185func Test_find_prop_later_in_line()
1186 new
1187 call prop_type_add('test', {'highlight': 'ErrorMsg'})
1188 call setline(1, 'just some text')
1189 call prop_add(1, 1, {'length': 4, 'type': 'test'})
1190 call prop_add(1, 10, {'length': 3, 'type': 'test'})
1191
1192 call assert_equal({'id': 0, 'lnum': 1, 'col': 10, 'end': 1, 'type': 'test', 'length': 3, 'start': 1},
1193 \ prop_find(#{type: 'test', lnum: 1, col: 6}))
1194
1195 bwipe!
1196 call prop_type_delete('test')
1197endfunc
1198
1199func Test_find_zerowidth_prop_sol()
1200 new
1201 call prop_type_add('test', {'highlight': 'ErrorMsg'})
1202 call setline(1, 'just some text')
1203 call prop_add(1, 1, {'length': 0, 'type': 'test'})
1204
1205 call assert_equal({'id': 0, 'lnum': 1, 'col': 1, 'end': 1, 'type': 'test', 'length': 0, 'start': 1},
1206 \ prop_find(#{type: 'test', lnum: 1}))
1207
1208 bwipe!
1209 call prop_type_delete('test')
1210endfunc
Bram Moolenaar99fa7212020-04-26 15:59:55 +02001211
1212" Test for passing invalid arguments to prop_xxx() functions
1213func Test_prop_func_invalid_args()
1214 call assert_fails('call prop_clear(1, 2, [])', 'E715:')
1215 call assert_fails('call prop_clear(-1, 2)', 'E16:')
1216 call assert_fails('call prop_find(test_null_dict())', 'E474:')
1217 call assert_fails('call prop_find({"bufnr" : []})', 'E158:')
1218 call assert_fails('call prop_find({})', 'E968:')
1219 call assert_fails('call prop_find({}, "x")', 'E474:')
1220 call assert_fails('call prop_find({"lnum" : -2})', 'E16:')
1221 call assert_fails('call prop_list(1, [])', 'E715:')
1222 call assert_fails('call prop_list(-1 , {})', 'E16:')
1223 call assert_fails('call prop_remove([])', 'E474:')
1224 call assert_fails('call prop_remove({}, -2)', 'E16:')
1225 call assert_fails('call prop_remove({})', 'E968:')
1226 call assert_fails('call prop_type_add([], {})', 'E474:')
1227 call assert_fails("call prop_type_change('long', {'xyz' : 10})", 'E971:')
1228 call assert_fails("call prop_type_delete([])", 'E474:')
1229 call assert_fails("call prop_type_delete('xyz', [])", 'E715:')
1230 call assert_fails("call prop_type_get([])", 'E474:')
1231 call assert_fails("call prop_type_get('', [])", 'E474:')
1232 call assert_fails("call prop_type_list([])", 'E715:')
1233endfunc
1234
Bram Moolenaar87be9be2020-05-30 15:32:02 +02001235func Test_split_join()
1236 new
1237 call prop_type_add('test', {'highlight': 'ErrorMsg'})
1238 call setline(1, 'just some text')
1239 call prop_add(1, 6, {'length': 4, 'type': 'test'})
1240
1241 " Split in middle of "some"
1242 execute "normal! 8|i\<CR>"
1243 call assert_equal([{'id': 0, 'col': 6, 'end': 0, 'type': 'test', 'length': 2, 'start': 1}],
1244 \ prop_list(1))
1245 call assert_equal([{'id': 0, 'col': 1, 'end': 1, 'type': 'test', 'length': 2, 'start': 0}],
1246 \ prop_list(2))
1247
1248 " Join the two lines back together
1249 normal! 1GJ
1250 call assert_equal([{'id': 0, 'col': 6, 'end': 1, 'type': 'test', 'length': 5, 'start': 1}], prop_list(1))
1251
1252 bwipe!
1253 call prop_type_delete('test')
1254endfunc
1255
Bram Moolenaar99fa7212020-04-26 15:59:55 +02001256" vim: shiftwidth=2 sts=2 expandtab