1" Test for syntax and syntax iskeyword option 2 3source check.vim 4CheckFeature syntax 5 6source view_util.vim 7source screendump.vim 8 9func GetSyntaxItem(pat) 10 let c = '' 11 let a = ['a', getreg('a'), getregtype('a')] 12 0 13 redraw! 14 call search(a:pat, 'W') 15 let synid = synID(line('.'), col('.'), 1) 16 while synid == synID(line('.'), col('.'), 1) 17 norm! v"ay 18 " stop at whitespace 19 if @a =~# '\s' 20 break 21 endif 22 let c .= @a 23 norm! l 24 endw 25 call call('setreg', a) 26 0 27 return c 28endfunc 29 30func Test_syn_iskeyword() 31 new 32 call setline(1, [ 33 \ 'CREATE TABLE FOOBAR(', 34 \ ' DLTD_BY VARCHAR2(100)', 35 \ ');', 36 \ '']) 37 38 syntax on 39 set ft=sql 40 syn match SYN /C\k\+\>/ 41 hi link SYN ErrorMsg 42 call assert_equal('DLTD_BY', GetSyntaxItem('DLTD')) 43 /\<D\k\+\>/:norm! ygn 44 call assert_equal('DLTD_BY', @0) 45 redir @c 46 syn iskeyword 47 redir END 48 call assert_equal("\nsyntax iskeyword not set", @c) 49 50 syn iskeyword @,48-57,_,192-255 51 redir @c 52 syn iskeyword 53 redir END 54 call assert_equal("\nsyntax iskeyword @,48-57,_,192-255", @c) 55 56 setlocal isk-=_ 57 call assert_equal('DLTD_BY', GetSyntaxItem('DLTD')) 58 /\<D\k\+\>/:norm! ygn 59 let b2 = @0 60 call assert_equal('DLTD', @0) 61 62 syn iskeyword clear 63 redir @c 64 syn iskeyword 65 redir END 66 call assert_equal("\nsyntax iskeyword not set", @c) 67 68 quit! 69endfunc 70 71func Test_syntax_after_reload() 72 split Xsomefile 73 call setline(1, ['hello', 'there']) 74 w! 75 only! 76 setl filetype=hello 77 au FileType hello let g:gotit = 1 78 call assert_false(exists('g:gotit')) 79 edit other 80 buf Xsomefile 81 call assert_equal('hello', &filetype) 82 call assert_true(exists('g:gotit')) 83 call delete('Xsomefile') 84endfunc 85 86func Test_syntime() 87 if !has('profile') 88 return 89 endif 90 91 syntax on 92 syntime on 93 let a = execute('syntime report') 94 call assert_equal("\nNo Syntax items defined for this buffer", a) 95 96 view ../memfile_test.c 97 setfiletype cpp 98 redraw 99 let a = execute('syntime report') 100 call assert_match('^ TOTAL *COUNT *MATCH *SLOWEST *AVERAGE *NAME *PATTERN', a) 101 call assert_match(' \d*\.\d* \+[^0]\d* .* cppRawString ', a) 102 call assert_match(' \d*\.\d* \+[^0]\d* .* cppNumber ', a) 103 104 syntime off 105 syntime clear 106 let a = execute('syntime report') 107 call assert_match('^ TOTAL *COUNT *MATCH *SLOWEST *AVERAGE *NAME *PATTERN', a) 108 call assert_notmatch('.* cppRawString *', a) 109 call assert_notmatch('.* cppNumber*', a) 110 call assert_notmatch('[1-9]', a) 111 112 call assert_fails('syntime abc', 'E475') 113 114 syntax clear 115 let a = execute('syntime report') 116 call assert_equal("\nNo Syntax items defined for this buffer", a) 117 118 bd 119endfunc 120 121func Test_syntime_completion() 122 if !has('profile') 123 return 124 endif 125 126 call feedkeys(":syntime \<C-A>\<C-B>\"\<CR>", 'tx') 127 call assert_equal('"syntime clear off on report', @:) 128endfunc 129 130func Test_syntax_list() 131 syntax on 132 let a = execute('syntax list') 133 call assert_equal("\nNo Syntax items defined for this buffer", a) 134 135 view ../memfile_test.c 136 setfiletype c 137 138 let a = execute('syntax list') 139 call assert_match('cInclude*', a) 140 call assert_match('cDefine', a) 141 142 let a = execute('syntax list cDefine') 143 call assert_notmatch('cInclude*', a) 144 call assert_match('cDefine', a) 145 call assert_match(' links to Macro$', a) 146 147 call assert_fails('syntax list ABCD', 'E28:') 148 call assert_fails('syntax list @ABCD', 'E392:') 149 150 syntax clear 151 let a = execute('syntax list') 152 call assert_equal("\nNo Syntax items defined for this buffer", a) 153 154 bd 155endfunc 156 157func Test_syntax_completion() 158 call feedkeys(":syn \<C-A>\<C-B>\"\<CR>", 'tx') 159 call assert_equal('"syn case clear cluster conceal enable include iskeyword keyword list manual match off on region reset spell sync', @:) 160 161 call feedkeys(":syn case \<C-A>\<C-B>\"\<CR>", 'tx') 162 call assert_equal('"syn case ignore match', @:) 163 164 call feedkeys(":syn spell \<C-A>\<C-B>\"\<CR>", 'tx') 165 call assert_equal('"syn spell default notoplevel toplevel', @:) 166 167 call feedkeys(":syn sync \<C-A>\<C-B>\"\<CR>", 'tx') 168 call assert_equal('"syn sync ccomment clear fromstart linebreaks= linecont lines= match maxlines= minlines= region', @:) 169 170 " Check that clearing "Aap" avoids it showing up before Boolean. 171 hi Aap ctermfg=blue 172 call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx') 173 call assert_match('^"syn list Aap Boolean Character ', @:) 174 hi clear Aap 175 176 call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx') 177 call assert_match('^"syn list Boolean Character ', @:) 178 179 call feedkeys(":syn match \<C-A>\<C-B>\"\<CR>", 'tx') 180 call assert_match('^"syn match Boolean Character ', @:) 181endfunc 182 183func Test_syntax_arg_skipped() 184 syn clear 185 syntax case ignore 186 if 0 187 syntax case match 188 endif 189 call assert_match('case ignore', execute('syntax case')) 190 191 syn keyword Foo foo 192 call assert_match('Foo', execute('syntax')) 193 syn clear 194 call assert_match('case match', execute('syntax case')) 195 call assert_notmatch('Foo', execute('syntax')) 196 197 if has('conceal') 198 syn clear 199 syntax conceal on 200 if 0 201 syntax conceal off 202 endif 203 call assert_match('conceal on', execute('syntax conceal')) 204 syn clear 205 call assert_match('conceal off', execute('syntax conceal')) 206 207 syntax conceal on 208 syntax conceal off 209 call assert_match('conceal off', execute('syntax conceal')) 210 endif 211 212 syntax region Bar start=/</ end=/>/ 213 if 0 214 syntax region NotTest start=/</ end=/>/ contains=@Spell 215 endif 216 call assert_match('Bar', execute('syntax')) 217 call assert_notmatch('NotTest', execute('syntax')) 218 call assert_notmatch('Spell', execute('syntax')) 219 220 hi Foo ctermfg=blue 221 let a = execute('hi Foo') 222 if 0 223 syntax rest 224 endif 225 call assert_equal(a, execute('hi Foo')) 226 hi clear Bar 227 hi clear Foo 228 229 set ft=tags 230 syn off 231 if 0 232 syntax enable 233 endif 234 call assert_match('No Syntax items defined', execute('syntax')) 235 syntax enable 236 call assert_match('tagComment', execute('syntax')) 237 set ft= 238 239 syn clear 240 if 0 241 syntax include @Spell nothing 242 endif 243 call assert_notmatch('Spell', execute('syntax')) 244 245 syn clear 246 syn iskeyword 48-57,$,_ 247 call assert_match('48-57,$,_', execute('syntax iskeyword')) 248 if 0 249 syn clear 250 syn iskeyword clear 251 endif 252 call assert_match('48-57,$,_', execute('syntax iskeyword')) 253 syn iskeyword clear 254 call assert_match('not set', execute('syntax iskeyword')) 255 syn iskeyword 48-57,$,_ 256 syn clear 257 call assert_match('not set', execute('syntax iskeyword')) 258 259 syn clear 260 syn keyword Foo foo 261 if 0 262 syn keyword NotAdded bar 263 endif 264 call assert_match('Foo', execute('syntax')) 265 call assert_notmatch('NotAdded', execute('highlight')) 266 267 syn clear 268 syn keyword Foo foo 269 call assert_match('Foo', execute('syntax')) 270 call assert_match('Foo', execute('syntax list')) 271 call assert_notmatch('Foo', execute('if 0 | syntax | endif')) 272 call assert_notmatch('Foo', execute('if 0 | syntax list | endif')) 273 274 syn clear 275 syn match Fopi /asdf/ 276 if 0 277 syn match Fopx /asdf/ 278 endif 279 call assert_match('Fopi', execute('syntax')) 280 call assert_notmatch('Fopx', execute('syntax')) 281 282 syn clear 283 syn spell toplevel 284 call assert_match('spell toplevel', execute('syntax spell')) 285 if 0 286 syn spell notoplevel 287 endif 288 call assert_match('spell toplevel', execute('syntax spell')) 289 syn spell notoplevel 290 call assert_match('spell notoplevel', execute('syntax spell')) 291 syn spell default 292 call assert_match('spell default', execute('syntax spell')) 293 294 syn clear 295 if 0 296 syntax cluster Spell 297 endif 298 call assert_notmatch('Spell', execute('syntax')) 299 300 syn clear 301 syn keyword Foo foo 302 syn sync ccomment 303 syn sync maxlines=5 304 if 0 305 syn sync maxlines=11 306 endif 307 call assert_match('on C-style comments', execute('syntax sync')) 308 call assert_match('maximal 5 lines', execute('syntax sync')) 309 syn sync clear 310 if 0 311 syn sync ccomment 312 endif 313 call assert_notmatch('on C-style comments', execute('syntax sync')) 314 315 syn clear 316endfunc 317 318func Test_syntax_invalid_arg() 319 call assert_fails('syntax case asdf', 'E390:') 320 if has('conceal') 321 call assert_fails('syntax conceal asdf', 'E390:') 322 endif 323 call assert_fails('syntax spell asdf', 'E390:') 324 call assert_fails('syntax clear @ABCD', 'E391:') 325 call assert_fails('syntax include @Xxx', 'E397:') 326 call assert_fails('syntax region X start="{"', 'E399:') 327 call assert_fails('syntax sync x', 'E404:') 328 call assert_fails('syntax keyword Abc a[', 'E789:') 329 call assert_fails('syntax keyword Abc a[bc]d', 'E890:') 330endfunc 331 332func Test_syn_sync() 333 syntax region HereGroup start=/this/ end=/that/ 334 syntax sync match SyncHere grouphere HereGroup "pattern" 335 call assert_match('SyncHere', execute('syntax sync')) 336 syn sync clear 337 call assert_notmatch('SyncHere', execute('syntax sync')) 338 syn clear 339endfunc 340 341func Test_syn_clear() 342 syntax keyword Foo foo 343 syntax keyword Bar tar 344 call assert_match('Foo', execute('syntax')) 345 call assert_match('Bar', execute('syntax')) 346 call assert_equal('Foo', synIDattr(hlID("Foo"), "name")) 347 syn clear Foo 348 call assert_notmatch('Foo', execute('syntax')) 349 call assert_match('Bar', execute('syntax')) 350 call assert_equal('Foo', synIDattr(hlID("Foo"), "name")) 351 syn clear Foo Bar 352 call assert_notmatch('Foo', execute('syntax')) 353 call assert_notmatch('Bar', execute('syntax')) 354 hi clear Foo 355 call assert_equal('Foo', synIDattr(hlID("Foo"), "name")) 356 hi clear Bar 357endfunc 358 359func Test_invalid_name() 360 syn clear 361 syn keyword Nop yes 362 call assert_fails("syntax keyword Wr\x17ong bar", 'E669:') 363 syntax keyword @Wrong bar 364 call assert_match('W18:', execute('1messages')) 365 syn clear 366 hi clear Nop 367 hi clear @Wrong 368endfunc 369 370func Test_ownsyntax() 371 new Xfoo 372 call setline(1, '#define FOO') 373 syntax on 374 set filetype=c 375 ownsyntax perl 376 call assert_equal('perlComment', synIDattr(synID(line('.'), col('.'), 1), 'name')) 377 call assert_equal('c', b:current_syntax) 378 call assert_equal('perl', w:current_syntax) 379 380 " A new split window should have the original syntax. 381 split 382 call assert_equal('cDefine', synIDattr(synID(line('.'), col('.'), 1), 'name')) 383 call assert_equal('c', b:current_syntax) 384 call assert_equal(0, exists('w:current_syntax')) 385 386 wincmd x 387 call assert_equal('perlComment', synIDattr(synID(line("."), col("."), 1), "name")) 388 389 syntax off 390 set filetype& 391 %bw! 392endfunc 393 394func Test_ownsyntax_completion() 395 call feedkeys(":ownsyntax java\<C-A>\<C-B>\"\<CR>", 'tx') 396 call assert_equal('"ownsyntax java javacc javascript javascriptreact', @:) 397endfunc 398 399func Test_highlight_invalid_arg() 400 if has('gui_running') 401 call assert_fails('hi XXX guifg=xxx', 'E254:') 402 endif 403 call assert_fails('hi DoesNotExist', 'E411:') 404 call assert_fails('hi link', 'E412:') 405 call assert_fails('hi link a', 'E412:') 406 call assert_fails('hi link a b c', 'E413:') 407 call assert_fails('hi XXX =', 'E415:') 408 call assert_fails('hi XXX cterm', 'E416:') 409 call assert_fails('hi XXX cterm=', 'E417:') 410 call assert_fails('hi XXX cterm=DoesNotExist', 'E418:') 411 call assert_fails('hi XXX ctermfg=DoesNotExist', 'E421:') 412 call assert_fails('hi XXX xxx=White', 'E423:') 413endfunc 414 415func Test_bg_detection() 416 CheckNotGui 417 418 " auto-detection of &bg, make sure sure it isn't set anywhere before 419 " this test 420 hi Normal ctermbg=0 421 call assert_equal('dark', &bg) 422 hi Normal ctermbg=4 423 call assert_equal('dark', &bg) 424 hi Normal ctermbg=12 425 call assert_equal('light', &bg) 426 hi Normal ctermbg=15 427 call assert_equal('light', &bg) 428 429 " manually-set &bg takes precedence over auto-detection 430 set bg=light 431 hi Normal ctermbg=4 432 call assert_equal('light', &bg) 433 set bg=dark 434 hi Normal ctermbg=12 435 call assert_equal('dark', &bg) 436 437 hi Normal ctermbg=NONE 438endfunc 439 440func Test_syntax_hangs() 441 if !has('reltime') || !has('float') || !has('syntax') 442 return 443 endif 444 445 " This pattern takes a long time to match, it should timeout. 446 new 447 call setline(1, ['aaa', repeat('abc ', 1000), 'ccc']) 448 let start = reltime() 449 set nolazyredraw redrawtime=101 450 syn match Error /\%#=1a*.*X\@<=b*/ 451 redraw 452 let elapsed = reltimefloat(reltime(start)) 453 call assert_true(elapsed > 0.1) 454 call assert_true(elapsed < 1.0) 455 456 " second time syntax HL is disabled 457 let start = reltime() 458 redraw 459 let elapsed = reltimefloat(reltime(start)) 460 call assert_true(elapsed < 0.1) 461 462 " after CTRL-L the timeout flag is reset 463 let start = reltime() 464 exe "normal \<C-L>" 465 redraw 466 let elapsed = reltimefloat(reltime(start)) 467 call assert_true(elapsed > 0.1) 468 call assert_true(elapsed < 1.0) 469 470 set redrawtime& 471 bwipe! 472endfunc 473 474func Test_conceal() 475 if !has('conceal') 476 return 477 endif 478 479 new 480 call setline(1, ['', '123456']) 481 syn match test23 "23" conceal cchar=X 482 syn match test45 "45" conceal 483 484 set conceallevel=0 485 call assert_equal('123456 ', ScreenLines(2, 7)[0]) 486 call assert_equal([[0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)')) 487 488 set conceallevel=1 489 call assert_equal('1X 6 ', ScreenLines(2, 7)[0]) 490 call assert_equal([[0, '', 0], [1, 'X', 1], [1, 'X', 1], [1, ' ', 2], [1, ' ', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)')) 491 492 set conceallevel=1 493 set listchars=conceal:Y 494 call assert_equal([[0, '', 0], [1, 'X', 1], [1, 'X', 1], [1, 'Y', 2], [1, 'Y', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)')) 495 call assert_equal('1XY6 ', ScreenLines(2, 7)[0]) 496 497 set conceallevel=2 498 call assert_match('1X6 ', ScreenLines(2, 7)[0]) 499 call assert_equal([[0, '', 0], [1, 'X', 1], [1, 'X', 1], [1, '', 2], [1, '', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)')) 500 501 set conceallevel=3 502 call assert_match('16 ', ScreenLines(2, 7)[0]) 503 call assert_equal([[0, '', 0], [1, '', 1], [1, '', 1], [1, '', 2], [1, '', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)')) 504 505 syn clear 506 set conceallevel& 507 bw! 508endfunc 509 510func Test_synstack_synIDtrans() 511 new 512 setfiletype c 513 syntax on 514 call setline(1, ' /* A comment with a TODO */') 515 516 call assert_equal([], synstack(1, 1)) 517 518 norm f/ 519 eval synstack(line("."), col("."))->map('synIDattr(v:val, "name")')->assert_equal(['cComment', 'cCommentStart']) 520 eval synstack(line("."), col("."))->map('synIDattr(synIDtrans(v:val), "name")')->assert_equal(['Comment', 'Comment']) 521 522 norm fA 523 call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")')) 524 call assert_equal(['Comment'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")')) 525 526 norm fT 527 call assert_equal(['cComment', 'cTodo'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")')) 528 call assert_equal(['Comment', 'Todo'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")')) 529 530 syn clear 531 bw! 532endfunc 533 534" Check highlighting for a small piece of C code with a screen dump. 535func Test_syntax_c() 536 if !CanRunVimInTerminal() 537 throw 'Skipped: cannot make screendumps' 538 endif 539 call writefile([ 540 \ '/* comment line at the top */', 541 \ ' int', 542 \ 'main(int argc, char **argv)// another comment', 543 \ '{', 544 \ '#if 0', 545 \ ' int not_used;', 546 \ '#else', 547 \ ' int used;', 548 \ '#endif', 549 \ ' printf("Just an example piece of C code\n");', 550 \ ' return 0x0ff;', 551 \ '}', 552 \ ' static void', 553 \ 'myFunction(const double count, struct nothing, long there) {', 554 \ "\t// 123: nothing to read here", 555 \ "\tfor (int i = 0; i < count; ++i) {", 556 \ "\t break;", 557 \ "\t}", 558 \ '}', 559 \ ], 'Xtest.c') 560 561 " This makes the default for 'background' use "dark", check that the 562 " response to t_RB corrects it to "light". 563 let $COLORFGBG = '15;0' 564 565 let buf = RunVimInTerminal('Xtest.c', {}) 566 call VerifyScreenDump(buf, 'Test_syntax_c_01', {}) 567 call StopVimInTerminal(buf) 568 569 let $COLORFGBG = '' 570 call delete('Xtest.c') 571endfun 572 573" Using \z() in a region with NFA failing should not crash. 574func Test_syn_wrong_z_one() 575 new 576 call setline(1, ['just some text', 'with foo and bar to match with']) 577 syn region FooBar start="foo\z(.*\)bar" end="\z1" 578 call test_override("nfa_fail", 1) 579 redraw! 580 redraw! 581 call test_override("ALL", 0) 582 bwipe! 583endfunc 584 585func Test_syntax_after_bufdo() 586 call writefile(['/* aaa comment */'], 'Xaaa.c') 587 call writefile(['/* bbb comment */'], 'Xbbb.c') 588 call writefile(['/* ccc comment */'], 'Xccc.c') 589 call writefile(['/* ddd comment */'], 'Xddd.c') 590 591 let bnr = bufnr('%') 592 new Xaaa.c 593 badd Xbbb.c 594 badd Xccc.c 595 badd Xddd.c 596 exe "bwipe " . bnr 597 let l = [] 598 bufdo call add(l, bufnr('%')) 599 call assert_equal(4, len(l)) 600 601 syntax on 602 603 " This used to only enable syntax HL in the last buffer. 604 bufdo tab split 605 tabrewind 606 for tab in range(1, 4) 607 norm fm 608 call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")')) 609 tabnext 610 endfor 611 612 bwipe! Xaaa.c 613 bwipe! Xbbb.c 614 bwipe! Xccc.c 615 bwipe! Xddd.c 616 syntax off 617 call delete('Xaaa.c') 618 call delete('Xbbb.c') 619 call delete('Xccc.c') 620 call delete('Xddd.c') 621endfunc 622