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