1" Test 'statusline'
2"
3" Not tested yet:
4"   %a
5"   %N
6"   %T
7"   %X
8
9source view_util.vim
10
11func s:get_statusline()
12  return ScreenLines(&lines - 1, &columns)[0]
13endfunc
14
15func StatuslineWithCaughtError()
16  let s:func_in_statusline_called = 1
17  try
18    call eval('unknown expression')
19  catch
20  endtry
21  return ''
22endfunc
23
24func StatuslineWithError()
25  let s:func_in_statusline_called = 1
26  call eval('unknown expression')
27  return ''
28endfunc
29
30" Function used to display syntax group.
31func SyntaxItem()
32  call assert_equal(s:expected_curbuf, g:actual_curbuf)
33  call assert_equal(s:expected_curwin, g:actual_curwin)
34  return synIDattr(synID(line("."), col("."),1), "name")
35endfunc
36
37func Test_caught_error_in_statusline()
38  let s:func_in_statusline_called = 0
39  set laststatus=2
40  let statusline = '%{StatuslineWithCaughtError()}'
41  let &statusline = statusline
42  redrawstatus
43  call assert_true(s:func_in_statusline_called)
44  call assert_equal(statusline, &statusline)
45  set statusline=
46endfunc
47
48func Test_statusline_will_be_disabled_with_error()
49  let s:func_in_statusline_called = 0
50  set laststatus=2
51  let statusline = '%{StatuslineWithError()}'
52  try
53    let &statusline = statusline
54    redrawstatus
55  catch
56  endtry
57  call assert_true(s:func_in_statusline_called)
58  call assert_equal('', &statusline)
59  set statusline=
60endfunc
61
62func Test_statusline()
63  new Xstatusline
64  only
65  set laststatus=2
66  set splitbelow
67  call setline(1, range(1, 10000))
68
69  " %b: Value of character under cursor.
70  " %B: As above, in hexadecimal.
71  call cursor(9000, 1)
72  set statusline=%b,%B
73  call assert_match('^57,39\s*$', s:get_statusline())
74
75  " %o: Byte number in file of byte under cursor, first byte is 1.
76  " %O: As above, in hexadecimal.
77  set statusline=%o,%O
78  set fileformat=dos
79  call assert_match('^52888,CE98\s*$', s:get_statusline())
80  set fileformat=mac
81  call assert_match('^43889,AB71\s*$', s:get_statusline())
82  set fileformat=unix
83  call assert_match('^43889,AB71\s*$', s:get_statusline())
84  set fileformat&
85
86  " %f: Path to the file in the buffer, as typed or relative to current dir.
87  set statusline=%f
88  call assert_match('^Xstatusline\s*$', s:get_statusline())
89
90  " %F: Full path to the file in the buffer.
91  set statusline=%F
92  call assert_match('/testdir/Xstatusline\s*$', s:get_statusline())
93
94  " %h: Help buffer flag, text is "[help]".
95  " %H: Help buffer flag, text is ",HLP".
96  set statusline=%h,%H
97  call assert_match('^,\s*$', s:get_statusline())
98  help
99  call assert_match('^\[Help\],HLP\s*$', s:get_statusline())
100  helpclose
101
102  " %k: Value of "b:keymap_name" or 'keymap'
103  "     when :lmap mappings are being used: <keymap>"
104  set statusline=%k
105  if has('keymap')
106    set keymap=esperanto
107    call assert_match('^<Eo>\s*$', s:get_statusline())
108    set keymap&
109  else
110    call assert_match('^\s*$', s:get_statusline())
111  endif
112
113  " %l: Line number.
114  " %L: Number of line in buffer.
115  " %c: Column number.
116  set statusline=%l/%L,%c
117  call assert_match('^9000/10000,1\s*$', s:get_statusline())
118
119  " %m: Modified flag, text is "[+]", "[-]" if 'modifiable' is off.
120  " %M: Modified flag, text is ",+" or ",-".
121  set statusline=%m%M
122  call assert_match('^\[+\],+\s*$', s:get_statusline())
123  set nomodifiable
124  call assert_match('^\[+-\],+-\s*$', s:get_statusline())
125  write
126  call assert_match('^\[-\],-\s*$', s:get_statusline())
127  set modifiable&
128  call assert_match('^\s*$', s:get_statusline())
129
130  " %n: Buffer number.
131  set statusline=%n
132  call assert_match('^'.bufnr('%').'\s*$', s:get_statusline())
133
134  " %p: Percentage through file in lines as in CTRL-G.
135  " %P: Percentage through file of displayed window.
136  set statusline=%p,%P
137  0
138  call assert_match('^0,Top\s*$', s:get_statusline())
139  norm G
140  call assert_match('^100,Bot\s*$', s:get_statusline())
141  9000
142  " Don't check the exact percentage as it depends on the window size
143  call assert_match('^90,\(Top\|Bot\|\d\+%\)\s*$', s:get_statusline())
144
145  " %q: "[Quickfix List]", "[Location List]" or empty.
146  set statusline=%q
147  call assert_match('^\s*$', s:get_statusline())
148  copen
149  call assert_match('^\[Quickfix List\]\s*$', s:get_statusline())
150  cclose
151  lexpr getline(1, 2)
152  lopen
153  call assert_match('^\[Location List\]\s*$', s:get_statusline())
154  lclose
155
156  " %r: Readonly flag, text is "[RO]".
157  " %R: Readonly flag, text is ",RO".
158  set statusline=%r,%R
159  call assert_match('^,\s*$', s:get_statusline())
160  help
161  call assert_match('^\[RO\],RO\s*$', s:get_statusline())
162  helpclose
163
164  " %t: File name (tail) of file in the buffer.
165  set statusline=%t
166  call assert_match('^Xstatusline\s*$', s:get_statusline())
167
168  " %v: Virtual column number.
169  " %V: Virtual column number as -{num}. Not displayed if equal to 'c'.
170  call cursor(9000, 2)
171  set statusline=%v,%V
172  call assert_match('^2,\s*$', s:get_statusline())
173  set virtualedit=all
174  norm 10|
175  call assert_match('^10,-10\s*$', s:get_statusline())
176  set virtualedit&
177
178  " %w: Preview window flag, text is "[Preview]".
179  " %W: Preview window flag, text is ",PRV".
180  set statusline=%w%W
181  call assert_match('^\s*$', s:get_statusline())
182  pedit
183  wincmd j
184  call assert_match('^\[Preview\],PRV\s*$', s:get_statusline())
185  pclose
186
187  " %y: Type of file in the buffer, e.g., "[vim]". See 'filetype'.
188  " %Y: Type of file in the buffer, e.g., ",VIM". See 'filetype'.
189  set statusline=%y\ %Y
190  call assert_match('^\s*$', s:get_statusline())
191  setfiletype vim
192  call assert_match('^\[vim\] VIM\s*$', s:get_statusline())
193
194  " %=: Separation point between left and right aligned items.
195  set statusline=foo%=bar
196  call assert_match('^foo\s\+bar\s*$', s:get_statusline())
197
198  " Test min/max width, leading zeroes, left/right justify.
199  set statusline=%04B
200  call cursor(9000, 1)
201  call assert_match('^0039\s*$', s:get_statusline())
202  set statusline=#%4B#
203  call assert_match('^#  39#\s*$', s:get_statusline())
204  set statusline=#%-4B#
205  call assert_match('^#39  #\s*$', s:get_statusline())
206  set statusline=%.6f
207  call assert_match('^<sline\s*$', s:get_statusline())
208
209  " %<: Where to truncate.
210  " First check with when %< should not truncate with many columns
211  exe 'set statusline=a%<b' . repeat('c', &columns - 3) . 'd'
212  call assert_match('^abc\+d$', s:get_statusline())
213  exe 'set statusline=a' . repeat('b', &columns - 2) . '%<c'
214  call assert_match('^ab\+c$', s:get_statusline())
215  " Then check when %< should truncate when there with too few columns.
216  exe 'set statusline=a%<b' . repeat('c', &columns - 2) . 'd'
217  call assert_match('^a<c\+d$', s:get_statusline())
218  exe 'set statusline=a' . repeat('b', &columns - 1) . '%<c'
219  call assert_match('^ab\+>$', s:get_statusline())
220
221  "%{: Evaluate expression between '%{' and '}' and substitute result.
222  syntax on
223  let s:expected_curbuf = string(bufnr(''))
224  let s:expected_curwin = string(win_getid())
225  set statusline=%{SyntaxItem()}
226  call assert_match('^vimNumber\s*$', s:get_statusline())
227  s/^/"/
228  call assert_match('^vimLineComment\s*$', s:get_statusline())
229  syntax off
230
231  "%(: Start of item group.
232  set statusline=ab%(cd%q%)de
233  call assert_match('^abde\s*$', s:get_statusline())
234  copen
235  call assert_match('^abcd\[Quickfix List]de\s*$', s:get_statusline())
236  cclose
237
238  " %#: Set highlight group. The name must follow and then a # again.
239  set statusline=ab%#Todo#cd%#Error#ef
240  call assert_match('^abcdef\s*$', s:get_statusline())
241  let sa1=screenattr(&lines - 1, 1)
242  let sa2=screenattr(&lines - 1, 3)
243  let sa3=screenattr(&lines - 1, 5)
244  call assert_notequal(sa1, sa2)
245  call assert_notequal(sa1, sa3)
246  call assert_notequal(sa2, sa3)
247  call assert_equal(sa1, screenattr(&lines - 1, 2))
248  call assert_equal(sa2, screenattr(&lines - 1, 4))
249  call assert_equal(sa3, screenattr(&lines - 1, 6))
250  call assert_equal(sa3, screenattr(&lines - 1, 7))
251
252  " %*: Set highlight group to User{N}
253  set statusline=a%1*b%0*c
254  call assert_match('^abc\s*$', s:get_statusline())
255  let sa1=screenattr(&lines - 1, 1)
256  let sa2=screenattr(&lines - 1, 2)
257  let sa3=screenattr(&lines - 1, 3)
258  call assert_equal(sa1, sa3)
259  call assert_notequal(sa1, sa2)
260
261  " An empty group that contains highlight changes
262  let g:a = ''
263  set statusline=ab%(cd%1*%{g:a}%*%)de
264  call assert_match('^abde\s*$', s:get_statusline())
265  let sa1=screenattr(&lines - 1, 1)
266  let sa2=screenattr(&lines - 1, 4)
267  call assert_equal(sa1, sa2)
268  let g:a = 'X'
269  call assert_match('^abcdXde\s*$', s:get_statusline())
270  let sa1=screenattr(&lines - 1, 1)
271  let sa2=screenattr(&lines - 1, 5)
272  let sa3=screenattr(&lines - 1, 7)
273  call assert_equal(sa1, sa3)
274  call assert_notequal(sa1, sa2)
275
276  let g:a = ''
277  set statusline=ab%1*%(cd%*%{g:a}%1*%)de
278  call assert_match('^abde\s*$', s:get_statusline())
279  let sa1=screenattr(&lines - 1, 1)
280  let sa2=screenattr(&lines - 1, 4)
281  call assert_notequal(sa1, sa2)
282  let g:a = 'X'
283  call assert_match('^abcdXde\s*$', s:get_statusline())
284  let sa1=screenattr(&lines - 1, 1)
285  let sa2=screenattr(&lines - 1, 3)
286  let sa3=screenattr(&lines - 1, 5)
287  let sa4=screenattr(&lines - 1, 7)
288  call assert_notequal(sa1, sa2)
289  call assert_equal(sa1, sa3)
290  call assert_equal(sa2, sa4)
291
292  " An empty group that contains highlight changes and doesn't reset them
293  let g:a = ''
294  set statusline=ab%(cd%1*%{g:a}%)de
295  call assert_match('^abcdde\s*$', s:get_statusline())
296  let sa1=screenattr(&lines - 1, 1)
297  let sa2=screenattr(&lines - 1, 5)
298  call assert_notequal(sa1, sa2)
299  let g:a = 'X'
300  call assert_match('^abcdXde\s*$', s:get_statusline())
301  let sa1=screenattr(&lines - 1, 1)
302  let sa2=screenattr(&lines - 1, 5)
303  let sa3=screenattr(&lines - 1, 7)
304  call assert_notequal(sa1, sa2)
305  call assert_equal(sa2, sa3)
306
307  let g:a = ''
308  set statusline=ab%1*%(cd%*%{g:a}%)de
309  call assert_match('^abcdde\s*$', s:get_statusline())
310  let sa1=screenattr(&lines - 1, 1)
311  let sa2=screenattr(&lines - 1, 3)
312  let sa3=screenattr(&lines - 1, 5)
313  call assert_notequal(sa1, sa2)
314  call assert_equal(sa1, sa3)
315  let g:a = 'X'
316  call assert_match('^abcdXde\s*$', s:get_statusline())
317  let sa1=screenattr(&lines - 1, 1)
318  let sa2=screenattr(&lines - 1, 3)
319  let sa3=screenattr(&lines - 1, 5)
320  let sa4=screenattr(&lines - 1, 7)
321  call assert_notequal(sa1, sa2)
322  call assert_equal(sa1, sa3)
323  call assert_equal(sa1, sa4)
324
325  let g:a = ''
326  set statusline=%#Error#{%(\ %{g:a}\ %)}
327  call assert_match('^{}\s*$', s:get_statusline())
328  let g:a = 'X'
329  call assert_match('^{ X }\s*$', s:get_statusline())
330
331  " %%: a percent sign.
332  set statusline=10%%
333  call assert_match('^10%\s*$', s:get_statusline())
334
335  " %!: evaluated expression is used as the option value
336  set statusline=%!2*3+1
337  call assert_match('7\s*$', s:get_statusline())
338
339  func GetNested()
340    call assert_equal(string(win_getid()), g:actual_curwin)
341    call assert_equal(string(bufnr('')), g:actual_curbuf)
342    return 'nested'
343  endfunc
344  func GetStatusLine()
345    call assert_equal(win_getid(), g:statusline_winid)
346    return 'the %{GetNested()} line'
347  endfunc
348  set statusline=%!GetStatusLine()
349  call assert_match('the nested line', s:get_statusline())
350  call assert_false(exists('g:actual_curwin'))
351  call assert_false(exists('g:actual_curbuf'))
352  call assert_false(exists('g:statusline_winid'))
353  delfunc GetNested
354  delfunc GetStatusLine
355
356  " Check statusline in current and non-current window
357  " with the 'fillchars' option.
358  set fillchars=stl:^,stlnc:=,vert:\|,fold:-,diff:-
359  vsplit
360  set statusline=x%=y
361  call assert_match('^x^\+y^x=\+y$', s:get_statusline())
362  set fillchars&
363  close
364
365  %bw!
366  call delete('Xstatusline')
367  set statusline&
368  set laststatus&
369  set splitbelow&
370endfunc
371