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', @:) 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 if has('gui_running') 417 return 418 endif 419 " auto-detection of &bg, make sure sure it isn't set anywhere before 420 " this test 421 hi Normal ctermbg=0 422 call assert_equal('dark', &bg) 423 hi Normal ctermbg=4 424 call assert_equal('dark', &bg) 425 hi Normal ctermbg=12 426 call assert_equal('light', &bg) 427 hi Normal ctermbg=15 428 call assert_equal('light', &bg) 429 430 " manually-set &bg takes precedence over auto-detection 431 set bg=light 432 hi Normal ctermbg=4 433 call assert_equal('light', &bg) 434 set bg=dark 435 hi Normal ctermbg=12 436 call assert_equal('dark', &bg) 437 438 hi Normal ctermbg=NONE 439endfunc 440 441func Test_syntax_hangs() 442 if !has('reltime') || !has('float') || !has('syntax') 443 return 444 endif 445 446 " This pattern takes a long time to match, it should timeout. 447 new 448 call setline(1, ['aaa', repeat('abc ', 1000), 'ccc']) 449 let start = reltime() 450 set nolazyredraw redrawtime=101 451 syn match Error /\%#=1a*.*X\@<=b*/ 452 redraw 453 let elapsed = reltimefloat(reltime(start)) 454 call assert_true(elapsed > 0.1) 455 call assert_true(elapsed < 1.0) 456 457 " second time syntax HL is disabled 458 let start = reltime() 459 redraw 460 let elapsed = reltimefloat(reltime(start)) 461 call assert_true(elapsed < 0.1) 462 463 " after CTRL-L the timeout flag is reset 464 let start = reltime() 465 exe "normal \<C-L>" 466 redraw 467 let elapsed = reltimefloat(reltime(start)) 468 call assert_true(elapsed > 0.1) 469 call assert_true(elapsed < 1.0) 470 471 set redrawtime& 472 bwipe! 473endfunc 474 475func Test_conceal() 476 if !has('conceal') 477 return 478 endif 479 480 new 481 call setline(1, ['', '123456']) 482 syn match test23 "23" conceal cchar=X 483 syn match test45 "45" conceal 484 485 set conceallevel=0 486 call assert_equal('123456 ', ScreenLines(2, 7)[0]) 487 call assert_equal([[0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)')) 488 489 set conceallevel=1 490 call assert_equal('1X 6 ', ScreenLines(2, 7)[0]) 491 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)')) 492 493 set conceallevel=1 494 set listchars=conceal:Y 495 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)')) 496 call assert_equal('1XY6 ', ScreenLines(2, 7)[0]) 497 498 set conceallevel=2 499 call assert_match('1X6 ', ScreenLines(2, 7)[0]) 500 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)')) 501 502 set conceallevel=3 503 call assert_match('16 ', ScreenLines(2, 7)[0]) 504 call assert_equal([[0, '', 0], [1, '', 1], [1, '', 1], [1, '', 2], [1, '', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)')) 505 506 syn clear 507 set conceallevel& 508 bw! 509endfunc 510 511func Test_synstack_synIDtrans() 512 new 513 setfiletype c 514 syntax on 515 call setline(1, ' /* A comment with a TODO */') 516 517 call assert_equal([], synstack(1, 1)) 518 519 norm f/ 520 eval synstack(line("."), col("."))->map('synIDattr(v:val, "name")')->assert_equal(['cComment', 'cCommentStart']) 521 eval synstack(line("."), col("."))->map('synIDattr(synIDtrans(v:val), "name")')->assert_equal(['Comment', 'Comment']) 522 523 norm fA 524 call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")')) 525 call assert_equal(['Comment'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")')) 526 527 norm fT 528 call assert_equal(['cComment', 'cTodo'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")')) 529 call assert_equal(['Comment', 'Todo'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")')) 530 531 syn clear 532 bw! 533endfunc 534 535" Check highlighting for a small piece of C code with a screen dump. 536func Test_syntax_c() 537 if !CanRunVimInTerminal() 538 throw 'Skipped: cannot make screendumps' 539 endif 540 call writefile([ 541 \ '/* comment line at the top */', 542 \ ' int', 543 \ 'main(int argc, char **argv)// another comment', 544 \ '{', 545 \ '#if 0', 546 \ ' int not_used;', 547 \ '#else', 548 \ ' int used;', 549 \ '#endif', 550 \ ' printf("Just an example piece of C code\n");', 551 \ ' return 0x0ff;', 552 \ '}', 553 \ ' static void', 554 \ 'myFunction(const double count, struct nothing, long there) {', 555 \ ' // 123: nothing to read here', 556 \ ' for (int i = 0; i < count; ++i) {', 557 \ ' break;', 558 \ ' }', 559 \ '}', 560 \ ], 'Xtest.c') 561 562 " This makes the default for 'background' use "dark", check that the 563 " response to t_RB corrects it to "light". 564 let $COLORFGBG = '15;0' 565 566 let buf = RunVimInTerminal('Xtest.c', {}) 567 call VerifyScreenDump(buf, 'Test_syntax_c_01', {}) 568 call StopVimInTerminal(buf) 569 570 let $COLORFGBG = '' 571 call delete('Xtest.c') 572endfun 573 574" Using \z() in a region with NFA failing should not crash. 575func Test_syn_wrong_z_one() 576 new 577 call setline(1, ['just some text', 'with foo and bar to match with']) 578 syn region FooBar start="foo\z(.*\)bar" end="\z1" 579 call test_override("nfa_fail", 1) 580 redraw! 581 redraw! 582 call test_override("ALL", 0) 583 bwipe! 584endfunc 585 586func Test_syntax_after_bufdo() 587 call writefile(['/* aaa comment */'], 'Xaaa.c') 588 call writefile(['/* bbb comment */'], 'Xbbb.c') 589 call writefile(['/* ccc comment */'], 'Xccc.c') 590 call writefile(['/* ddd comment */'], 'Xddd.c') 591 592 let bnr = bufnr('%') 593 new Xaaa.c 594 badd Xbbb.c 595 badd Xccc.c 596 badd Xddd.c 597 exe "bwipe " . bnr 598 let l = [] 599 bufdo call add(l, bufnr('%')) 600 call assert_equal(4, len(l)) 601 602 syntax on 603 604 " This used to only enable syntax HL in the last buffer. 605 bufdo tab split 606 tabrewind 607 for tab in range(1, 4) 608 norm fm 609 call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")')) 610 tabnext 611 endfor 612 613 bwipe! Xaaa.c 614 bwipe! Xbbb.c 615 bwipe! Xccc.c 616 bwipe! Xddd.c 617 syntax off 618 call delete('Xaaa.c') 619 call delete('Xbbb.c') 620 call delete('Xccc.c') 621 call delete('Xddd.c') 622endfunc 623