1" Tests for 'listchars' display with 'list' and :list
2
3source view_util.vim
4
5func Test_listchars()
6  enew!
7  set ff=unix
8  set list
9
10  set listchars+=tab:>-,space:.,trail:<
11  call append(0, [
12	      \ '	aa	',
13	      \ '  bb	  ',
14	      \ '   cccc	 ',
15	      \ 'dd        ee  	',
16	      \ ' '
17	      \ ])
18  let expected = [
19	      \ '>-------aa>-----$',
20	      \ '..bb>---<<$',
21	      \ '...cccc><$',
22	      \ 'dd........ee<<>-$',
23	      \ '<$'
24	      \ ]
25  redraw!
26  for i in range(1, 5)
27    call cursor(i, 1)
28    call assert_equal([expected[i - 1]], ScreenLines(i, '$'->virtcol()))
29  endfor
30
31  set listchars-=trail:<
32  let expected = [
33	      \ '>-------aa>-----$',
34	      \ '..bb>---..$',
35	      \ '...cccc>.$',
36	      \ 'dd........ee..>-$',
37	      \ '.$'
38	      \ ]
39  redraw!
40  for i in range(1, 5)
41    call cursor(i, 1)
42    call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$')))
43  endfor
44
45  " tab with 3rd character.
46  set listchars-=tab:>-
47  set listchars+=tab:<=>,trail:-
48  let expected = [
49	      \ '<======>aa<====>$',
50	      \ '..bb<==>--$',
51	      \ '...cccc>-$',
52	      \ 'dd........ee--<>$',
53	      \ '-$'
54	      \ ]
55  redraw!
56  for i in range(1, 5)
57    call cursor(i, 1)
58    call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$')))
59  endfor
60
61  " tab with 3rd character and linebreak set
62  set listchars-=tab:<=>
63  set listchars+=tab:<·>
64  set linebreak
65  let expected = [
66	      \ '<······>aa<····>$',
67	      \ '..bb<··>--$',
68	      \ '...cccc>-$',
69	      \ 'dd........ee--<>$',
70	      \ '-$'
71	      \ ]
72  redraw!
73  for i in range(1, 5)
74    call cursor(i, 1)
75    call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$')))
76  endfor
77  set nolinebreak
78  set listchars-=tab:<·>
79  set listchars+=tab:<=>
80
81  set listchars-=trail:-
82  let expected = [
83	      \ '<======>aa<====>$',
84	      \ '..bb<==>..$',
85	      \ '...cccc>.$',
86	      \ 'dd........ee..<>$',
87	      \ '.$'
88	      \ ]
89  redraw!
90  for i in range(1, 5)
91    call cursor(i, 1)
92    call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$')))
93  endfor
94
95  set listchars-=tab:<=>
96  set listchars+=tab:>-
97  set listchars+=trail:<
98  set nolist
99  normal ggdG
100  call append(0, [
101	      \ '  fff	  ',
102	      \ '	gg	',
103	      \ '     h	',
104	      \ 'iii    	  ',
105	      \ ])
106  let l = split(execute("%list"), "\n")
107  call assert_equal([
108	      \ '..fff>--<<$',
109	      \ '>-------gg>-----$',
110	      \ '.....h>-$',
111	      \ 'iii<<<<><<$', '$'], l)
112
113  " Test lead and trail
114  normal ggdG
115  set listchars&
116  set listchars+=lead:>,trail:<,space:x
117  set list
118
119  call append(0, [
120	      \ '    ffff    ',
121	      \ '          gg',
122	      \ 'h           ',
123	      \ '            ',
124	      \ '    0  0    ',
125	      \ ])
126
127  let expected = [
128	      \ '>>>>ffff<<<<$',
129	      \ '>>>>>>>>>>gg$',
130	      \ 'h<<<<<<<<<<<$',
131	      \ '<<<<<<<<<<<<$',
132	      \ '>>>>0xx0<<<<$',
133              \ '$'
134	      \ ]
135  redraw!
136  for i in range(1, 5)
137    call cursor(i, 1)
138    call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$')))
139  endfor
140
141  call assert_equal(expected, split(execute("%list"), "\n"))
142
143  " test nbsp
144  normal ggdG
145  set listchars=nbsp:X,trail:Y
146  set list
147  " Non-breaking space
148  let nbsp = nr2char(0xa0)
149  call append(0, [ ">" .. nbsp .. "<" ])
150
151  let expected = '>X< '
152
153  redraw!
154  call cursor(1, 1)
155  call assert_equal([expected], ScreenLines(1, virtcol('$')))
156
157  set listchars=nbsp:X
158  redraw!
159  call cursor(1, 1)
160  call assert_equal([expected], ScreenLines(1, virtcol('$')))
161
162  " test extends
163  normal ggdG
164  set listchars=extends:Z
165  set nowrap
166  set nolist
167  call append(0, [ repeat('A', &columns + 1) ])
168
169  let expected = repeat('A', &columns)
170
171  redraw!
172  call cursor(1, 1)
173  call assert_equal([expected], ScreenLines(1, &columns))
174
175  set list
176  let expected = expected[:-2] . 'Z'
177  redraw!
178  call cursor(1, 1)
179  call assert_equal([expected], ScreenLines(1, &columns))
180
181  enew!
182  set listchars& ff&
183endfunc
184
185" Test that unicode listchars characters get properly inserted
186func Test_listchars_unicode()
187  enew!
188  let oldencoding=&encoding
189  set encoding=utf-8
190  set ff=unix
191
192  set listchars=eol:⇔,space:␣,nbsp:≠,tab:←↔→
193  set list
194
195  let nbsp = nr2char(0xa0)
196  call append(0, ["a\tb c" .. nbsp .. "d"])
197  let expected = ['a←↔↔↔↔↔→b␣c≠d⇔']
198  redraw!
199  call cursor(1, 1)
200  call assert_equal(expected, ScreenLines(1, virtcol('$')))
201  let &encoding=oldencoding
202  enew!
203  set listchars& ff&
204endfunction
205
206" Tests that space characters following composing character won't get replaced
207" by listchars.
208func Test_listchars_composing()
209  enew!
210  let oldencoding=&encoding
211  set encoding=utf-8
212  set ff=unix
213  set list
214
215  set listchars=eol:$,space:_,nbsp:=
216
217  let nbsp1 = nr2char(0xa0)
218  let nbsp2 = nr2char(0x202f)
219  call append(0, [
220        \ "  \u3099\t \u309A" .. nbsp1 .. nbsp1 .. "\u0302" .. nbsp2 .. nbsp2 .. "\u0302",
221        \ ])
222  let expected = [
223        \ "_ \u3099^I \u309A=" .. nbsp1 .. "\u0302=" .. nbsp2 .. "\u0302$"
224        \ ]
225  redraw!
226  call cursor(1, 1)
227  call assert_equal(expected, ScreenLines(1, virtcol('$')))
228  let &encoding=oldencoding
229  enew!
230  set listchars& ff&
231endfunction
232
233" Check for the value of the 'listchars' option
234func s:CheckListCharsValue(expected)
235  call assert_equal(a:expected, &listchars)
236  call assert_equal(a:expected, getwinvar(0, '&listchars'))
237endfunc
238
239" Test for using a window local value for 'listchars'
240func Test_listchars_window_local()
241  %bw!
242  set list listchars&
243  new
244  " set a local value for 'listchars'
245  setlocal listchars=tab:+-,eol:#
246  call s:CheckListCharsValue('tab:+-,eol:#')
247  " When local value is reset, global value should be used
248  setlocal listchars=
249  call s:CheckListCharsValue('eol:$')
250  " Use 'setlocal <' to copy global value
251  setlocal listchars=space:.,extends:>
252  setlocal listchars<
253  call s:CheckListCharsValue('eol:$')
254  " Use 'set <' to copy global value
255  setlocal listchars=space:.,extends:>
256  set listchars<
257  call s:CheckListCharsValue('eol:$')
258  " Changing global setting should not change the local setting
259  setlocal listchars=space:.,extends:>
260  setglobal listchars=tab:+-,eol:#
261  call s:CheckListCharsValue('space:.,extends:>')
262  " when split opening a new window, local value should be copied
263  split
264  call s:CheckListCharsValue('space:.,extends:>')
265  " clearing local value in one window should not change the other window
266  set listchars&
267  call s:CheckListCharsValue('eol:$')
268  close
269  call s:CheckListCharsValue('space:.,extends:>')
270
271  " use different values for 'listchars' items in two different windows
272  call setline(1, ["\t  one  two  "])
273  setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
274  split
275  setlocal listchars=tab:[.],lead:#,space:_,trail:.,eol:&
276  split
277  set listchars=tab:+-+,lead:^,space:>,trail:<,eol:%
278  call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
279  close
280  call assert_equal(['[......]##one__two..&'], ScreenLines(1, virtcol('$')))
281  close
282  call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
283  " changing the global setting should not change the local value
284  setglobal listchars=tab:[.],lead:#,space:_,trail:.,eol:&
285  call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
286  set listchars<
287  call assert_equal(['[......]##one__two..&'], ScreenLines(1, virtcol('$')))
288
289  " Using setglobal in a window with local setting should not affect the
290  " window. But should impact other windows using the global setting.
291  enew! | only
292  call setline(1, ["\t  one  two  "])
293  set listchars=tab:[.],lead:#,space:_,trail:.,eol:&
294  split
295  setlocal listchars=tab:+-+,lead:^,space:>,trail:<,eol:%
296  split
297  setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
298  setglobal listchars=tab:{.},lead:-,space:=,trail:#,eol:$
299  call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
300  close
301  call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
302  close
303  call assert_equal(['{......}--one==two##$'], ScreenLines(1, virtcol('$')))
304
305  " Setting the global setting to the default value should not impact a window
306  " using a local setting
307  split
308  setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
309  setglobal listchars&vim
310  call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
311  close
312  call assert_equal(['^I  one  two  $'], ScreenLines(1, virtcol('$')))
313
314  " Setting the local setting to the default value should not impact a window
315  " using a global setting
316  set listchars=tab:{.},lead:-,space:=,trail:#,eol:$
317  split
318  setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
319  call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
320  setlocal listchars&vim
321  call assert_equal(['^I  one  two  $'], ScreenLines(1, virtcol('$')))
322  close
323  call assert_equal(['{......}--one==two##$'], ScreenLines(1, virtcol('$')))
324
325  " Using set in a window with a local setting should change it to use the
326  " global setting and also impact other windows using the global setting
327  split
328  setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
329  call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
330  set listchars=tab:+-+,lead:^,space:>,trail:<,eol:%
331  call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
332  close
333  call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
334
335  " Setting invalid value for a local setting should not impact the local and
336  " global settings
337  split
338  setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
339  let cmd = 'setlocal listchars=tab:{.},lead:-,space:=,trail:#,eol:$,x'
340  call assert_fails(cmd, 'E474:')
341  call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
342  close
343  call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
344
345  " Setting invalid value for a global setting should not impact the local and
346  " global settings
347  split
348  setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
349  let cmd = 'setglobal listchars=tab:{.},lead:-,space:=,trail:#,eol:$,x'
350  call assert_fails(cmd, 'E474:')
351  call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
352  close
353  call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
354
355  %bw!
356  set list& listchars&
357endfunc
358
359" vim: shiftwidth=2 sts=2 expandtab
360