1" Test 'statusline' 2" 3" Not tested yet: 4" %N 5 6source view_util.vim 7source check.vim 8source screendump.vim 9 10func s:get_statusline() 11 return ScreenLines(&lines - 1, &columns)[0] 12endfunc 13 14func StatuslineWithCaughtError() 15 let s:func_in_statusline_called = 1 16 try 17 call eval('unknown expression') 18 catch 19 endtry 20 return '' 21endfunc 22 23func StatuslineWithError() 24 let s:func_in_statusline_called = 1 25 call eval('unknown expression') 26 return '' 27endfunc 28 29" Function used to display syntax group. 30func SyntaxItem() 31 call assert_equal(s:expected_curbuf, g:actual_curbuf) 32 call assert_equal(s:expected_curwin, g:actual_curwin) 33 return synIDattr(synID(line("."), col("."),1), "name") 34endfunc 35 36func Test_caught_error_in_statusline() 37 let s:func_in_statusline_called = 0 38 set laststatus=2 39 let statusline = '%{StatuslineWithCaughtError()}' 40 let &statusline = statusline 41 redrawstatus 42 call assert_true(s:func_in_statusline_called) 43 call assert_equal(statusline, &statusline) 44 set statusline= 45endfunc 46 47func Test_statusline_will_be_disabled_with_error() 48 let s:func_in_statusline_called = 0 49 set laststatus=2 50 let statusline = '%{StatuslineWithError()}' 51 try 52 let &statusline = statusline 53 redrawstatus 54 catch 55 endtry 56 call assert_true(s:func_in_statusline_called) 57 call assert_equal('', &statusline) 58 set statusline= 59endfunc 60 61func Test_statusline() 62 CheckFeature quickfix 63 64 " %a: Argument list ({current} of {max}) 65 set statusline=%a 66 call assert_match('^\s*$', s:get_statusline()) 67 arglocal a1 a2 68 rewind 69 call assert_match('^ (1 of 2)\s*$', s:get_statusline()) 70 next 71 call assert_match('^ (2 of 2)\s*$', s:get_statusline()) 72 e Xstatusline 73 call assert_match('^ ((2) of 2)\s*$', s:get_statusline()) 74 75 only 76 set laststatus=2 77 set splitbelow 78 call setline(1, range(1, 10000)) 79 80 " %b: Value of character under cursor. 81 " %B: As above, in hexadecimal. 82 call cursor(9000, 1) 83 set statusline=%b,%B 84 call assert_match('^57,39\s*$', s:get_statusline()) 85 86 " %o: Byte number in file of byte under cursor, first byte is 1. 87 " %O: As above, in hexadecimal. 88 set statusline=%o,%O 89 set fileformat=dos 90 call assert_match('^52888,CE98\s*$', s:get_statusline()) 91 set fileformat=mac 92 call assert_match('^43889,AB71\s*$', s:get_statusline()) 93 set fileformat=unix 94 call assert_match('^43889,AB71\s*$', s:get_statusline()) 95 set fileformat& 96 97 " %f: Path to the file in the buffer, as typed or relative to current dir. 98 set statusline=%f 99 call assert_match('^Xstatusline\s*$', s:get_statusline()) 100 101 " %F: Full path to the file in the buffer. 102 set statusline=%F 103 call assert_match('/testdir/Xstatusline\s*$', s:get_statusline()) 104 105 " Test for min and max width with %(. For some reason, if this test is moved 106 " after the below test for the help buffer flag, then the code to truncate 107 " the string is not executed. 108 set statusline=%015(%f%) 109 call assert_match('^ Xstatusline\s*$', s:get_statusline()) 110 set statusline=%.6(%f%) 111 call assert_match('^<sline\s*$', s:get_statusline()) 112 set statusline=%14f 113 call assert_match('^ Xstatusline\s*$', s:get_statusline()) 114 set statusline=%.4L 115 call assert_match('^10>3\s*$', s:get_statusline()) 116 117 " %h: Help buffer flag, text is "[help]". 118 " %H: Help buffer flag, text is ",HLP". 119 set statusline=%h,%H 120 call assert_match('^,\s*$', s:get_statusline()) 121 help 122 call assert_match('^\[Help\],HLP\s*$', s:get_statusline()) 123 helpclose 124 125 " %k: Value of "b:keymap_name" or 'keymap' 126 " when :lmap mappings are being used: <keymap>" 127 set statusline=%k 128 if has('keymap') 129 set keymap=esperanto 130 call assert_match('^<Eo>\s*$', s:get_statusline()) 131 set keymap& 132 else 133 call assert_match('^\s*$', s:get_statusline()) 134 endif 135 136 " %l: Line number. 137 " %L: Number of line in buffer. 138 " %c: Column number. 139 set statusline=%l/%L,%c 140 call assert_match('^9000/10000,1\s*$', s:get_statusline()) 141 142 " %m: Modified flag, text is "[+]", "[-]" if 'modifiable' is off. 143 " %M: Modified flag, text is ",+" or ",-". 144 set statusline=%m%M 145 call assert_match('^\[+\],+\s*$', s:get_statusline()) 146 set nomodifiable 147 call assert_match('^\[+-\],+-\s*$', s:get_statusline()) 148 write 149 call assert_match('^\[-\],-\s*$', s:get_statusline()) 150 set modifiable& 151 call assert_match('^\s*$', s:get_statusline()) 152 153 " %n: Buffer number. 154 set statusline=%n 155 call assert_match('^'.bufnr('%').'\s*$', s:get_statusline()) 156 157 " %p: Percentage through file in lines as in CTRL-G. 158 " %P: Percentage through file of displayed window. 159 set statusline=%p,%P 160 0 161 call assert_match('^0,Top\s*$', s:get_statusline()) 162 norm G 163 call assert_match('^100,Bot\s*$', s:get_statusline()) 164 9000 165 " Don't check the exact percentage as it depends on the window size 166 call assert_match('^90,\(Top\|Bot\|\d\+%\)\s*$', s:get_statusline()) 167 168 " %q: "[Quickfix List]", "[Location List]" or empty. 169 set statusline=%q 170 call assert_match('^\s*$', s:get_statusline()) 171 copen 172 call assert_match('^\[Quickfix List\]\s*$', s:get_statusline()) 173 cclose 174 lexpr getline(1, 2) 175 lopen 176 call assert_match('^\[Location List\]\s*$', s:get_statusline()) 177 lclose 178 179 " %r: Readonly flag, text is "[RO]". 180 " %R: Readonly flag, text is ",RO". 181 set statusline=%r,%R 182 call assert_match('^,\s*$', s:get_statusline()) 183 help 184 call assert_match('^\[RO\],RO\s*$', s:get_statusline()) 185 helpclose 186 187 " %t: File name (tail) of file in the buffer. 188 set statusline=%t 189 call assert_match('^Xstatusline\s*$', s:get_statusline()) 190 191 " %v: Virtual column number. 192 " %V: Virtual column number as -{num}. Not displayed if equal to 'c'. 193 call cursor(9000, 2) 194 set statusline=%v,%V 195 call assert_match('^2,\s*$', s:get_statusline()) 196 set virtualedit=all 197 norm 10| 198 call assert_match('^10,-10\s*$', s:get_statusline()) 199 set virtualedit& 200 201 " %w: Preview window flag, text is "[Preview]". 202 " %W: Preview window flag, text is ",PRV". 203 set statusline=%w%W 204 call assert_match('^\s*$', s:get_statusline()) 205 pedit 206 wincmd j 207 call assert_match('^\[Preview\],PRV\s*$', s:get_statusline()) 208 pclose 209 210 " %y: Type of file in the buffer, e.g., "[vim]". See 'filetype'. 211 " %Y: Type of file in the buffer, e.g., ",VIM". See 'filetype'. 212 set statusline=%y\ %Y 213 call assert_match('^\s*$', s:get_statusline()) 214 setfiletype vim 215 call assert_match('^\[vim\] VIM\s*$', s:get_statusline()) 216 217 " %=: Separation point between left and right aligned items. 218 set statusline=foo%=bar 219 call assert_match('^foo\s\+bar\s*$', s:get_statusline()) 220 221 " Test min/max width, leading zeroes, left/right justify. 222 set statusline=%04B 223 call cursor(9000, 1) 224 call assert_match('^0039\s*$', s:get_statusline()) 225 set statusline=#%4B# 226 call assert_match('^# 39#\s*$', s:get_statusline()) 227 set statusline=#%-4B# 228 call assert_match('^#39 #\s*$', s:get_statusline()) 229 set statusline=%.6f 230 call assert_match('^<sline\s*$', s:get_statusline()) 231 232 " %<: Where to truncate. 233 " First check with when %< should not truncate with many columns 234 exe 'set statusline=a%<b' . repeat('c', &columns - 3) . 'd' 235 call assert_match('^abc\+d$', s:get_statusline()) 236 exe 'set statusline=a' . repeat('b', &columns - 2) . '%<c' 237 call assert_match('^ab\+c$', s:get_statusline()) 238 " Then check when %< should truncate when there with too few columns. 239 exe 'set statusline=a%<b' . repeat('c', &columns - 2) . 'd' 240 call assert_match('^a<c\+d$', s:get_statusline()) 241 exe 'set statusline=a' . repeat('b', &columns - 1) . '%<c' 242 call assert_match('^ab\+>$', s:get_statusline()) 243 244 "%{: Evaluate expression between '%{' and '}' and substitute result. 245 syntax on 246 let s:expected_curbuf = string(bufnr('')) 247 let s:expected_curwin = string(win_getid()) 248 set statusline=%{SyntaxItem()} 249 call assert_match('^vimNumber\s*$', s:get_statusline()) 250 s/^/"/ 251 call assert_match('^vimLineComment\s*$', s:get_statusline()) 252 syntax off 253 254 "%(: Start of item group. 255 set statusline=ab%(cd%q%)de 256 call assert_match('^abde\s*$', s:get_statusline()) 257 copen 258 call assert_match('^abcd\[Quickfix List]de\s*$', s:get_statusline()) 259 cclose 260 261 " %#: Set highlight group. The name must follow and then a # again. 262 set statusline=ab%#Todo#cd%#Error#ef 263 call assert_match('^abcdef\s*$', s:get_statusline()) 264 let sa1=screenattr(&lines - 1, 1) 265 let sa2=screenattr(&lines - 1, 3) 266 let sa3=screenattr(&lines - 1, 5) 267 call assert_notequal(sa1, sa2) 268 call assert_notequal(sa1, sa3) 269 call assert_notequal(sa2, sa3) 270 call assert_equal(sa1, screenattr(&lines - 1, 2)) 271 call assert_equal(sa2, screenattr(&lines - 1, 4)) 272 call assert_equal(sa3, screenattr(&lines - 1, 6)) 273 call assert_equal(sa3, screenattr(&lines - 1, 7)) 274 275 " %*: Set highlight group to User{N} 276 set statusline=a%1*b%0*c 277 call assert_match('^abc\s*$', s:get_statusline()) 278 let sa1=screenattr(&lines - 1, 1) 279 let sa2=screenattr(&lines - 1, 2) 280 let sa3=screenattr(&lines - 1, 3) 281 call assert_equal(sa1, sa3) 282 call assert_notequal(sa1, sa2) 283 284 " An empty group that contains highlight changes 285 let g:a = '' 286 set statusline=ab%(cd%1*%{g:a}%*%)de 287 call assert_match('^abde\s*$', s:get_statusline()) 288 let sa1=screenattr(&lines - 1, 1) 289 let sa2=screenattr(&lines - 1, 4) 290 call assert_equal(sa1, sa2) 291 let g:a = 'X' 292 call assert_match('^abcdXde\s*$', s:get_statusline()) 293 let sa1=screenattr(&lines - 1, 1) 294 let sa2=screenattr(&lines - 1, 5) 295 let sa3=screenattr(&lines - 1, 7) 296 call assert_equal(sa1, sa3) 297 call assert_notequal(sa1, sa2) 298 299 let g:a = '' 300 set statusline=ab%1*%(cd%*%{g:a}%1*%)de 301 call assert_match('^abde\s*$', s:get_statusline()) 302 let sa1=screenattr(&lines - 1, 1) 303 let sa2=screenattr(&lines - 1, 4) 304 call assert_notequal(sa1, sa2) 305 let g:a = 'X' 306 call assert_match('^abcdXde\s*$', s:get_statusline()) 307 let sa1=screenattr(&lines - 1, 1) 308 let sa2=screenattr(&lines - 1, 3) 309 let sa3=screenattr(&lines - 1, 5) 310 let sa4=screenattr(&lines - 1, 7) 311 call assert_notequal(sa1, sa2) 312 call assert_equal(sa1, sa3) 313 call assert_equal(sa2, sa4) 314 315 " An empty group that contains highlight changes and doesn't reset them 316 let g:a = '' 317 set statusline=ab%(cd%1*%{g:a}%)de 318 call assert_match('^abcdde\s*$', s:get_statusline()) 319 let sa1=screenattr(&lines - 1, 1) 320 let sa2=screenattr(&lines - 1, 5) 321 call assert_notequal(sa1, sa2) 322 let g:a = 'X' 323 call assert_match('^abcdXde\s*$', s:get_statusline()) 324 let sa1=screenattr(&lines - 1, 1) 325 let sa2=screenattr(&lines - 1, 5) 326 let sa3=screenattr(&lines - 1, 7) 327 call assert_notequal(sa1, sa2) 328 call assert_equal(sa2, sa3) 329 330 let g:a = '' 331 set statusline=ab%1*%(cd%*%{g:a}%)de 332 call assert_match('^abcdde\s*$', s:get_statusline()) 333 let sa1=screenattr(&lines - 1, 1) 334 let sa2=screenattr(&lines - 1, 3) 335 let sa3=screenattr(&lines - 1, 5) 336 call assert_notequal(sa1, sa2) 337 call assert_equal(sa1, sa3) 338 let g:a = 'X' 339 call assert_match('^abcdXde\s*$', s:get_statusline()) 340 let sa1=screenattr(&lines - 1, 1) 341 let sa2=screenattr(&lines - 1, 3) 342 let sa3=screenattr(&lines - 1, 5) 343 let sa4=screenattr(&lines - 1, 7) 344 call assert_notequal(sa1, sa2) 345 call assert_equal(sa1, sa3) 346 call assert_equal(sa1, sa4) 347 348 let g:a = '' 349 set statusline=%#Error#{%(\ %{g:a}\ %)} 350 call assert_match('^{}\s*$', s:get_statusline()) 351 let g:a = 'X' 352 call assert_match('^{ X }\s*$', s:get_statusline()) 353 354 " %%: a percent sign. 355 set statusline=10%% 356 call assert_match('^10%\s*$', s:get_statusline()) 357 358 " %!: evaluated expression is used as the option value 359 set statusline=%!2*3+1 360 call assert_match('7\s*$', s:get_statusline()) 361 362 func GetNested() 363 call assert_equal(string(win_getid()), g:actual_curwin) 364 call assert_equal(string(bufnr('')), g:actual_curbuf) 365 return 'nested' 366 endfunc 367 func GetStatusLine() 368 call assert_equal(win_getid(), g:statusline_winid) 369 return 'the %{GetNested()} line' 370 endfunc 371 set statusline=%!GetStatusLine() 372 call assert_match('the nested line', s:get_statusline()) 373 call assert_false(exists('g:actual_curwin')) 374 call assert_false(exists('g:actual_curbuf')) 375 call assert_false(exists('g:statusline_winid')) 376 delfunc GetNested 377 delfunc GetStatusLine 378 379 " Test statusline works with 80+ items 380 function! StatusLabel() 381 redrawstatus 382 return '[label]' 383 endfunc 384 let statusline = '%{StatusLabel()}' 385 for i in range(150) 386 let statusline .= '%#TabLine' . (i % 2 == 0 ? 'Fill' : 'Sel') . '#' . string(i)[0] 387 endfor 388 let &statusline = statusline 389 redrawstatus 390 set statusline& 391 delfunc StatusLabel 392 393 394 " Check statusline in current and non-current window 395 " with the 'fillchars' option. 396 set fillchars=stl:^,stlnc:=,vert:\|,fold:-,diff:- 397 vsplit 398 set statusline=x%=y 399 call assert_match('^x^\+y^x=\+y$', s:get_statusline()) 400 set fillchars& 401 close 402 403 %bw! 404 call delete('Xstatusline') 405 set statusline& 406 set laststatus& 407 set splitbelow& 408endfunc 409 410func Test_statusline_visual() 411 func CallWordcount() 412 call wordcount() 413 endfunc 414 new x1 415 setl statusline=count=%{CallWordcount()} 416 " buffer must not be empty 417 call setline(1, 'hello') 418 419 " window with more lines than x1 420 new x2 421 call setline(1, range(10)) 422 $ 423 " Visual mode in line below liast line in x1 should not give ml_get error 424 call feedkeys("\<C-V>", "xt") 425 redraw 426 427 delfunc CallWordcount 428 bwipe! x1 429 bwipe! x2 430endfunc 431 432func Test_statusline_removed_group() 433 CheckScreendump 434 435 let lines =<< trim END 436 scriptencoding utf-8 437 set laststatus=2 438 let &statusline = '%#StatColorHi2#%(✓%#StatColorHi2#%) Q≡' 439 END 440 call writefile(lines, 'XTest_statusline') 441 442 let buf = RunVimInTerminal('-S XTest_statusline', {'rows': 10, 'cols': 50}) 443 call TermWait(buf, 50) 444 call VerifyScreenDump(buf, 'Test_statusline_1', {}) 445 446 " clean up 447 call StopVimInTerminal(buf) 448 call delete('XTest_statusline') 449endfunc 450 451func Test_statusline_after_split_vsplit() 452 only 453 454 " Make the status line of each window show the window number. 455 set ls=2 stl=%{winnr()} 456 457 split | redraw 458 vsplit | redraw 459 460 " The status line of the third window should read '3' here. 461 call assert_equal('3', nr2char(screenchar(&lines - 1, 1))) 462 463 only 464 set ls& stl& 465endfunc 466 467 468" vim: shiftwidth=2 sts=2 expandtab 469