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