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, [
197        \ "a\tb c".nbsp."d"
198        \ ])
199  let expected = [
200        \ 'a←↔↔↔↔↔→b␣c≠d⇔'
201        \ ]
202  redraw!
203  call cursor(1, 1)
204  call assert_equal(expected, ScreenLines(1, virtcol('$')))
205  let &encoding=oldencoding
206  enew!
207  set listchars& ff&
208endfunction
209
210" Tests that space characters following composing character won't get replaced
211" by listchars.
212func Test_listchars_composing()
213  enew!
214  let oldencoding=&encoding
215  set encoding=utf-8
216  set ff=unix
217  set list
218
219  set listchars=eol:$,space:_,nbsp:=
220
221  let nbsp1 = nr2char(0xa0)
222  let nbsp2 = nr2char(0x202f)
223  call append(0, [
224        \ "  \u3099\t \u309A".nbsp1.nbsp1."\u0302".nbsp2.nbsp2."\u0302",
225        \ ])
226  let expected = [
227        \ "_ \u3099^I \u309A=".nbsp1."\u0302=".nbsp2."\u0302$"
228        \ ]
229  redraw!
230  call cursor(1, 1)
231  call assert_equal(expected, ScreenLines(1, virtcol('$')))
232  let &encoding=oldencoding
233  enew!
234  set listchars& ff&
235endfunction
236
237" Check for the value of the 'listchars' option
238func s:CheckListCharsValue(expected)
239  call assert_equal(a:expected, &listchars)
240  call assert_equal(a:expected, getwinvar(0, '&listchars'))
241endfunc
242
243" Test for using a window local value for 'listchars'
244func Test_listchars_window_local()
245  %bw!
246  set list listchars&
247  new
248  " set a local value for 'listchars'
249  setlocal listchars=tab:+-,eol:#
250  call s:CheckListCharsValue('tab:+-,eol:#')
251  " When local value is reset, global value should be used
252  setlocal listchars=
253  call s:CheckListCharsValue('eol:$')
254  " Use 'setlocal <' to copy global value
255  setlocal listchars=space:.,extends:>
256  setlocal listchars<
257  call s:CheckListCharsValue('eol:$')
258  " Use 'set <' to copy global value
259  setlocal listchars=space:.,extends:>
260  set listchars<
261  call s:CheckListCharsValue('eol:$')
262  " Changing global setting should not change the local setting
263  setlocal listchars=space:.,extends:>
264  setglobal listchars=tab:+-,eol:#
265  call s:CheckListCharsValue('space:.,extends:>')
266  " when split opening a new window, local value should be copied
267  split
268  call s:CheckListCharsValue('space:.,extends:>')
269  " clearing local value in one window should not change the other window
270  set listchars&
271  call s:CheckListCharsValue('eol:$')
272  close
273  call s:CheckListCharsValue('space:.,extends:>')
274
275  " use different values for 'listchars' items in two different windows
276  call setline(1, ["\t  one  two  "])
277  setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
278  split
279  setlocal listchars=tab:[.],lead:#,space:_,trail:.,eol:&
280  split
281  set listchars=tab:+-+,lead:^,space:>,trail:<,eol:%
282  call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
283  close
284  call assert_equal(['[......]##one__two..&'], ScreenLines(1, virtcol('$')))
285  close
286  call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
287  " changing the global setting should not change the local value
288  setglobal listchars=tab:[.],lead:#,space:_,trail:.,eol:&
289  call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
290  set listchars<
291  call assert_equal(['[......]##one__two..&'], ScreenLines(1, virtcol('$')))
292
293  " Using setglobal in a window with local setting should not affect the
294  " window. But should impact other windows using the global setting.
295  enew! | only
296  call setline(1, ["\t  one  two  "])
297  set listchars=tab:[.],lead:#,space:_,trail:.,eol:&
298  split
299  setlocal listchars=tab:+-+,lead:^,space:>,trail:<,eol:%
300  split
301  setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
302  setglobal listchars=tab:{.},lead:-,space:=,trail:#,eol:$
303  call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
304  close
305  call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
306  close
307  call assert_equal(['{......}--one==two##$'], ScreenLines(1, virtcol('$')))
308
309  " Setting the global setting to the default value should not impact a window
310  " using a local setting
311  split
312  setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
313  setglobal listchars&vim
314  call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
315  close
316  call assert_equal(['^I  one  two  $'], ScreenLines(1, virtcol('$')))
317
318  " Setting the local setting to the default value should not impact a window
319  " using a global setting
320  set listchars=tab:{.},lead:-,space:=,trail:#,eol:$
321  split
322  setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
323  call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
324  setlocal listchars&vim
325  call assert_equal(['^I  one  two  $'], ScreenLines(1, virtcol('$')))
326  close
327  call assert_equal(['{......}--one==two##$'], ScreenLines(1, virtcol('$')))
328
329  " Using set in a window with a local setting should change it to use the
330  " global setting and also impact other windows using the global setting
331  split
332  setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
333  call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
334  set listchars=tab:+-+,lead:^,space:>,trail:<,eol:%
335  call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
336  close
337  call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
338
339  " Setting invalid value for a local setting should not impact the local and
340  " global settings
341  split
342  setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
343  let cmd = 'setlocal listchars=tab:{.},lead:-,space:=,trail:#,eol:$,x'
344  call assert_fails(cmd, 'E474:')
345  call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
346  close
347  call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
348
349  " Setting invalid value for a global setting should not impact the local and
350  " global settings
351  split
352  setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
353  let cmd = 'setglobal listchars=tab:{.},lead:-,space:=,trail:#,eol:$,x'
354  call assert_fails(cmd, 'E474:')
355  call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
356  close
357  call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
358
359  %bw!
360  set list& listchars&
361endfunc
362
363" vim: shiftwidth=2 sts=2 expandtab
364