1" Tests for 'listchars' display with 'list' and :list 2 3source check.vim 4source view_util.vim 5source screendump.vim 6 7func Test_listchars() 8 enew! 9 set ff=unix 10 set list 11 12 set listchars+=tab:>-,space:.,trail:< 13 call append(0, [ 14 \ ' aa ', 15 \ ' bb ', 16 \ ' cccc ', 17 \ 'dd ee ', 18 \ ' ' 19 \ ]) 20 let expected = [ 21 \ '>-------aa>-----$', 22 \ '..bb>---<<$', 23 \ '...cccc><$', 24 \ 'dd........ee<<>-$', 25 \ '<$' 26 \ ] 27 redraw! 28 for i in range(1, 5) 29 call cursor(i, 1) 30 call assert_equal([expected[i - 1]], ScreenLines(i, '$'->virtcol())) 31 endfor 32 33 set listchars-=trail:< 34 let expected = [ 35 \ '>-------aa>-----$', 36 \ '..bb>---..$', 37 \ '...cccc>.$', 38 \ 'dd........ee..>-$', 39 \ '.$' 40 \ ] 41 redraw! 42 for i in range(1, 5) 43 call cursor(i, 1) 44 call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$'))) 45 endfor 46 47 " tab with 3rd character. 48 set listchars-=tab:>- 49 set listchars+=tab:<=>,trail:- 50 let expected = [ 51 \ '<======>aa<====>$', 52 \ '..bb<==>--$', 53 \ '...cccc>-$', 54 \ 'dd........ee--<>$', 55 \ '-$' 56 \ ] 57 redraw! 58 for i in range(1, 5) 59 call cursor(i, 1) 60 call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$'))) 61 endfor 62 63 " tab with 3rd character and linebreak set 64 set listchars-=tab:<=> 65 set listchars+=tab:<·> 66 set linebreak 67 let expected = [ 68 \ '<······>aa<····>$', 69 \ '..bb<··>--$', 70 \ '...cccc>-$', 71 \ 'dd........ee--<>$', 72 \ '-$' 73 \ ] 74 redraw! 75 for i in range(1, 5) 76 call cursor(i, 1) 77 call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$'))) 78 endfor 79 set nolinebreak 80 set listchars-=tab:<·> 81 set listchars+=tab:<=> 82 83 set listchars-=trail:- 84 let expected = [ 85 \ '<======>aa<====>$', 86 \ '..bb<==>..$', 87 \ '...cccc>.$', 88 \ 'dd........ee..<>$', 89 \ '.$' 90 \ ] 91 redraw! 92 for i in range(1, 5) 93 call cursor(i, 1) 94 call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$'))) 95 endfor 96 97 set listchars-=tab:<=> 98 set listchars+=tab:>- 99 set listchars+=trail:< 100 set nolist 101 normal ggdG 102 call append(0, [ 103 \ ' fff ', 104 \ ' gg ', 105 \ ' h ', 106 \ 'iii ', 107 \ ]) 108 let l = split(execute("%list"), "\n") 109 call assert_equal([ 110 \ '..fff>--<<$', 111 \ '>-------gg>-----$', 112 \ '.....h>-$', 113 \ 'iii<<<<><<$', '$'], l) 114 115 " Test lead and trail 116 normal ggdG 117 set listchars& 118 set listchars+=lead:>,trail:<,space:x 119 set list 120 121 call append(0, [ 122 \ ' ffff ', 123 \ ' gg', 124 \ 'h ', 125 \ ' ', 126 \ ' 0 0 ', 127 \ ]) 128 129 let expected = [ 130 \ '>>>>ffff<<<<$', 131 \ '>>>>>>>>>>gg$', 132 \ 'h<<<<<<<<<<<$', 133 \ '<<<<<<<<<<<<$', 134 \ '>>>>0xx0<<<<$', 135 \ '$' 136 \ ] 137 redraw! 138 for i in range(1, 5) 139 call cursor(i, 1) 140 call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$'))) 141 endfor 142 143 call assert_equal(expected, split(execute("%list"), "\n")) 144 145 " Test multispace 146 normal ggdG 147 set listchars& 148 set listchars+=multispace:yYzZ 149 set list 150 151 call append(0, [ 152 \ ' ffff ', 153 \ ' i i gg', 154 \ ' h ', 155 \ ' j ', 156 \ ' 0 0 ', 157 \ ]) 158 159 let expected = [ 160 \ 'yYzZffffyYzZ$', 161 \ 'yYi iyYzZygg$', 162 \ ' hyYzZyYzZyY$', 163 \ 'yYzZyYzZyYj $', 164 \ 'yYzZ0yY0yYzZ$', 165 \ '$' 166 \ ] 167 redraw! 168 for i in range(1, 5) 169 call cursor(i, 1) 170 call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$'))) 171 endfor 172 173 call assert_equal(expected, split(execute("%list"), "\n")) 174 175 " the last occurrence of 'multispace:' is used 176 set listchars+=space:x,multispace:XyY 177 178 let expected = [ 179 \ 'XyYXffffXyYX$', 180 \ 'XyixiXyYXygg$', 181 \ 'xhXyYXyYXyYX$', 182 \ 'XyYXyYXyYXjx$', 183 \ 'XyYX0Xy0XyYX$', 184 \ '$' 185 \ ] 186 redraw! 187 for i in range(1, 5) 188 call cursor(i, 1) 189 call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$'))) 190 endfor 191 192 call assert_equal(expected, split(execute("%list"), "\n")) 193 194 set listchars+=lead:>,trail:< 195 196 let expected = [ 197 \ '>>>>ffff<<<<$', 198 \ '>>ixiXyYXygg$', 199 \ '>h<<<<<<<<<<$', 200 \ '>>>>>>>>>>j<$', 201 \ '>>>>0Xy0<<<<$', 202 \ '$' 203 \ ] 204 redraw! 205 for i in range(1, 5) 206 call cursor(i, 1) 207 call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$'))) 208 endfor 209 210 call assert_equal(expected, split(execute("%list"), "\n")) 211 212 " removing 'multispace:' 213 set listchars-=multispace:XyY 214 set listchars-=multispace:yYzZ 215 216 let expected = [ 217 \ '>>>>ffff<<<<$', 218 \ '>>ixixxxxxgg$', 219 \ '>h<<<<<<<<<<$', 220 \ '>>>>>>>>>>j<$', 221 \ '>>>>0xx0<<<<$', 222 \ '$' 223 \ ] 224 redraw! 225 for i in range(1, 5) 226 call cursor(i, 1) 227 call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$'))) 228 endfor 229 230 call assert_equal(expected, split(execute("%list"), "\n")) 231 232 " test nbsp 233 normal ggdG 234 set listchars=nbsp:X,trail:Y 235 set list 236 " Non-breaking space 237 let nbsp = nr2char(0xa0) 238 call append(0, [ ">" .. nbsp .. "<" ]) 239 240 let expected = '>X< ' 241 242 redraw! 243 call cursor(1, 1) 244 call assert_equal([expected], ScreenLines(1, virtcol('$'))) 245 246 set listchars=nbsp:X 247 redraw! 248 call cursor(1, 1) 249 call assert_equal([expected], ScreenLines(1, virtcol('$'))) 250 251 " test extends 252 normal ggdG 253 set listchars=extends:Z 254 set nowrap 255 set nolist 256 call append(0, [ repeat('A', &columns + 1) ]) 257 258 let expected = repeat('A', &columns) 259 260 redraw! 261 call cursor(1, 1) 262 call assert_equal([expected], ScreenLines(1, &columns)) 263 264 set list 265 let expected = expected[:-2] . 'Z' 266 redraw! 267 call cursor(1, 1) 268 call assert_equal([expected], ScreenLines(1, &columns)) 269 270 enew! 271 set listchars& ff& 272endfunc 273 274" Test that unicode listchars characters get properly inserted 275func Test_listchars_unicode() 276 enew! 277 let oldencoding=&encoding 278 set encoding=utf-8 279 set ff=unix 280 281 set listchars=eol:⇔,space:␣,multispace:≡≢≣,nbsp:≠,tab:←↔→ 282 set list 283 284 let nbsp = nr2char(0xa0) 285 call append(0, [" a\tb c" .. nbsp .. "d "]) 286 let expected = ['≡≢≣≡≢≣≡≢a←↔↔↔↔↔→b␣c≠d≡≢⇔'] 287 redraw! 288 call cursor(1, 1) 289 call assert_equal(expected, ScreenLines(1, virtcol('$'))) 290 291 set listchars+=lead:⇨,trail:⇦ 292 let expected = ['⇨⇨⇨⇨⇨⇨⇨⇨a←↔↔↔↔↔→b␣c≠d⇦⇦⇔'] 293 redraw! 294 call cursor(1, 1) 295 call assert_equal(expected, ScreenLines(1, virtcol('$'))) 296 297 let &encoding=oldencoding 298 enew! 299 set listchars& ff& 300endfunction 301 302func Test_listchars_invalid() 303 enew! 304 set ff=unix 305 306 set listchars& 307 set list 308 set ambiwidth=double 309 310 " No colon 311 call assert_fails('set listchars=x', 'E474:') 312 call assert_fails('set listchars=x', 'E474:') 313 call assert_fails('set listchars=multispace', 'E474:') 314 315 " Too short 316 call assert_fails('set listchars=space:', 'E474:') 317 call assert_fails('set listchars=tab:x', 'E474:') 318 call assert_fails('set listchars=multispace:', 'E474:') 319 320 " One occurrence too short 321 call assert_fails('set listchars=space:,space:x', 'E474:') 322 call assert_fails('set listchars=space:x,space:', 'E474:') 323 call assert_fails('set listchars=tab:x,tab:xx', 'E474:') 324 call assert_fails('set listchars=tab:xx,tab:x', 'E474:') 325 call assert_fails('set listchars=multispace:,multispace:x', 'E474:') 326 call assert_fails('set listchars=multispace:x,multispace:', 'E474:') 327 328 " Too long 329 call assert_fails('set listchars=space:xx', 'E474:') 330 call assert_fails('set listchars=tab:xxxx', 'E474:') 331 332 " Has non-single width character 333 call assert_fails('set listchars=space:·', 'E474:') 334 call assert_fails('set listchars=tab:·x', 'E474:') 335 call assert_fails('set listchars=tab:x·', 'E474:') 336 call assert_fails('set listchars=tab:xx·', 'E474:') 337 call assert_fails('set listchars=multispace:·', 'E474:') 338 call assert_fails('set listchars=multispace:xxx·', 'E474:') 339 340 enew! 341 set ambiwidth& listchars& ff& 342endfunction 343 344" Tests that space characters following composing character won't get replaced 345" by listchars. 346func Test_listchars_composing() 347 enew! 348 let oldencoding=&encoding 349 set encoding=utf-8 350 set ff=unix 351 set list 352 353 set listchars=eol:$,space:_,nbsp:= 354 355 let nbsp1 = nr2char(0xa0) 356 let nbsp2 = nr2char(0x202f) 357 call append(0, [ 358 \ " \u3099\t \u309A" .. nbsp1 .. nbsp1 .. "\u0302" .. nbsp2 .. nbsp2 .. "\u0302", 359 \ ]) 360 let expected = [ 361 \ "_ \u3099^I \u309A=" .. nbsp1 .. "\u0302=" .. nbsp2 .. "\u0302$" 362 \ ] 363 redraw! 364 call cursor(1, 1) 365 call assert_equal(expected, ScreenLines(1, virtcol('$'))) 366 let &encoding=oldencoding 367 enew! 368 set listchars& ff& 369endfunction 370 371" Check for the value of the 'listchars' option 372func s:CheckListCharsValue(expected) 373 call assert_equal(a:expected, &listchars) 374 call assert_equal(a:expected, getwinvar(0, '&listchars')) 375endfunc 376 377" Test for using a window local value for 'listchars' 378func Test_listchars_window_local() 379 %bw! 380 set list listchars& 381 new 382 " set a local value for 'listchars' 383 setlocal listchars=tab:+-,eol:# 384 call s:CheckListCharsValue('tab:+-,eol:#') 385 " When local value is reset, global value should be used 386 setlocal listchars= 387 call s:CheckListCharsValue('eol:$') 388 " Use 'setlocal <' to copy global value 389 setlocal listchars=space:.,extends:> 390 setlocal listchars< 391 call s:CheckListCharsValue('eol:$') 392 " Use 'set <' to copy global value 393 setlocal listchars=space:.,extends:> 394 set listchars< 395 call s:CheckListCharsValue('eol:$') 396 " Changing global setting should not change the local setting 397 setlocal listchars=space:.,extends:> 398 setglobal listchars=tab:+-,eol:# 399 call s:CheckListCharsValue('space:.,extends:>') 400 " when split opening a new window, local value should be copied 401 split 402 call s:CheckListCharsValue('space:.,extends:>') 403 " clearing local value in one window should not change the other window 404 set listchars& 405 call s:CheckListCharsValue('eol:$') 406 close 407 call s:CheckListCharsValue('space:.,extends:>') 408 409 " use different values for 'listchars' items in two different windows 410 call setline(1, ["\t one two "]) 411 setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:# 412 split 413 setlocal listchars=tab:[.],lead:#,space:_,trail:.,eol:& 414 split 415 set listchars=tab:+-+,lead:^,space:>,trail:<,eol:% 416 call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$'))) 417 close 418 call assert_equal(['[......]##one__two..&'], ScreenLines(1, virtcol('$'))) 419 close 420 call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$'))) 421 " changing the global setting should not change the local value 422 setglobal listchars=tab:[.],lead:#,space:_,trail:.,eol:& 423 call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$'))) 424 set listchars< 425 call assert_equal(['[......]##one__two..&'], ScreenLines(1, virtcol('$'))) 426 427 " Using setglobal in a window with local setting should not affect the 428 " window. But should impact other windows using the global setting. 429 enew! | only 430 call setline(1, ["\t one two "]) 431 set listchars=tab:[.],lead:#,space:_,trail:.,eol:& 432 split 433 setlocal listchars=tab:+-+,lead:^,space:>,trail:<,eol:% 434 split 435 setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:# 436 setglobal listchars=tab:{.},lead:-,space:=,trail:#,eol:$ 437 call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$'))) 438 close 439 call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$'))) 440 close 441 call assert_equal(['{......}--one==two##$'], ScreenLines(1, virtcol('$'))) 442 443 " Setting the global setting to the default value should not impact a window 444 " using a local setting 445 split 446 setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:# 447 setglobal listchars&vim 448 call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$'))) 449 close 450 call assert_equal(['^I one two $'], ScreenLines(1, virtcol('$'))) 451 452 " Setting the local setting to the default value should not impact a window 453 " using a global setting 454 set listchars=tab:{.},lead:-,space:=,trail:#,eol:$ 455 split 456 setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:# 457 call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$'))) 458 setlocal listchars&vim 459 call assert_equal(['^I one two $'], ScreenLines(1, virtcol('$'))) 460 close 461 call assert_equal(['{......}--one==two##$'], ScreenLines(1, virtcol('$'))) 462 463 " Using set in a window with a local setting should change it to use the 464 " global setting and also impact other windows using the global setting 465 split 466 setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:# 467 call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$'))) 468 set listchars=tab:+-+,lead:^,space:>,trail:<,eol:% 469 call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$'))) 470 close 471 call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$'))) 472 473 " Setting invalid value for a local setting should not impact the local and 474 " global settings 475 split 476 setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:# 477 let cmd = 'setlocal listchars=tab:{.},lead:-,space:=,trail:#,eol:$,x' 478 call assert_fails(cmd, 'E474:') 479 call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$'))) 480 close 481 call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$'))) 482 483 " Setting invalid value for a global setting should not impact the local and 484 " global settings 485 split 486 setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:# 487 let cmd = 'setglobal listchars=tab:{.},lead:-,space:=,trail:#,eol:$,x' 488 call assert_fails(cmd, 'E474:') 489 call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$'))) 490 close 491 call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$'))) 492 493 %bw! 494 set list& listchars& 495endfunc 496 497func Test_listchars_foldcolumn() 498 CheckScreendump 499 500 let lines =<< trim END 501 call setline(1, ['aaa', '', 'a', 'aaaaaa']) 502 vsplit 503 vsplit 504 windo set signcolumn=yes foldcolumn=1 winminwidth=0 nowrap list listchars=extends:>,precedes:< 505 END 506 call writefile(lines, 'XTest_listchars') 507 508 let buf = RunVimInTerminal('-S XTest_listchars', {'rows': 10, 'cols': 60}) 509 510 call term_sendkeys(buf, "13\<C-W>>") 511 call VerifyScreenDump(buf, 'Test_listchars_01', {}) 512 call term_sendkeys(buf, "\<C-W>>") 513 call VerifyScreenDump(buf, 'Test_listchars_02', {}) 514 call term_sendkeys(buf, "\<C-W>>") 515 call VerifyScreenDump(buf, 'Test_listchars_03', {}) 516 call term_sendkeys(buf, "\<C-W>>") 517 call VerifyScreenDump(buf, 'Test_listchars_04', {}) 518 call term_sendkeys(buf, "\<C-W>>") 519 call VerifyScreenDump(buf, 'Test_listchars_05', {}) 520 call term_sendkeys(buf, "\<C-W>h") 521 call term_sendkeys(buf, ":set nowrap foldcolumn=4\<CR>") 522 call term_sendkeys(buf, "15\<C-W><") 523 call VerifyScreenDump(buf, 'Test_listchars_06', {}) 524 call term_sendkeys(buf, "4\<C-W><") 525 call VerifyScreenDump(buf, 'Test_listchars_07', {}) 526 527 " clean up 528 call StopVimInTerminal(buf) 529 call delete('XTest_listchars') 530endfunc 531 532 533" vim: shiftwidth=2 sts=2 expandtab 534