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 call assert_equal(['cComment', 'cCommentStart'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")')) 521 call assert_equal(['Comment', 'Comment'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")')) 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