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