blob: 8bed38a589d277134658460095a4bfe314913ebb [file] [log] [blame]
Bram Moolenaar209d3872017-11-16 21:52:51 +01001" Tests for 'listchars' display with 'list' and :list
2
Bram Moolenaar41fb7232021-07-08 12:40:05 +02003source check.vim
Bram Moolenaar209d3872017-11-16 21:52:51 +01004source view_util.vim
Bram Moolenaar41fb7232021-07-08 12:40:05 +02005source screendump.vim
Bram Moolenaar209d3872017-11-16 21:52:51 +01006
zeertzjqabc80812023-09-24 23:32:18 +02007func Check_listchars(expected, end_lnum, end_scol = -1, leftcol = 0)
8 if a:leftcol > 0
9 let save_wrap = &wrap
10 set nowrap
11 call cursor(1, 1)
12 exe 'normal! ' .. a:leftcol .. 'zl'
13 endif
14
15 redraw!
16 for i in range(1, a:end_lnum)
17 if a:leftcol > 0
18 let col = virtcol2col(0, i, a:leftcol)
19 let col += getline(i)->strpart(col - 1, 1, v:true)->len()
20 call cursor(i, col)
21 redraw
22 call assert_equal(a:leftcol, winsaveview().leftcol)
23 else
24 call cursor(i, 1)
25 end
26
27 let end_scol = a:end_scol < 0 ? '$'->virtcol() - a:leftcol : a:end_scol
28 call assert_equal([a:expected[i - 1]->strcharpart(a:leftcol)],
29 \ ScreenLines(i, end_scol))
30 endfor
31
32 if a:leftcol > 0
33 let &wrap = save_wrap
34 endif
35endfunc
36
Bram Moolenaar209d3872017-11-16 21:52:51 +010037func Test_listchars()
38 enew!
39 set ff=unix
40 set list
41
42 set listchars+=tab:>-,space:.,trail:<
43 call append(0, [
44 \ ' aa ',
45 \ ' bb ',
46 \ ' cccc ',
47 \ 'dd ee ',
48 \ ' '
49 \ ])
50 let expected = [
51 \ '>-------aa>-----$',
52 \ '..bb>---<<$',
53 \ '...cccc><$',
54 \ 'dd........ee<<>-$',
55 \ '<$'
56 \ ]
zeertzjqabc80812023-09-24 23:32:18 +020057 call Check_listchars(expected, 5)
58 call Check_listchars(expected, 4, -1, 5)
Bram Moolenaar209d3872017-11-16 21:52:51 +010059
60 set listchars-=trail:<
61 let expected = [
62 \ '>-------aa>-----$',
63 \ '..bb>---..$',
64 \ '...cccc>.$',
65 \ 'dd........ee..>-$',
66 \ '.$'
67 \ ]
zeertzjqabc80812023-09-24 23:32:18 +020068 call Check_listchars(expected, 5)
69 call Check_listchars(expected, 4, -1, 5)
Bram Moolenaar209d3872017-11-16 21:52:51 +010070
Bram Moolenaar83a52172019-01-16 22:41:54 +010071 " tab with 3rd character.
72 set listchars-=tab:>-
73 set listchars+=tab:<=>,trail:-
74 let expected = [
75 \ '<======>aa<====>$',
76 \ '..bb<==>--$',
77 \ '...cccc>-$',
78 \ 'dd........ee--<>$',
79 \ '-$'
80 \ ]
zeertzjqabc80812023-09-24 23:32:18 +020081 call Check_listchars(expected, 5)
82 call Check_listchars(expected, 4, -1, 5)
Bram Moolenaar83a52172019-01-16 22:41:54 +010083
Bram Moolenaar69cbbec2019-08-17 14:10:56 +020084 " tab with 3rd character and linebreak set
85 set listchars-=tab:<=>
86 set listchars+=tab:<·>
87 set linebreak
88 let expected = [
89 \ '<······>aa<····>$',
90 \ '..bb<··>--$',
91 \ '...cccc>-$',
92 \ 'dd........ee--<>$',
93 \ '-$'
94 \ ]
zeertzjqabc80812023-09-24 23:32:18 +020095 call Check_listchars(expected, 5)
Bram Moolenaar69cbbec2019-08-17 14:10:56 +020096 set nolinebreak
97 set listchars-=tab:<·>
98 set listchars+=tab:<=>
99
Bram Moolenaar83a52172019-01-16 22:41:54 +0100100 set listchars-=trail:-
101 let expected = [
102 \ '<======>aa<====>$',
103 \ '..bb<==>..$',
104 \ '...cccc>.$',
105 \ 'dd........ee..<>$',
106 \ '.$'
107 \ ]
zeertzjqabc80812023-09-24 23:32:18 +0200108 call Check_listchars(expected, 5)
109 call Check_listchars(expected, 4, -1, 5)
Bram Moolenaar83a52172019-01-16 22:41:54 +0100110
111 set listchars-=tab:<=>
112 set listchars+=tab:>-
Bram Moolenaar209d3872017-11-16 21:52:51 +0100113 set listchars+=trail:<
114 set nolist
115 normal ggdG
116 call append(0, [
117 \ ' fff ',
118 \ ' gg ',
119 \ ' h ',
120 \ 'iii ',
121 \ ])
122 let l = split(execute("%list"), "\n")
123 call assert_equal([
124 \ '..fff>--<<$',
125 \ '>-------gg>-----$',
126 \ '.....h>-$',
zeertzjqabc80812023-09-24 23:32:18 +0200127 \ 'iii<<<<><<$',
128 \ '$'], l)
Bram Moolenaar209d3872017-11-16 21:52:51 +0100129
Bram Moolenaar91478ae2021-02-03 15:58:13 +0100130 " Test lead and trail
131 normal ggdG
132 set listchars&
133 set listchars+=lead:>,trail:<,space:x
134 set list
135
136 call append(0, [
137 \ ' ffff ',
138 \ ' gg',
139 \ 'h ',
140 \ ' ',
141 \ ' 0 0 ',
142 \ ])
143
144 let expected = [
145 \ '>>>>ffff<<<<$',
146 \ '>>>>>>>>>>gg$',
147 \ 'h<<<<<<<<<<<$',
148 \ '<<<<<<<<<<<<$',
149 \ '>>>>0xx0<<<<$',
zeertzjqabc80812023-09-24 23:32:18 +0200150 \ '$'
Bram Moolenaar91478ae2021-02-03 15:58:13 +0100151 \ ]
zeertzjqabc80812023-09-24 23:32:18 +0200152 call Check_listchars(expected, 6)
153 call Check_listchars(expected, 5, -1, 6)
Bram Moolenaar91478ae2021-02-03 15:58:13 +0100154 call assert_equal(expected, split(execute("%list"), "\n"))
Bram Moolenaar895d9662019-01-31 21:57:21 +0100155
zeertzjqf14b8ba2021-09-10 16:58:30 +0200156 " Test multispace
157 normal ggdG
158 set listchars&
159 set listchars+=multispace:yYzZ
160 set list
161
162 call append(0, [
163 \ ' ffff ',
164 \ ' i i gg',
165 \ ' h ',
166 \ ' j ',
167 \ ' 0 0 ',
168 \ ])
169
170 let expected = [
171 \ 'yYzZffffyYzZ$',
172 \ 'yYi iyYzZygg$',
173 \ ' hyYzZyYzZyY$',
174 \ 'yYzZyYzZyYj $',
175 \ 'yYzZ0yY0yYzZ$',
zeertzjqabc80812023-09-24 23:32:18 +0200176 \ '$'
zeertzjqf14b8ba2021-09-10 16:58:30 +0200177 \ ]
zeertzjqabc80812023-09-24 23:32:18 +0200178 call Check_listchars(expected, 6)
179 call Check_listchars(expected, 5, -1, 6)
zeertzjqf14b8ba2021-09-10 16:58:30 +0200180 call assert_equal(expected, split(execute("%list"), "\n"))
181
Bram Moolenaaraca12fd2022-06-07 10:16:15 +0100182 " Test leadmultispace + multispace
183 normal ggdG
184 set listchars=eol:$,multispace:yYzZ,nbsp:S
185 set listchars+=leadmultispace:.-+*
186 set list
187
188 call append(0, [
189 \ ' ffff ',
190 \ ' i i  gg',
191 \ ' h ',
192 \ ' j ',
193 \ ' 0 0 ',
194 \ ])
195
196 let expected = [
197 \ '.-+*ffffyYzZ$',
198 \ '.-i iSyYzZgg$',
199 \ ' hyYzZyYzZyY$',
200 \ '.-+*.-+*.-j $',
201 \ '.-+*0yY0yYzZ$',
zeertzjqabc80812023-09-24 23:32:18 +0200202 \ '$'
Bram Moolenaaraca12fd2022-06-07 10:16:15 +0100203 \ ]
Bram Moolenaaraca12fd2022-06-07 10:16:15 +0100204 call assert_equal('eol:$,multispace:yYzZ,nbsp:S,leadmultispace:.-+*', &listchars)
zeertzjqabc80812023-09-24 23:32:18 +0200205 call Check_listchars(expected, 6)
206 call Check_listchars(expected, 5, -1, 1)
207 call Check_listchars(expected, 5, -1, 2)
208 call Check_listchars(expected, 5, -1, 3)
209 call Check_listchars(expected, 5, -1, 6)
Bram Moolenaaraca12fd2022-06-07 10:16:15 +0100210 call assert_equal(expected, split(execute("%list"), "\n"))
211
212 " Test leadmultispace without multispace
213 normal ggdG
214 set listchars-=multispace:yYzZ
215 set listchars+=space:+,trail:>,eol:$
216 set list
217
218 call append(0, [
219 \ ' ffff ',
220 \ ' i i gg',
221 \ ' h ',
222 \ ' j ',
223 \ ' 0 0 ',
224 \ ])
225
226 let expected = [
227 \ '.-+*ffff>>>>$',
228 \ '.-i+i+++++gg$',
229 \ '+h>>>>>>>>>>$',
230 \ '.-+*.-+*.-j>$',
231 \ '.-+*0++0>>>>$',
zeertzjqabc80812023-09-24 23:32:18 +0200232 \ '$'
Bram Moolenaaraca12fd2022-06-07 10:16:15 +0100233 \ ]
Bram Moolenaaraca12fd2022-06-07 10:16:15 +0100234 call assert_equal('eol:$,nbsp:S,leadmultispace:.-+*,space:+,trail:>,eol:$', &listchars)
zeertzjqabc80812023-09-24 23:32:18 +0200235 call Check_listchars(expected, 6)
236 call Check_listchars(expected, 5, -1, 1)
237 call Check_listchars(expected, 5, -1, 2)
238 call Check_listchars(expected, 5, -1, 3)
239 call Check_listchars(expected, 5, -1, 6)
Bram Moolenaaraca12fd2022-06-07 10:16:15 +0100240 call assert_equal(expected, split(execute("%list"), "\n"))
241
242 " Test leadmultispace only
243 normal ggdG
244 set listchars&
245 set listchars=leadmultispace:.-+*
246 set list
247
248 call append(0, [
249 \ ' ffff ',
250 \ ' i i gg',
251 \ ' h ',
252 \ ' j ',
253 \ ' 0 0 ',
254 \ ])
255
256 let expected = [
257 \ '.-+*ffff ',
258 \ '.-i i gg',
259 \ ' h ',
260 \ '.-+*.-+*.-j ',
261 \ '.-+*0 0 ',
zeertzjqabc80812023-09-24 23:32:18 +0200262 \ ' '
Bram Moolenaaraca12fd2022-06-07 10:16:15 +0100263 \ ]
Bram Moolenaaraca12fd2022-06-07 10:16:15 +0100264 call assert_equal('leadmultispace:.-+*', &listchars)
zeertzjqabc80812023-09-24 23:32:18 +0200265 call Check_listchars(expected, 5, 12)
Bram Moolenaaraca12fd2022-06-07 10:16:15 +0100266 call assert_equal(expected, split(execute("%list"), "\n"))
267
zeertzjq00624a22023-11-23 20:47:16 +0100268 " Changing the value of 'ambiwidth' twice shouldn't cause double-free when
269 " "leadmultispace" is specified.
270 set ambiwidth=double
271 set ambiwidth&
272
Bram Moolenaaraca12fd2022-06-07 10:16:15 +0100273 " Test leadmultispace and lead and space
274 normal ggdG
275 set listchars&
276 set listchars+=lead:<,space:-
277 set listchars+=leadmultispace:.-+*
278 set list
279
280 call append(0, [
281 \ ' ffff ',
282 \ ' i i gg',
283 \ ' h ',
284 \ ' j ',
285 \ ' 0 0 ',
286 \ ])
287
288 let expected = [
289 \ '.-+*ffff----$',
290 \ '.-i-i-----gg$',
291 \ '<h----------$',
292 \ '.-+*.-+*.-j-$',
293 \ '.-+*0--0----$',
zeertzjqabc80812023-09-24 23:32:18 +0200294 \ '$'
Bram Moolenaaraca12fd2022-06-07 10:16:15 +0100295 \ ]
Bram Moolenaaraca12fd2022-06-07 10:16:15 +0100296 call assert_equal('eol:$,lead:<,space:-,leadmultispace:.-+*', &listchars)
zeertzjqabc80812023-09-24 23:32:18 +0200297 call Check_listchars(expected, 6)
298 call Check_listchars(expected, 5, -1, 1)
299 call Check_listchars(expected, 5, -1, 2)
300 call Check_listchars(expected, 5, -1, 3)
301 call Check_listchars(expected, 5, -1, 6)
Bram Moolenaaraca12fd2022-06-07 10:16:15 +0100302 call assert_equal(expected, split(execute("%list"), "\n"))
303
zeertzjqf14b8ba2021-09-10 16:58:30 +0200304 " the last occurrence of 'multispace:' is used
Bram Moolenaaraca12fd2022-06-07 10:16:15 +0100305 set listchars&
306 set listchars+=multispace:yYzZ
zeertzjqf14b8ba2021-09-10 16:58:30 +0200307 set listchars+=space:x,multispace:XyY
308
309 let expected = [
310 \ 'XyYXffffXyYX$',
311 \ 'XyixiXyYXygg$',
312 \ 'xhXyYXyYXyYX$',
313 \ 'XyYXyYXyYXjx$',
314 \ 'XyYX0Xy0XyYX$',
zeertzjqabc80812023-09-24 23:32:18 +0200315 \ '$'
zeertzjqf14b8ba2021-09-10 16:58:30 +0200316 \ ]
Bram Moolenaaraca12fd2022-06-07 10:16:15 +0100317 call assert_equal('eol:$,multispace:yYzZ,space:x,multispace:XyY', &listchars)
zeertzjqabc80812023-09-24 23:32:18 +0200318 call Check_listchars(expected, 6)
319 call Check_listchars(expected, 5, -1, 6)
zeertzjqf14b8ba2021-09-10 16:58:30 +0200320 call assert_equal(expected, split(execute("%list"), "\n"))
321
322 set listchars+=lead:>,trail:<
323
324 let expected = [
325 \ '>>>>ffff<<<<$',
326 \ '>>ixiXyYXygg$',
327 \ '>h<<<<<<<<<<$',
328 \ '>>>>>>>>>>j<$',
329 \ '>>>>0Xy0<<<<$',
zeertzjqabc80812023-09-24 23:32:18 +0200330 \ '$'
zeertzjqf14b8ba2021-09-10 16:58:30 +0200331 \ ]
zeertzjqabc80812023-09-24 23:32:18 +0200332 call Check_listchars(expected, 6)
333 call Check_listchars(expected, 5, -1, 6)
zeertzjqf14b8ba2021-09-10 16:58:30 +0200334 call assert_equal(expected, split(execute("%list"), "\n"))
335
336 " removing 'multispace:'
337 set listchars-=multispace:XyY
338 set listchars-=multispace:yYzZ
339
340 let expected = [
341 \ '>>>>ffff<<<<$',
342 \ '>>ixixxxxxgg$',
343 \ '>h<<<<<<<<<<$',
344 \ '>>>>>>>>>>j<$',
345 \ '>>>>0xx0<<<<$',
zeertzjqabc80812023-09-24 23:32:18 +0200346 \ '$'
zeertzjqf14b8ba2021-09-10 16:58:30 +0200347 \ ]
zeertzjqabc80812023-09-24 23:32:18 +0200348 call Check_listchars(expected, 6)
349 call Check_listchars(expected, 5, -1, 6)
zeertzjqf14b8ba2021-09-10 16:58:30 +0200350 call assert_equal(expected, split(execute("%list"), "\n"))
351
Bram Moolenaar895d9662019-01-31 21:57:21 +0100352 " test nbsp
353 normal ggdG
354 set listchars=nbsp:X,trail:Y
355 set list
356 " Non-breaking space
357 let nbsp = nr2char(0xa0)
Bram Moolenaarf1387282021-03-22 17:11:15 +0100358 call append(0, [ ">" .. nbsp .. "<" ])
Bram Moolenaar895d9662019-01-31 21:57:21 +0100359
360 let expected = '>X< '
zeertzjqabc80812023-09-24 23:32:18 +0200361 call Check_listchars([expected], 1)
Bram Moolenaar895d9662019-01-31 21:57:21 +0100362
363 set listchars=nbsp:X
zeertzjqabc80812023-09-24 23:32:18 +0200364 call Check_listchars([expected], 1)
Bram Moolenaar895d9662019-01-31 21:57:21 +0100365
Bram Moolenaara5c6a0b2019-05-08 20:20:46 +0200366 " test extends
367 normal ggdG
368 set listchars=extends:Z
369 set nowrap
370 set nolist
371 call append(0, [ repeat('A', &columns + 1) ])
372
373 let expected = repeat('A', &columns)
zeertzjqabc80812023-09-24 23:32:18 +0200374 call Check_listchars([expected], 1, &columns)
Bram Moolenaara5c6a0b2019-05-08 20:20:46 +0200375
376 set list
377 let expected = expected[:-2] . 'Z'
zeertzjqabc80812023-09-24 23:32:18 +0200378 call Check_listchars([expected], 1, &columns)
Bram Moolenaara5c6a0b2019-05-08 20:20:46 +0200379
Bram Moolenaar209d3872017-11-16 21:52:51 +0100380 enew!
381 set listchars& ff&
382endfunc
Bram Moolenaar5f8069b2019-03-30 15:34:47 +0100383
Bram Moolenaare5e4e222019-04-04 13:28:45 +0200384" Test that unicode listchars characters get properly inserted
385func Test_listchars_unicode()
386 enew!
387 let oldencoding=&encoding
388 set encoding=utf-8
389 set ff=unix
390
zeertzjqf14b8ba2021-09-10 16:58:30 +0200391 set listchars=eol:⇔,space:␣,multispace:≡≢≣,nbsp:≠,tab:←↔→
Bram Moolenaare5e4e222019-04-04 13:28:45 +0200392 set list
393
394 let nbsp = nr2char(0xa0)
zeertzjqf14b8ba2021-09-10 16:58:30 +0200395 call append(0, [" a\tb c" .. nbsp .. "d "])
396 let expected = ['≡≢≣≡≢≣≡≢a←↔↔↔↔↔→b␣c≠d≡≢⇔']
zeertzjqabc80812023-09-24 23:32:18 +0200397 call Check_listchars(expected, 1)
398 call Check_listchars(expected, 1, -1, 3)
399 call Check_listchars(expected, 1, -1, 13)
zeertzjqf14b8ba2021-09-10 16:58:30 +0200400
Bram Moolenaar93ff6722021-10-16 17:51:40 +0100401 set listchars=eol:\\u21d4,space:\\u2423,multispace:≡\\u2262\\U00002263,nbsp:\\U00002260,tab:←↔\\u2192
zeertzjqabc80812023-09-24 23:32:18 +0200402 call Check_listchars(expected, 1)
403 call Check_listchars(expected, 1, -1, 3)
404 call Check_listchars(expected, 1, -1, 13)
Bram Moolenaar93ff6722021-10-16 17:51:40 +0100405
zeertzjqf14b8ba2021-09-10 16:58:30 +0200406 set listchars+=lead:⇨,trail:⇦
407 let expected = ['⇨⇨⇨⇨⇨⇨⇨⇨a←↔↔↔↔↔→b␣c≠d⇦⇦⇔']
zeertzjqabc80812023-09-24 23:32:18 +0200408 call Check_listchars(expected, 1)
409 call Check_listchars(expected, 1, -1, 3)
410 call Check_listchars(expected, 1, -1, 13)
zeertzjqf14b8ba2021-09-10 16:58:30 +0200411
Bram Moolenaare5e4e222019-04-04 13:28:45 +0200412 let &encoding=oldencoding
413 enew!
414 set listchars& ff&
415endfunction
416
zeertzjqf14b8ba2021-09-10 16:58:30 +0200417func Test_listchars_invalid()
418 enew!
419 set ff=unix
420
421 set listchars&
422 set list
423 set ambiwidth=double
424
425 " No colon
426 call assert_fails('set listchars=x', 'E474:')
427 call assert_fails('set listchars=x', 'E474:')
428 call assert_fails('set listchars=multispace', 'E474:')
Bram Moolenaaraca12fd2022-06-07 10:16:15 +0100429 call assert_fails('set listchars=leadmultispace', 'E474:')
zeertzjqf14b8ba2021-09-10 16:58:30 +0200430
431 " Too short
zeertzjq6a8d2e12024-01-17 20:54:49 +0100432 call assert_fails('set listchars=space:', 'E1511:')
433 call assert_fails('set listchars=tab:x', 'E1511:')
434 call assert_fails('set listchars=multispace:', 'E1511:')
435 call assert_fails('set listchars=leadmultispace:', 'E1511:')
zeertzjqf14b8ba2021-09-10 16:58:30 +0200436
437 " One occurrence too short
zeertzjq6a8d2e12024-01-17 20:54:49 +0100438 call assert_fails('set listchars=space:x,space:', 'E1511:')
439 call assert_fails('set listchars=space:,space:x', 'E1511:')
440 call assert_fails('set listchars=tab:xx,tab:x', 'E1511:')
441 call assert_fails('set listchars=tab:x,tab:xx', 'E1511:')
442 call assert_fails('set listchars=multispace:,multispace:x', 'E1511:')
443 call assert_fails('set listchars=multispace:x,multispace:', 'E1511:')
444 call assert_fails('set listchars=leadmultispace:,leadmultispace:x', 'E1511:')
445 call assert_fails('set listchars=leadmultispace:x,leadmultispace:', 'E1511:')
zeertzjqf14b8ba2021-09-10 16:58:30 +0200446
447 " Too long
zeertzjq6a8d2e12024-01-17 20:54:49 +0100448 call assert_fails('set listchars=space:xx', 'E1511:')
449 call assert_fails('set listchars=tab:xxxx', 'E1511:')
zeertzjqf14b8ba2021-09-10 16:58:30 +0200450
zeertzjq60618c82021-12-18 15:32:46 +0000451 " Has double-width character
zeertzjq6a8d2e12024-01-17 20:54:49 +0100452 call assert_fails('set listchars=space:·', 'E1512:')
453 call assert_fails('set listchars=tab:·x', 'E1512:')
454 call assert_fails('set listchars=tab:x·', 'E1512:')
455 call assert_fails('set listchars=tab:xx·', 'E1512:')
456 call assert_fails('set listchars=multispace:·', 'E1512:')
457 call assert_fails('set listchars=multispace:xxx·', 'E1512:')
458 call assert_fails('set listchars=leadmultispace:·', 'E1512:')
459 call assert_fails('set listchars=leadmultispace:xxx·', 'E1512:')
zeertzjqf14b8ba2021-09-10 16:58:30 +0200460
zeertzjq60618c82021-12-18 15:32:46 +0000461 " Has control character
zeertzjq6a8d2e12024-01-17 20:54:49 +0100462 call assert_fails("set listchars=space:\x01", 'E1512:')
463 call assert_fails("set listchars=tab:\x01x", 'E1512:')
464 call assert_fails("set listchars=tab:x\x01", 'E1512:')
465 call assert_fails("set listchars=tab:xx\x01", 'E1512:')
466 call assert_fails("set listchars=multispace:\x01", 'E1512:')
467 call assert_fails("set listchars=multispace:xxx\x01", 'E1512:')
468 call assert_fails('set listchars=space:\\x01', 'E1512:')
469 call assert_fails('set listchars=tab:\\x01x', 'E1512:')
470 call assert_fails('set listchars=tab:x\\x01', 'E1512:')
471 call assert_fails('set listchars=tab:xx\\x01', 'E1512:')
472 call assert_fails('set listchars=multispace:\\x01', 'E1512:')
473 call assert_fails('set listchars=multispace:xxx\\x01', 'E1512:')
474 call assert_fails("set listchars=leadmultispace:\x01", 'E1512:')
475 call assert_fails('set listchars=leadmultispace:\\x01', 'E1512:')
476 call assert_fails("set listchars=leadmultispace:xxx\x01", 'E1512:')
477 call assert_fails('set listchars=leadmultispace:xxx\\x01', 'E1512:')
zeertzjq60618c82021-12-18 15:32:46 +0000478
zeertzjqf14b8ba2021-09-10 16:58:30 +0200479 enew!
480 set ambiwidth& listchars& ff&
481endfunction
482
Bram Moolenaare5e4e222019-04-04 13:28:45 +0200483" Tests that space characters following composing character won't get replaced
484" by listchars.
Bram Moolenaar5f8069b2019-03-30 15:34:47 +0100485func Test_listchars_composing()
486 enew!
487 let oldencoding=&encoding
488 set encoding=utf-8
489 set ff=unix
490 set list
491
Bram Moolenaare5e4e222019-04-04 13:28:45 +0200492 set listchars=eol:$,space:_,nbsp:=
Bram Moolenaar94722c52023-01-28 19:19:03 +0000493
Bram Moolenaare5e4e222019-04-04 13:28:45 +0200494 let nbsp1 = nr2char(0xa0)
495 let nbsp2 = nr2char(0x202f)
Bram Moolenaar5f8069b2019-03-30 15:34:47 +0100496 call append(0, [
Bram Moolenaarf1387282021-03-22 17:11:15 +0100497 \ " \u3099\t \u309A" .. nbsp1 .. nbsp1 .. "\u0302" .. nbsp2 .. nbsp2 .. "\u0302",
Bram Moolenaar5f8069b2019-03-30 15:34:47 +0100498 \ ])
499 let expected = [
Bram Moolenaarf1387282021-03-22 17:11:15 +0100500 \ "_ \u3099^I \u309A=" .. nbsp1 .. "\u0302=" .. nbsp2 .. "\u0302$"
Bram Moolenaar5f8069b2019-03-30 15:34:47 +0100501 \ ]
zeertzjqabc80812023-09-24 23:32:18 +0200502 call Check_listchars(expected, 1)
Bram Moolenaar5f8069b2019-03-30 15:34:47 +0100503 let &encoding=oldencoding
Bram Moolenaare5e4e222019-04-04 13:28:45 +0200504 enew!
Bram Moolenaar5f8069b2019-03-30 15:34:47 +0100505 set listchars& ff&
506endfunction
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200507
Bram Moolenaareed9d462021-02-15 20:38:25 +0100508" Check for the value of the 'listchars' option
509func s:CheckListCharsValue(expected)
510 call assert_equal(a:expected, &listchars)
511 call assert_equal(a:expected, getwinvar(0, '&listchars'))
512endfunc
513
514" Test for using a window local value for 'listchars'
515func Test_listchars_window_local()
516 %bw!
517 set list listchars&
518 new
519 " set a local value for 'listchars'
520 setlocal listchars=tab:+-,eol:#
521 call s:CheckListCharsValue('tab:+-,eol:#')
522 " When local value is reset, global value should be used
523 setlocal listchars=
524 call s:CheckListCharsValue('eol:$')
525 " Use 'setlocal <' to copy global value
526 setlocal listchars=space:.,extends:>
527 setlocal listchars<
528 call s:CheckListCharsValue('eol:$')
529 " Use 'set <' to copy global value
530 setlocal listchars=space:.,extends:>
531 set listchars<
532 call s:CheckListCharsValue('eol:$')
533 " Changing global setting should not change the local setting
534 setlocal listchars=space:.,extends:>
535 setglobal listchars=tab:+-,eol:#
536 call s:CheckListCharsValue('space:.,extends:>')
537 " when split opening a new window, local value should be copied
538 split
539 call s:CheckListCharsValue('space:.,extends:>')
540 " clearing local value in one window should not change the other window
541 set listchars&
542 call s:CheckListCharsValue('eol:$')
543 close
544 call s:CheckListCharsValue('space:.,extends:>')
545
546 " use different values for 'listchars' items in two different windows
547 call setline(1, ["\t one two "])
548 setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
549 split
550 setlocal listchars=tab:[.],lead:#,space:_,trail:.,eol:&
551 split
552 set listchars=tab:+-+,lead:^,space:>,trail:<,eol:%
553 call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
554 close
555 call assert_equal(['[......]##one__two..&'], ScreenLines(1, virtcol('$')))
556 close
557 call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
558 " changing the global setting should not change the local value
559 setglobal listchars=tab:[.],lead:#,space:_,trail:.,eol:&
560 call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
561 set listchars<
562 call assert_equal(['[......]##one__two..&'], ScreenLines(1, virtcol('$')))
563
564 " Using setglobal in a window with local setting should not affect the
565 " window. But should impact other windows using the global setting.
566 enew! | only
567 call setline(1, ["\t one two "])
568 set listchars=tab:[.],lead:#,space:_,trail:.,eol:&
569 split
570 setlocal listchars=tab:+-+,lead:^,space:>,trail:<,eol:%
571 split
572 setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
573 setglobal listchars=tab:{.},lead:-,space:=,trail:#,eol:$
574 call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
575 close
576 call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
577 close
578 call assert_equal(['{......}--one==two##$'], ScreenLines(1, virtcol('$')))
579
580 " Setting the global setting to the default value should not impact a window
zeertzjq7a33ebf2021-11-02 20:56:07 +0000581 " using a local setting.
Bram Moolenaareed9d462021-02-15 20:38:25 +0100582 split
583 setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
584 setglobal listchars&vim
585 call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
586 close
587 call assert_equal(['^I one two $'], ScreenLines(1, virtcol('$')))
588
589 " Setting the local setting to the default value should not impact a window
zeertzjq7a33ebf2021-11-02 20:56:07 +0000590 " using a global setting.
Bram Moolenaareed9d462021-02-15 20:38:25 +0100591 set listchars=tab:{.},lead:-,space:=,trail:#,eol:$
592 split
593 setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
594 call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
595 setlocal listchars&vim
596 call assert_equal(['^I one two $'], ScreenLines(1, virtcol('$')))
597 close
598 call assert_equal(['{......}--one==two##$'], ScreenLines(1, virtcol('$')))
599
600 " Using set in a window with a local setting should change it to use the
zeertzjq7a33ebf2021-11-02 20:56:07 +0000601 " global setting and also impact other windows using the global setting.
Bram Moolenaareed9d462021-02-15 20:38:25 +0100602 split
603 setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
604 call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
605 set listchars=tab:+-+,lead:^,space:>,trail:<,eol:%
606 call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
607 close
608 call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
609
Bram Moolenaar04ea7e92021-02-16 21:14:33 +0100610 " Setting invalid value for a local setting should not impact the local and
zeertzjq7a33ebf2021-11-02 20:56:07 +0000611 " global settings.
Bram Moolenaar04ea7e92021-02-16 21:14:33 +0100612 split
613 setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
614 let cmd = 'setlocal listchars=tab:{.},lead:-,space:=,trail:#,eol:$,x'
615 call assert_fails(cmd, 'E474:')
616 call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
617 close
618 call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
619
620 " Setting invalid value for a global setting should not impact the local and
zeertzjq7a33ebf2021-11-02 20:56:07 +0000621 " global settings.
Bram Moolenaar04ea7e92021-02-16 21:14:33 +0100622 split
623 setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
624 let cmd = 'setglobal listchars=tab:{.},lead:-,space:=,trail:#,eol:$,x'
625 call assert_fails(cmd, 'E474:')
626 call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
627 close
628 call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
629
zeertzjq7a33ebf2021-11-02 20:56:07 +0000630 " Closing window with local lcs-multispace should not cause a memory leak.
631 setlocal listchars=multispace:---+
632 split
633 call s:CheckListCharsValue('multispace:---+')
634 close
635
Bram Moolenaareed9d462021-02-15 20:38:25 +0100636 %bw!
637 set list& listchars&
638endfunc
639
Bram Moolenaar41fb7232021-07-08 12:40:05 +0200640func Test_listchars_foldcolumn()
641 CheckScreendump
642
643 let lines =<< trim END
644 call setline(1, ['aaa', '', 'a', 'aaaaaa'])
645 vsplit
646 vsplit
647 windo set signcolumn=yes foldcolumn=1 winminwidth=0 nowrap list listchars=extends:>,precedes:<
648 END
Bram Moolenaar7dd5a782022-09-29 21:01:57 +0100649 call writefile(lines, 'XTest_listchars', 'D')
Bram Moolenaar41fb7232021-07-08 12:40:05 +0200650
651 let buf = RunVimInTerminal('-S XTest_listchars', {'rows': 10, 'cols': 60})
652
653 call term_sendkeys(buf, "13\<C-W>>")
654 call VerifyScreenDump(buf, 'Test_listchars_01', {})
655 call term_sendkeys(buf, "\<C-W>>")
656 call VerifyScreenDump(buf, 'Test_listchars_02', {})
657 call term_sendkeys(buf, "\<C-W>>")
658 call VerifyScreenDump(buf, 'Test_listchars_03', {})
659 call term_sendkeys(buf, "\<C-W>>")
660 call VerifyScreenDump(buf, 'Test_listchars_04', {})
661 call term_sendkeys(buf, "\<C-W>>")
662 call VerifyScreenDump(buf, 'Test_listchars_05', {})
Bram Moolenaar30441bb2021-07-08 13:19:31 +0200663 call term_sendkeys(buf, "\<C-W>h")
664 call term_sendkeys(buf, ":set nowrap foldcolumn=4\<CR>")
665 call term_sendkeys(buf, "15\<C-W><")
666 call VerifyScreenDump(buf, 'Test_listchars_06', {})
667 call term_sendkeys(buf, "4\<C-W><")
668 call VerifyScreenDump(buf, 'Test_listchars_07', {})
Bram Moolenaar41fb7232021-07-08 12:40:05 +0200669
670 " clean up
671 call StopVimInTerminal(buf)
Bram Moolenaar41fb7232021-07-08 12:40:05 +0200672endfunc
673
zeertzjq08a83a02025-02-20 22:04:09 +0100674func Test_listchars_precedes_with_wide_char()
675 new
676 setlocal nowrap list listchars=eol:$,precedes:!
677 call setline(1, '123口456')
678 call assert_equal(['123口456$ '], ScreenLines(1, 10))
679 let attr = screenattr(1, 9)
zeertzjq13f100e2025-02-21 19:49:44 +0100680
zeertzjq08a83a02025-02-20 22:04:09 +0100681 normal! zl
682 call assert_equal(['!3口456$ '], ScreenLines(1, 10))
683 call assert_equal(attr, screenattr(1, 1))
684 normal! zl
685 call assert_equal(['!口456$ '], ScreenLines(1, 10))
686 call assert_equal(attr, screenattr(1, 1))
687 normal! zl
688 call assert_equal(['!<456$ '], ScreenLines(1, 10))
689 call assert_equal(attr, screenattr(1, 1))
690 call assert_equal(attr, screenattr(1, 2))
691 normal! zl
zeertzjq13f100e2025-02-21 19:49:44 +0100692 call assert_equal(['!456$ '], ScreenLines(1, 10))
zeertzjq08a83a02025-02-20 22:04:09 +0100693 call assert_equal(attr, screenattr(1, 1))
694 normal! zl
695 call assert_equal(['!56$ '], ScreenLines(1, 10))
696 call assert_equal(attr, screenattr(1, 1))
697 normal! zl
698 call assert_equal(['!6$ '], ScreenLines(1, 10))
699 call assert_equal(attr, screenattr(1, 1))
700
701 bw!
702endfunc
Bram Moolenaar41fb7232021-07-08 12:40:05 +0200703
zeertzjq13f100e2025-02-21 19:49:44 +0100704func Test_listchars_precedes_with_tab()
705 new
706 setlocal nowrap list listchars=eol:$,precedes:!,tab:<->
707 call setline(1, "1234\t56")
708 let expected_line = '1234<-->56$ '
709 call assert_equal([expected_line], ScreenLines(1, 12))
710 let expected_attrs = mapnew(range(1, 12), 'screenattr(1, v:val)')
711 let attr = expected_attrs[-2]
712
713 for i in range(8)
714 normal! zl
715 let expected_line = '!' .. expected_line[2:] .. ' '
716 let expected_attrs = [attr] + expected_attrs[2:] + expected_attrs[-1:]
717 call assert_equal([expected_line], ScreenLines(1, 12))
718 let attrs = mapnew(range(1, 12), 'screenattr(1, v:val)')
719 call assert_equal(expected_attrs, attrs)
720 endfor
721
722 bw!
723endfunc
724
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200725" vim: shiftwidth=2 sts=2 expandtab