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 AssertHighlightGroups(lnum, startcol, expected, trans = 1, msg = "") 31 " Assert that the characters starting at a given (line, col) 32 " sequentially match the expected highlight groups. 33 " If groups are provided as a string, each character is assumed to be a 34 " group and spaces represent no group, useful for visually describing tests. 35 let l:expectedGroups = type(a:expected) == v:t_string 36 \ ? a:expected->split('\zs')->map({_, v -> trim(v)}) 37 \ : a:expected 38 let l:errors = 0 39 let l:msg = (a:msg->empty() ? "" : a:msg .. ": ") 40 \ .. "Wrong highlight group at " .. a:lnum .. "," 41 42 for l:i in range(a:startcol, a:startcol + l:expectedGroups->len() - 1) 43 let l:errors += synID(a:lnum, l:i, a:trans) 44 \ ->synIDattr("name") 45 \ ->assert_equal(l:expectedGroups[l:i - 1], 46 \ l:msg .. l:i) 47 endfor 48endfunc 49 50func Test_syn_iskeyword() 51 new 52 call setline(1, [ 53 \ 'CREATE TABLE FOOBAR(', 54 \ ' DLTD_BY VARCHAR2(100)', 55 \ ');', 56 \ '']) 57 58 syntax on 59 set ft=sql 60 syn match SYN /C\k\+\>/ 61 hi link SYN ErrorMsg 62 call assert_equal('DLTD_BY', GetSyntaxItem('DLTD')) 63 /\<D\k\+\>/:norm! ygn 64 call assert_equal('DLTD_BY', @0) 65 redir @c 66 syn iskeyword 67 redir END 68 call assert_equal("\nsyntax iskeyword not set", @c) 69 70 syn iskeyword @,48-57,_,192-255 71 redir @c 72 syn iskeyword 73 redir END 74 call assert_equal("\nsyntax iskeyword @,48-57,_,192-255", @c) 75 76 setlocal isk-=_ 77 call assert_equal('DLTD_BY', GetSyntaxItem('DLTD')) 78 /\<D\k\+\>/:norm! ygn 79 let b2 = @0 80 call assert_equal('DLTD', @0) 81 82 syn iskeyword clear 83 redir @c 84 syn iskeyword 85 redir END 86 call assert_equal("\nsyntax iskeyword not set", @c) 87 88 quit! 89endfunc 90 91func Test_syntax_after_reload() 92 split Xsomefile 93 call setline(1, ['hello', 'there']) 94 w! 95 only! 96 setl filetype=hello 97 au FileType hello let g:gotit = 1 98 call assert_false(exists('g:gotit')) 99 edit other 100 buf Xsomefile 101 call assert_equal('hello', &filetype) 102 call assert_true(exists('g:gotit')) 103 call delete('Xsomefile') 104endfunc 105 106func Test_syntime() 107 CheckFeature profile 108 109 syntax on 110 syntime on 111 let a = execute('syntime report') 112 call assert_equal("\nNo Syntax items defined for this buffer", a) 113 114 view ../memfile_test.c 115 setfiletype cpp 116 redraw 117 let a = execute('syntime report') 118 call assert_match('^ TOTAL *COUNT *MATCH *SLOWEST *AVERAGE *NAME *PATTERN', a) 119 call assert_match(' \d*\.\d* \+[^0]\d* .* cppRawString ', a) 120 call assert_match(' \d*\.\d* \+[^0]\d* .* cppNumber ', a) 121 122 syntime off 123 syntime clear 124 let a = execute('syntime report') 125 call assert_match('^ TOTAL *COUNT *MATCH *SLOWEST *AVERAGE *NAME *PATTERN', a) 126 call assert_notmatch('.* cppRawString *', a) 127 call assert_notmatch('.* cppNumber*', a) 128 call assert_notmatch('[1-9]', a) 129 130 call assert_fails('syntime abc', 'E475:') 131 132 syntax clear 133 let a = execute('syntime report') 134 call assert_equal("\nNo Syntax items defined for this buffer", a) 135 136 bd 137endfunc 138 139func Test_syntime_completion() 140 CheckFeature profile 141 142 call feedkeys(":syntime \<C-A>\<C-B>\"\<CR>", 'tx') 143 call assert_equal('"syntime clear off on report', @:) 144endfunc 145 146func Test_syntax_list() 147 syntax on 148 let a = execute('syntax list') 149 call assert_equal("\nNo Syntax items defined for this buffer", a) 150 151 view ../memfile_test.c 152 setfiletype c 153 154 let a = execute('syntax list') 155 call assert_match('cInclude*', a) 156 call assert_match('cDefine', a) 157 158 let a = execute('syntax list cDefine') 159 call assert_notmatch('cInclude*', a) 160 call assert_match('cDefine', a) 161 call assert_match(' links to Macro$', a) 162 163 call assert_fails('syntax list ABCD', 'E28:') 164 call assert_fails('syntax list @ABCD', 'E392:') 165 166 syntax clear 167 let a = execute('syntax list') 168 call assert_equal("\nNo Syntax items defined for this buffer", a) 169 170 syntax keyword Type int containedin=g1 skipwhite skipempty skipnl nextgroup=Abc 171 let exp = "Type xxx containedin=g1 nextgroup=Abc skipnl skipwhite skipempty int" 172 call assert_equal(exp, split(execute("syntax list"), "\n")[1]) 173 174 bd 175endfunc 176 177func Test_syntax_completion() 178 call feedkeys(":syn \<C-A>\<C-B>\"\<CR>", 'tx') 179 call assert_equal('"syn case clear cluster conceal enable foldlevel include iskeyword keyword list manual match off on region reset spell sync', @:) 180 181 call feedkeys(":syn case \<C-A>\<C-B>\"\<CR>", 'tx') 182 call assert_equal('"syn case ignore match', @:) 183 184 call feedkeys(":syn spell \<C-A>\<C-B>\"\<CR>", 'tx') 185 call assert_equal('"syn spell default notoplevel toplevel', @:) 186 187 call feedkeys(":syn sync \<C-A>\<C-B>\"\<CR>", 'tx') 188 call assert_equal('"syn sync ccomment clear fromstart linebreaks= linecont lines= match maxlines= minlines= region', @:) 189 190 " Check that clearing "Aap" avoids it showing up before Boolean. 191 hi Aap ctermfg=blue 192 call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx') 193 call assert_match('^"syn list Aap Boolean Character ', @:) 194 hi clear Aap 195 196 call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx') 197 call assert_match('^"syn list Boolean Character ', @:) 198 199 call feedkeys(":syn match \<C-A>\<C-B>\"\<CR>", 'tx') 200 call assert_match('^"syn match Boolean Character ', @:) 201endfunc 202 203func Test_echohl_completion() 204 call feedkeys(":echohl no\<C-A>\<C-B>\"\<CR>", 'tx') 205 call assert_equal('"echohl NonText Normal none', @:) 206endfunc 207 208func Test_syntax_arg_skipped() 209 syn clear 210 syntax case ignore 211 if 0 212 syntax case match 213 endif 214 call assert_match('case ignore', execute('syntax case')) 215 216 syn keyword Foo foo 217 call assert_match('Foo', execute('syntax')) 218 syn clear 219 call assert_match('case match', execute('syntax case')) 220 call assert_notmatch('Foo', execute('syntax')) 221 222 if has('conceal') 223 syn clear 224 syntax conceal on 225 if 0 226 syntax conceal off 227 endif 228 call assert_match('conceal on', execute('syntax conceal')) 229 syn clear 230 call assert_match('conceal off', execute('syntax conceal')) 231 232 syntax conceal on 233 syntax conceal off 234 call assert_match('conceal off', execute('syntax conceal')) 235 endif 236 237 syntax region Bar start=/</ end=/>/ 238 if 0 239 syntax region NotTest start=/</ end=/>/ contains=@Spell 240 endif 241 call assert_match('Bar', execute('syntax')) 242 call assert_notmatch('NotTest', execute('syntax')) 243 call assert_notmatch('Spell', execute('syntax')) 244 245 hi Foo ctermfg=blue 246 let a = execute('hi Foo') 247 if 0 248 syntax rest 249 endif 250 call assert_equal(a, execute('hi Foo')) 251 hi clear Bar 252 hi clear Foo 253 254 set ft=tags 255 syn off 256 if 0 257 syntax enable 258 endif 259 call assert_match('No Syntax items defined', execute('syntax')) 260 syntax enable 261 call assert_match('tagComment', execute('syntax')) 262 set ft= 263 264 syn clear 265 if 0 266 syntax include @Spell nothing 267 endif 268 call assert_notmatch('Spell', execute('syntax')) 269 270 syn clear 271 syn iskeyword 48-57,$,_ 272 call assert_match('48-57,$,_', execute('syntax iskeyword')) 273 if 0 274 syn clear 275 syn iskeyword clear 276 endif 277 call assert_match('48-57,$,_', execute('syntax iskeyword')) 278 syn iskeyword clear 279 call assert_match('not set', execute('syntax iskeyword')) 280 syn iskeyword 48-57,$,_ 281 syn clear 282 call assert_match('not set', execute('syntax iskeyword')) 283 284 syn clear 285 syn keyword Foo foo 286 if 0 287 syn keyword NotAdded bar 288 endif 289 call assert_match('Foo', execute('syntax')) 290 call assert_notmatch('NotAdded', execute('highlight')) 291 292 syn clear 293 syn keyword Foo foo 294 call assert_match('Foo', execute('syntax')) 295 call assert_match('Foo', execute('syntax list')) 296 call assert_notmatch('Foo', execute('if 0 | syntax | endif')) 297 call assert_notmatch('Foo', execute('if 0 | syntax list | endif')) 298 299 syn clear 300 syn match Fopi /asdf/ 301 if 0 302 syn match Fopx /asdf/ 303 endif 304 call assert_match('Fopi', execute('syntax')) 305 call assert_notmatch('Fopx', execute('syntax')) 306 307 syn clear 308 syn spell toplevel 309 call assert_match('spell toplevel', execute('syntax spell')) 310 if 0 311 syn spell notoplevel 312 endif 313 call assert_match('spell toplevel', execute('syntax spell')) 314 syn spell notoplevel 315 call assert_match('spell notoplevel', execute('syntax spell')) 316 syn spell default 317 call assert_match('spell default', execute('syntax spell')) 318 319 syn clear 320 if 0 321 syntax cluster Spell 322 endif 323 call assert_notmatch('Spell', execute('syntax')) 324 325 syn clear 326 syn keyword Foo foo 327 syn sync ccomment 328 syn sync maxlines=5 329 if 0 330 syn sync maxlines=11 331 endif 332 call assert_match('on C-style comments', execute('syntax sync')) 333 call assert_match('maximal 5 lines', execute('syntax sync')) 334 syn sync clear 335 if 0 336 syn sync ccomment 337 endif 338 call assert_notmatch('on C-style comments', execute('syntax sync')) 339 syn sync fromstart 340 call assert_match('syncing starts at the first line', execute('syntax sync')) 341 342 syn clear 343endfunc 344 345" Check for an error. Used when multiple errors are thrown and we are checking 346" for an earliest error. 347func AssertFails(cmd, errcode) 348 let save_exception = '' 349 try 350 exe a:cmd 351 catch 352 let save_exception = v:exception 353 endtry 354 call assert_match(a:errcode, save_exception) 355endfunc 356 357func Test_syntax_invalid_arg() 358 call assert_fails('syntax case asdf', 'E390:') 359 if has('conceal') 360 call assert_fails('syntax conceal asdf', 'E390:') 361 endif 362 call assert_fails('syntax spell asdf', 'E390:') 363 call assert_fails('syntax clear @ABCD', 'E391:') 364 call assert_fails('syntax include random_file', 'E484:') 365 call assert_fails('syntax include <afile>', 'E495:') 366 call assert_fails('syntax sync x', 'E404:') 367 call assert_fails('syntax keyword Abc a[', 'E789:') 368 call assert_fails('syntax keyword Abc a[bc]d', 'E890:') 369 call assert_fails('syntax cluster Abc add=A add=', 'E406:') 370 371 " Test for too many \z\( and unmatched \z\( 372 " Not able to use assert_fails() here because both E50:/E879: and E475: 373 " messages are emitted. 374 set regexpengine=1 375 call AssertFails("syntax region MyRegion start='\\z\\(' end='\\*/'", 'E52:') 376 377 let cmd = "syntax region MyRegion start='" 378 let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'" 379 call AssertFails(cmd, 'E50:') 380 381 set regexpengine=2 382 call AssertFails("syntax region MyRegion start='\\z\\(' end='\\*/'", 'E54:') 383 384 let cmd = "syntax region MyRegion start='" 385 let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'" 386 call AssertFails(cmd, 'E879:') 387 set regexpengine& 388 389 call AssertFails('syntax keyword cMyItem grouphere G1', 'E393:') 390 call AssertFails('syntax sync match Abc grouphere MyItem "abc"', 'E394:') 391 call AssertFails('syn keyword Type contains int', 'E395:') 392 call assert_fails('syntax include @Xxx', 'E397:') 393 call AssertFails('syntax region X start', 'E398:') 394 call assert_fails('syntax region X start="{"', 'E399:') 395 call AssertFails('syntax cluster contains=Abc', 'E400:') 396 call AssertFails("syntax match Character /'.'", 'E401:') 397 call AssertFails("syntax match Character /'.'/a", 'E402:') 398 call assert_fails('syntax sync linecont /\%(/', 'E53:') 399 call assert_fails('syntax sync linecont /pat', 'E404:') 400 call assert_fails('syntax sync linecont', 'E404:') 401 call assert_fails('syntax sync linecont /pat1/ linecont /pat2/', 'E403:') 402 call assert_fails('syntax sync minlines=a', 'E404:') 403 call AssertFails('syntax match ABC /x/ contains=', 'E406:') 404 call AssertFails("syntax match Character contains /'.'/", 'E405:') 405 call AssertFails('syntax match ccFoo "Foo" nextgroup=ALLBUT,F', 'E407:') 406 call AssertFails('syntax region Block start="{" contains=F,ALLBUT', 'E408:') 407 call AssertFails("syntax match Characters contains=a.*x /'.'/", 'E409:') 408 call assert_fails('syntax match Search /abc/ contains=ALLBUT,/\%(/', 'E53:') 409endfunc 410 411func Test_syn_sync() 412 syntax region HereGroup start=/this/ end=/that/ 413 syntax sync match SyncHere grouphere HereGroup "pattern" 414 call assert_match('SyncHere', execute('syntax sync')) 415 syn sync clear 416 call assert_notmatch('SyncHere', execute('syntax sync')) 417 syn clear 418endfunc 419 420func Test_syn_clear() 421 syntax keyword Foo foo 422 syntax keyword Bar tar 423 call assert_match('Foo', execute('syntax')) 424 call assert_match('Bar', execute('syntax')) 425 call assert_equal('Foo', synIDattr(hlID("Foo"), "name")) 426 syn clear Foo 427 call assert_notmatch('Foo', execute('syntax')) 428 call assert_match('Bar', execute('syntax')) 429 call assert_equal('Foo', synIDattr(hlID("Foo"), "name")) 430 syn clear Foo Bar 431 call assert_notmatch('Foo', execute('syntax')) 432 call assert_notmatch('Bar', execute('syntax')) 433 hi clear Foo 434 call assert_equal('Foo', synIDattr(hlID("Foo"), "name")) 435 hi clear Bar 436 call assert_fails('syntax clear invalid_syngroup', 'E28:') 437endfunc 438 439func Test_invalid_name() 440 syn clear 441 syn keyword Nop yes 442 call assert_fails("syntax keyword Wr\x17ong bar", 'E669:') 443 syntax keyword @Wrong bar 444 call assert_match('W18:', execute('1messages')) 445 syn clear 446 hi clear Nop 447 hi clear @Wrong 448endfunc 449 450func Test_ownsyntax() 451 new Xfoo 452 call setline(1, '#define FOO') 453 syntax on 454 set filetype=c 455 456 ownsyntax perl 457 " this should not crash 458 set 459 460 call assert_equal('perlComment', synIDattr(synID(line('.'), col('.'), 1), 'name')) 461 call assert_equal('c', b:current_syntax) 462 call assert_equal('perl', w:current_syntax) 463 464 " A new split window should have the original syntax. 465 split 466 call assert_equal('cDefine', synIDattr(synID(line('.'), col('.'), 1), 'name')) 467 call assert_equal('c', b:current_syntax) 468 call assert_equal(0, exists('w:current_syntax')) 469 470 wincmd x 471 call assert_equal('perlComment', synIDattr(synID(line("."), col("."), 1), "name")) 472 473 syntax off 474 set filetype& 475 %bw! 476endfunc 477 478func Test_ownsyntax_completion() 479 call feedkeys(":ownsyntax java\<C-A>\<C-B>\"\<CR>", 'tx') 480 call assert_equal('"ownsyntax java javacc javascript javascriptreact', @:) 481endfunc 482 483func Test_highlight_invalid_arg() 484 if has('gui_running') 485 call assert_fails('hi XXX guifg=xxx', 'E254:') 486 endif 487 call assert_fails('hi DoesNotExist', 'E411:') 488 call assert_fails('hi link', 'E412:') 489 call assert_fails('hi link a', 'E412:') 490 call assert_fails('hi link a b c', 'E413:') 491 call assert_fails('hi XXX =', 'E415:') 492 call assert_fails('hi XXX cterm', 'E416:') 493 call assert_fails('hi XXX cterm=', 'E417:') 494 call assert_fails('hi XXX cterm=DoesNotExist', 'E418:') 495 call assert_fails('hi XXX ctermfg=DoesNotExist', 'E421:') 496 call assert_fails('hi XXX xxx=White', 'E423:') 497endfunc 498 499func Test_bg_detection() 500 CheckNotGui 501 502 " auto-detection of &bg, make sure sure it isn't set anywhere before 503 " this test 504 hi Normal ctermbg=0 505 call assert_equal('dark', &bg) 506 hi Normal ctermbg=4 507 call assert_equal('dark', &bg) 508 hi Normal ctermbg=12 509 call assert_equal('light', &bg) 510 hi Normal ctermbg=15 511 call assert_equal('light', &bg) 512 513 " manually-set &bg takes precedence over auto-detection 514 set bg=light 515 hi Normal ctermbg=4 516 call assert_equal('light', &bg) 517 set bg=dark 518 hi Normal ctermbg=12 519 call assert_equal('dark', &bg) 520 521 hi Normal ctermbg=NONE 522endfunc 523 524func Test_syntax_hangs() 525 CheckFunction reltimefloat 526 CheckFeature syntax 527 528 " This pattern takes a long time to match, it should timeout. 529 new 530 call setline(1, ['aaa', repeat('abc ', 1000), 'ccc']) 531 let start = reltime() 532 set nolazyredraw redrawtime=101 533 syn match Error /\%#=1a*.*X\@<=b*/ 534 redraw 535 let elapsed = reltimefloat(reltime(start)) 536 call assert_true(elapsed > 0.1) 537 call assert_true(elapsed < 1.0) 538 539 " second time syntax HL is disabled 540 let start = reltime() 541 redraw 542 let elapsed = reltimefloat(reltime(start)) 543 call assert_true(elapsed < 0.1) 544 545 " after CTRL-L the timeout flag is reset 546 let start = reltime() 547 exe "normal \<C-L>" 548 redraw 549 let elapsed = reltimefloat(reltime(start)) 550 call assert_true(elapsed > 0.1) 551 call assert_true(elapsed < 1.0) 552 553 set redrawtime& 554 bwipe! 555endfunc 556 557func Test_conceal() 558 CheckFeature conceal 559 560 new 561 call setline(1, ['', '123456']) 562 syn match test23 "23" conceal cchar=X 563 syn match test45 "45" conceal 564 565 set conceallevel=0 566 call assert_equal('123456 ', ScreenLines(2, 7)[0]) 567 call assert_equal([[0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)')) 568 569 set conceallevel=1 570 call assert_equal('1X 6 ', ScreenLines(2, 7)[0]) 571 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)')) 572 573 set conceallevel=1 574 set listchars=conceal:Y 575 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)')) 576 call assert_equal('1XY6 ', ScreenLines(2, 7)[0]) 577 578 set conceallevel=2 579 call assert_match('1X6 ', ScreenLines(2, 7)[0]) 580 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)')) 581 582 set conceallevel=3 583 call assert_match('16 ', ScreenLines(2, 7)[0]) 584 call assert_equal([[0, '', 0], [1, '', 1], [1, '', 1], [1, '', 2], [1, '', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)')) 585 586 call AssertFails("syntax match Entity '&' conceal cchar=\<Tab>", 'E844:') 587 588 syn clear 589 set conceallevel& 590 bw! 591endfunc 592 593func Test_synstack_synIDtrans() 594 new 595 setfiletype c 596 syntax on 597 call setline(1, ' /* A comment with a TODO */') 598 599 call assert_equal([], synstack(1, 1)) 600 601 norm f/ 602 eval synstack(line("."), col("."))->map('synIDattr(v:val, "name")')->assert_equal(['cComment', 'cCommentStart']) 603 eval synstack(line("."), col("."))->map('synIDattr(synIDtrans(v:val), "name")')->assert_equal(['Comment', 'Comment']) 604 605 norm fA 606 call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")')) 607 call assert_equal(['Comment'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")')) 608 609 norm fT 610 call assert_equal(['cComment', 'cTodo'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")')) 611 call assert_equal(['Comment', 'Todo'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")')) 612 613 call assert_fails("let n=synIDtrans([])", 'E745:') 614 615 syn clear 616 bw! 617endfunc 618 619" Check highlighting for a small piece of C code with a screen dump. 620func Test_syntax_c() 621 CheckRunVimInTerminal 622 call writefile([ 623 \ '/* comment line at the top */', 624 \ 'int main(int argc, char **argv) { // another comment', 625 \ '#if 0', 626 \ ' int not_used;', 627 \ '#else', 628 \ ' int used;', 629 \ '#endif', 630 \ ' printf("Just an example piece of C code\n");', 631 \ ' return 0x0ff;', 632 \ '}', 633 \ "\t\t ", 634 \ ' static void', 635 \ 'myFunction(const double count, struct nothing, long there) {', 636 \ "\t// 123: nothing to endif here", 637 \ "\tfor (int i = 0; i < count; ++i) {", 638 \ "\t break;", 639 \ "\t}", 640 \ "\tNote: asdf", 641 \ '}', 642 \ ], 'Xtest.c') 643 644 " This makes the default for 'background' use "dark", check that the 645 " response to t_RB corrects it to "light". 646 let $COLORFGBG = '15;0' 647 648 let buf = RunVimInTerminal('Xtest.c', {}) 649 call term_sendkeys(buf, ":syn keyword Search Note\r") 650 call term_sendkeys(buf, ":syn match Error /^\\s\\+$/\r") 651 call term_sendkeys(buf, ":set hlsearch\r") 652 call term_sendkeys(buf, "/endif\r") 653 call term_sendkeys(buf, "vjfC") 654 call VerifyScreenDump(buf, 'Test_syntax_c_01', {}) 655 656 call term_sendkeys(buf, "\<Esc>") 657 call StopVimInTerminal(buf) 658 659 let $COLORFGBG = '' 660 call delete('Xtest.c') 661endfun 662 663" Using \z() in a region with NFA failing should not crash. 664func Test_syn_wrong_z_one() 665 new 666 call setline(1, ['just some text', 'with foo and bar to match with']) 667 syn region FooBar start="foo\z(.*\)bar" end="\z1" 668 call test_override("nfa_fail", 1) 669 redraw! 670 redraw! 671 call test_override("ALL", 0) 672 bwipe! 673endfunc 674 675func Test_syntax_after_bufdo() 676 call writefile(['/* aaa comment */'], 'Xaaa.c') 677 call writefile(['/* bbb comment */'], 'Xbbb.c') 678 call writefile(['/* ccc comment */'], 'Xccc.c') 679 call writefile(['/* ddd comment */'], 'Xddd.c') 680 681 let bnr = bufnr('%') 682 new Xaaa.c 683 badd Xbbb.c 684 badd Xccc.c 685 badd Xddd.c 686 exe "bwipe " . bnr 687 let l = [] 688 bufdo call add(l, bufnr('%')) 689 call assert_equal(4, len(l)) 690 691 syntax on 692 693 " This used to only enable syntax HL in the last buffer. 694 bufdo tab split 695 tabrewind 696 for tab in range(1, 4) 697 norm fm 698 call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")')) 699 tabnext 700 endfor 701 702 bwipe! Xaaa.c 703 bwipe! Xbbb.c 704 bwipe! Xccc.c 705 bwipe! Xddd.c 706 syntax off 707 call delete('Xaaa.c') 708 call delete('Xbbb.c') 709 call delete('Xccc.c') 710 call delete('Xddd.c') 711endfunc 712 713func Test_syntax_foldlevel() 714 new 715 call setline(1, [ 716 \ 'void f(int a)', 717 \ '{', 718 \ ' if (a == 1) {', 719 \ ' a = 0;', 720 \ ' } else if (a == 2) {', 721 \ ' a = 1;', 722 \ ' } else {', 723 \ ' a = 2;', 724 \ ' }', 725 \ ' if (a > 0) {', 726 \ ' if (a == 1) {', 727 \ ' a = 0;', 728 \ ' } /* missing newline */ } /* end of outer if */ else {', 729 \ ' a = 1;', 730 \ ' }', 731 \ ' if (a == 1)', 732 \ ' {', 733 \ ' a = 0;', 734 \ ' }', 735 \ ' else if (a == 2)', 736 \ ' {', 737 \ ' a = 1;', 738 \ ' }', 739 \ ' else', 740 \ ' {', 741 \ ' a = 2;', 742 \ ' }', 743 \ '}', 744 \ ]) 745 setfiletype c 746 syntax on 747 set foldmethod=syntax 748 749 call assert_fails('syn foldlevel start start', 'E390:') 750 call assert_fails('syn foldlevel not_an_option', 'E390:') 751 752 set foldlevel=1 753 754 syn foldlevel start 755 redir @c 756 syn foldlevel 757 redir END 758 call assert_equal("\nsyntax foldlevel start", @c) 759 syn sync fromstart 760 call assert_match('from the first line$', execute('syn sync')) 761 let a = map(range(3,9), 'foldclosed(v:val)') 762 call assert_equal([3,3,3,3,3,3,3], a) " attached cascade folds together 763 let a = map(range(10,15), 'foldclosed(v:val)') 764 call assert_equal([10,10,10,10,10,10], a) " over-attached 'else' hidden 765 let a = map(range(16,27), 'foldclosed(v:val)') 766 let unattached_results = [-1,17,17,17,-1,21,21,21,-1,25,25,25] 767 call assert_equal(unattached_results, a) " unattached cascade folds separately 768 769 syn foldlevel minimum 770 redir @c 771 syn foldlevel 772 redir END 773 call assert_equal("\nsyntax foldlevel minimum", @c) 774 syn sync fromstart 775 let a = map(range(3,9), 'foldclosed(v:val)') 776 call assert_equal([3,3,5,5,7,7,7], a) " attached cascade folds separately 777 let a = map(range(10,15), 'foldclosed(v:val)') 778 call assert_equal([10,10,10,13,13,13], a) " over-attached 'else' visible 779 let a = map(range(16,27), 'foldclosed(v:val)') 780 call assert_equal(unattached_results, a) " unattached cascade folds separately 781 782 set foldlevel=2 783 784 syn foldlevel start 785 syn sync fromstart 786 let a = map(range(11,14), 'foldclosed(v:val)') 787 call assert_equal([11,11,11,-1], a) " over-attached 'else' hidden 788 789 syn foldlevel minimum 790 syn sync fromstart 791 let a = map(range(11,14), 'foldclosed(v:val)') 792 call assert_equal([11,11,-1,-1], a) " over-attached 'else' visible 793 794 quit! 795endfunc 796 797func Test_search_syntax_skip() 798 new 799 let lines =<< trim END 800 801 /* This is VIM */ 802 Another Text for VIM 803 let a = "VIM" 804 END 805 call setline(1, lines) 806 syntax on 807 syntax match Comment "^/\*.*\*/" 808 syntax match String '".*"' 809 810 " Skip argument using string evaluation. 811 1 812 call search('VIM', 'w', '', 0, 'synIDattr(synID(line("."), col("."), 1), "name") =~? "comment"') 813 call assert_equal('Another Text for VIM', getline('.')) 814 1 815 call search('VIM', 'w', '', 0, 'synIDattr(synID(line("."), col("."), 1), "name") !~? "string"') 816 call assert_equal(' let a = "VIM"', getline('.')) 817 818 " Skip argument using Lambda. 819 1 820 call search('VIM', 'w', '', 0, { -> synIDattr(synID(line("."), col("."), 1), "name") =~? "comment"}) 821 call assert_equal('Another Text for VIM', getline('.')) 822 823 1 824 call search('VIM', 'w', '', 0, { -> synIDattr(synID(line("."), col("."), 1), "name") !~? "string"}) 825 call assert_equal(' let a = "VIM"', getline('.')) 826 827 " Skip argument using funcref. 828 func InComment() 829 return synIDattr(synID(line("."), col("."), 1), "name") =~? "comment" 830 endfunc 831 func InString() 832 return synIDattr(synID(line("."), col("."), 1), "name") !~? "string" 833 endfunc 834 1 835 call search('VIM', 'w', '', 0, function('InComment')) 836 call assert_equal('Another Text for VIM', getline('.')) 837 838 1 839 call search('VIM', 'w', '', 0, function('InString')) 840 call assert_equal(' let a = "VIM"', getline('.')) 841 842 delfunc InComment 843 delfunc InString 844 bwipe! 845endfunc 846 847func Test_syn_contained_transparent() 848 " Comments starting with "Regression:" show the result when the highlighting 849 " span of the containing item is assigned to the contained region. 850 syntax on 851 852 let l:case = "Transparent region contained in region" 853 new 854 syntax region X start=/\[/ end=/\]/ contained transparent 855 syntax region Y start=/(/ end=/)/ contains=X 856 857 call setline(1, "==(--[~~]--)==") 858 let l:expected = " YYYYYYYYYY " 859 eval AssertHighlightGroups(1, 1, l:expected, 1, l:case) 860 syntax clear Y X 861 bw! 862 863 let l:case = "Transparent region extends region" 864 new 865 syntax region X start=/\[/ end=/\]/ contained transparent 866 syntax region Y start=/(/ end=/)/ end=/e/ contains=X 867 868 call setline(1, "==(--[~~e~~]--)==") 869 let l:expected = " YYYYYYYYYYYYY " 870 " Regression: " YYYYYYY YYY " 871 eval AssertHighlightGroups(1, 1, l:expected, 1, l:case) 872 syntax clear Y X 873 bw! 874 875 let l:case = "Nested transparent regions extend region" 876 new 877 syntax region X start=/\[/ end=/\]/ contained transparent 878 syntax region Y start=/(/ end=/)/ end=/e/ contains=X 879 880 call setline(1, "==(--[~~e~~[~~e~~]~~e~~]--)==") 881 let l:expected = " YYYYYYYYYYYYYYYYYYYYYYYYY " 882 " Regression: " YYYYYYY YYYYYYYYY " 883 eval AssertHighlightGroups(1, 1, l:expected, 1, l:case) 884 syntax clear Y X 885 bw! 886 887 let l:case = "Transparent region contained in match" 888 new 889 syntax region X start=/\[/ end=/\]/ contained transparent 890 syntax match Y /(.\{-})/ contains=X 891 892 call setline(1, "==(--[~~]--)==") 893 let l:expected = " YYYYYYYYYY " 894 eval AssertHighlightGroups(1, 1, l:expected, 1, l:case) 895 syntax clear Y X 896 bw! 897 898 let l:case = "Transparent region extends match" 899 new 900 syntax region X start=/\[/ end=/\]/ contained transparent 901 syntax match Y /(.\{-}[e)]/ contains=X 902 903 call setline(1, "==(--[~~e~~]--)==") 904 let l:expected = " YYYYYYYYYY " 905 " Regression: " YYYYYYY " 906 eval AssertHighlightGroups(1, 1, l:expected, 1, l:case) 907 syntax clear Y X 908 bw! 909 910 let l:case = "Nested transparent regions extend match" 911 new 912 syntax region X start=/\[/ end=/\]/ contained transparent 913 syntax match Y /(.\{-}[e)]/ contains=X 914 915 call setline(1, "==(--[~~e~~[~~e~~]~~e~~]--)==") 916 let l:expected = " YYYYYYYYYYYYYYYYYYYYYY " 917 " Regression: " YYYYYYY YYYYYY " 918 eval AssertHighlightGroups(1, 1, l:expected, 1, l:case) 919 syntax clear Y X 920 bw! 921endfunc 922 923" vim: shiftwidth=2 sts=2 expandtab 924