xref: /vim-8.2.3635/src/testdir/test_syntax.vim (revision 5ee0981f)
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  syn sync fromstart
320  call assert_match('syncing starts at the first line', execute('syntax sync'))
321
322  syn clear
323endfunc
324
325" Check for an error. Used when multiple errors are thrown and we are checking
326" for an earliest error.
327func AssertFails(cmd, errcode)
328  let save_exception = ''
329  try
330    exe a:cmd
331  catch
332    let save_exception = v:exception
333  endtry
334  call assert_match(a:errcode, save_exception)
335endfunc
336
337func Test_syntax_invalid_arg()
338  call assert_fails('syntax case asdf', 'E390:')
339  if has('conceal')
340    call assert_fails('syntax conceal asdf', 'E390:')
341  endif
342  call assert_fails('syntax spell asdf', 'E390:')
343  call assert_fails('syntax clear @ABCD', 'E391:')
344  call assert_fails('syntax include random_file', 'E484:')
345  call assert_fails('syntax include <afile>', 'E495:')
346  call assert_fails('syntax sync x', 'E404:')
347  call assert_fails('syntax keyword Abc a[', 'E789:')
348  call assert_fails('syntax keyword Abc a[bc]d', 'E890:')
349  call assert_fails('syntax cluster Abc add=A add=', 'E406:')
350
351  " Test for too many \z\( and unmatched \z\(
352  " Not able to use assert_fails() here because both E50:/E879: and E475:
353  " messages are emitted.
354  set regexpengine=1
355  call AssertFails("syntax region MyRegion start='\\z\\(' end='\\*/'", 'E52:')
356
357  let cmd = "syntax region MyRegion start='"
358  let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'"
359  call AssertFails(cmd, 'E50:')
360
361  set regexpengine=2
362  call AssertFails("syntax region MyRegion start='\\z\\(' end='\\*/'", 'E54:')
363
364  let cmd = "syntax region MyRegion start='"
365  let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'"
366  call AssertFails(cmd, 'E879:')
367  set regexpengine&
368
369  call AssertFails('syntax keyword cMyItem grouphere G1', 'E393:')
370  call AssertFails('syntax sync match Abc grouphere MyItem "abc"', 'E394:')
371  call AssertFails('syn keyword Type contains int', 'E395:')
372  call assert_fails('syntax include @Xxx', 'E397:')
373  call AssertFails('syntax region X start', 'E398:')
374  call assert_fails('syntax region X start="{"', 'E399:')
375  call AssertFails('syntax cluster contains=Abc', 'E400:')
376  call AssertFails("syntax match Character /'.'", 'E401:')
377  call AssertFails("syntax match Character /'.'/a", 'E402:')
378  call assert_fails('syntax sync linecont /\%(/', 'E53:')
379  call assert_fails('syntax sync linecont /pat', 'E404:')
380  call assert_fails('syntax sync linecont', 'E404:')
381  call assert_fails('syntax sync linecont /pat1/ linecont /pat2/', 'E403:')
382  call assert_fails('syntax sync minlines=a', 'E404:')
383  call AssertFails('syntax match ABC /x/ contains=', 'E406:')
384  call AssertFails("syntax match Character contains /'.'/", 'E405:')
385  call AssertFails('syntax match ccFoo "Foo" nextgroup=ALLBUT,F', 'E407:')
386  call AssertFails('syntax region Block start="{" contains=F,ALLBUT', 'E408:')
387  call AssertFails("syntax match Characters contains=a.*x /'.'/", 'E409:')
388  call assert_fails('syntax match Search /abc/ contains=ALLBUT,/\%(/', 'E53:')
389endfunc
390
391func Test_syn_sync()
392  syntax region HereGroup start=/this/ end=/that/
393  syntax sync match SyncHere grouphere HereGroup "pattern"
394  call assert_match('SyncHere', execute('syntax sync'))
395  syn sync clear
396  call assert_notmatch('SyncHere', execute('syntax sync'))
397  syn clear
398endfunc
399
400func Test_syn_clear()
401  syntax keyword Foo foo
402  syntax keyword Bar tar
403  call assert_match('Foo', execute('syntax'))
404  call assert_match('Bar', execute('syntax'))
405  call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
406  syn clear Foo
407  call assert_notmatch('Foo', execute('syntax'))
408  call assert_match('Bar', execute('syntax'))
409  call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
410  syn clear Foo Bar
411  call assert_notmatch('Foo', execute('syntax'))
412  call assert_notmatch('Bar', execute('syntax'))
413  hi clear Foo
414  call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
415  hi clear Bar
416  call assert_fails('syntax clear invalid_syngroup', 'E28:')
417endfunc
418
419func Test_invalid_name()
420  syn clear
421  syn keyword Nop yes
422  call assert_fails("syntax keyword Wr\x17ong bar", 'E669:')
423  syntax keyword @Wrong bar
424  call assert_match('W18:', execute('1messages'))
425  syn clear
426  hi clear Nop
427  hi clear @Wrong
428endfunc
429
430func Test_ownsyntax()
431  new Xfoo
432  call setline(1, '#define FOO')
433  syntax on
434  set filetype=c
435
436  ownsyntax perl
437  " this should not crash
438  set
439
440  call assert_equal('perlComment', synIDattr(synID(line('.'), col('.'), 1), 'name'))
441  call assert_equal('c',    b:current_syntax)
442  call assert_equal('perl', w:current_syntax)
443
444  " A new split window should have the original syntax.
445  split
446  call assert_equal('cDefine', synIDattr(synID(line('.'), col('.'), 1), 'name'))
447  call assert_equal('c', b:current_syntax)
448  call assert_equal(0, exists('w:current_syntax'))
449
450  wincmd x
451  call assert_equal('perlComment', synIDattr(synID(line("."), col("."), 1), "name"))
452
453  syntax off
454  set filetype&
455  %bw!
456endfunc
457
458func Test_ownsyntax_completion()
459  call feedkeys(":ownsyntax java\<C-A>\<C-B>\"\<CR>", 'tx')
460  call assert_equal('"ownsyntax java javacc javascript javascriptreact', @:)
461endfunc
462
463func Test_highlight_invalid_arg()
464  if has('gui_running')
465    call assert_fails('hi XXX guifg=xxx', 'E254:')
466  endif
467  call assert_fails('hi DoesNotExist', 'E411:')
468  call assert_fails('hi link', 'E412:')
469  call assert_fails('hi link a', 'E412:')
470  call assert_fails('hi link a b c', 'E413:')
471  call assert_fails('hi XXX =', 'E415:')
472  call assert_fails('hi XXX cterm', 'E416:')
473  call assert_fails('hi XXX cterm=', 'E417:')
474  call assert_fails('hi XXX cterm=DoesNotExist', 'E418:')
475  call assert_fails('hi XXX ctermfg=DoesNotExist', 'E421:')
476  call assert_fails('hi XXX xxx=White', 'E423:')
477endfunc
478
479func Test_bg_detection()
480  CheckNotGui
481
482  " auto-detection of &bg, make sure sure it isn't set anywhere before
483  " this test
484  hi Normal ctermbg=0
485  call assert_equal('dark', &bg)
486  hi Normal ctermbg=4
487  call assert_equal('dark', &bg)
488  hi Normal ctermbg=12
489  call assert_equal('light', &bg)
490  hi Normal ctermbg=15
491  call assert_equal('light', &bg)
492
493  " manually-set &bg takes precedence over auto-detection
494  set bg=light
495  hi Normal ctermbg=4
496  call assert_equal('light', &bg)
497  set bg=dark
498  hi Normal ctermbg=12
499  call assert_equal('dark', &bg)
500
501  hi Normal ctermbg=NONE
502endfunc
503
504func Test_syntax_hangs()
505  CheckFunction reltimefloat
506  CheckFeature syntax
507
508  " This pattern takes a long time to match, it should timeout.
509  new
510  call setline(1, ['aaa', repeat('abc ', 1000), 'ccc'])
511  let start = reltime()
512  set nolazyredraw redrawtime=101
513  syn match Error /\%#=1a*.*X\@<=b*/
514  redraw
515  let elapsed = reltimefloat(reltime(start))
516  call assert_true(elapsed > 0.1)
517  call assert_true(elapsed < 1.0)
518
519  " second time syntax HL is disabled
520  let start = reltime()
521  redraw
522  let elapsed = reltimefloat(reltime(start))
523  call assert_true(elapsed < 0.1)
524
525  " after CTRL-L the timeout flag is reset
526  let start = reltime()
527  exe "normal \<C-L>"
528  redraw
529  let elapsed = reltimefloat(reltime(start))
530  call assert_true(elapsed > 0.1)
531  call assert_true(elapsed < 1.0)
532
533  set redrawtime&
534  bwipe!
535endfunc
536
537func Test_conceal()
538  CheckFeature conceal
539
540  new
541  call setline(1, ['', '123456'])
542  syn match test23 "23" conceal cchar=X
543  syn match test45 "45" conceal
544
545  set conceallevel=0
546  call assert_equal('123456 ', ScreenLines(2, 7)[0])
547  call assert_equal([[0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
548
549  set conceallevel=1
550  call assert_equal('1X 6   ', ScreenLines(2, 7)[0])
551  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)'))
552
553  set conceallevel=1
554  set listchars=conceal:Y
555  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)'))
556  call assert_equal('1XY6   ', ScreenLines(2, 7)[0])
557
558  set conceallevel=2
559  call assert_match('1X6    ', ScreenLines(2, 7)[0])
560  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)'))
561
562  set conceallevel=3
563  call assert_match('16     ', ScreenLines(2, 7)[0])
564  call assert_equal([[0, '', 0], [1, '', 1], [1, '', 1], [1, '', 2], [1, '', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
565
566  call AssertFails("syntax match Entity '&amp;' conceal cchar=\<Tab>", 'E844:')
567
568  syn clear
569  set conceallevel&
570  bw!
571endfunc
572
573func Test_synstack_synIDtrans()
574  new
575  setfiletype c
576  syntax on
577  call setline(1, ' /* A comment with a TODO */')
578
579  call assert_equal([], synstack(1, 1))
580
581  norm f/
582  eval synstack(line("."), col("."))->map('synIDattr(v:val, "name")')->assert_equal(['cComment', 'cCommentStart'])
583  eval synstack(line("."), col("."))->map('synIDattr(synIDtrans(v:val), "name")')->assert_equal(['Comment', 'Comment'])
584
585  norm fA
586  call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
587  call assert_equal(['Comment'],  map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
588
589  norm fT
590  call assert_equal(['cComment', 'cTodo'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
591  call assert_equal(['Comment', 'Todo'],   map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
592
593  call assert_fails("let n=synIDtrans([])", 'E745:')
594
595  syn clear
596  bw!
597endfunc
598
599" Check highlighting for a small piece of C code with a screen dump.
600func Test_syntax_c()
601  CheckRunVimInTerminal
602  call writefile([
603	\ '/* comment line at the top */',
604	\ 'int main(int argc, char **argv) { // another comment',
605	\ '#if 0',
606	\ '   int   not_used;',
607	\ '#else',
608	\ '   int   used;',
609	\ '#endif',
610	\ '   printf("Just an example piece of C code\n");',
611	\ '   return 0x0ff;',
612	\ '}',
613	\ "\t\t ",
614	\ '   static void',
615	\ 'myFunction(const double count, struct nothing, long there) {',
616	\ "\t// 123: nothing to endif here",
617	\ "\tfor (int i = 0; i < count; ++i) {",
618	\ "\t   break;",
619	\ "\t}",
620	\ "\tNote: asdf",
621	\ '}',
622	\ ], 'Xtest.c')
623
624  " This makes the default for 'background' use "dark", check that the
625  " response to t_RB corrects it to "light".
626  let $COLORFGBG = '15;0'
627
628  let buf = RunVimInTerminal('Xtest.c', {})
629  call term_sendkeys(buf, ":syn keyword Search Note\r")
630  call term_sendkeys(buf, ":syn match Error /^\\s\\+$/\r")
631  call term_sendkeys(buf, ":set hlsearch\r")
632  call term_sendkeys(buf, "/endif\r")
633  call term_sendkeys(buf, "vjfC")
634  call VerifyScreenDump(buf, 'Test_syntax_c_01', {})
635
636  call term_sendkeys(buf, "\<Esc>")
637  call StopVimInTerminal(buf)
638
639  let $COLORFGBG = ''
640  call delete('Xtest.c')
641endfun
642
643" Using \z() in a region with NFA failing should not crash.
644func Test_syn_wrong_z_one()
645  new
646  call setline(1, ['just some text', 'with foo and bar to match with'])
647  syn region FooBar start="foo\z(.*\)bar" end="\z1"
648  call test_override("nfa_fail", 1)
649  redraw!
650  redraw!
651  call test_override("ALL", 0)
652  bwipe!
653endfunc
654
655func Test_syntax_after_bufdo()
656  call writefile(['/* aaa comment */'], 'Xaaa.c')
657  call writefile(['/* bbb comment */'], 'Xbbb.c')
658  call writefile(['/* ccc comment */'], 'Xccc.c')
659  call writefile(['/* ddd comment */'], 'Xddd.c')
660
661  let bnr = bufnr('%')
662  new Xaaa.c
663  badd Xbbb.c
664  badd Xccc.c
665  badd Xddd.c
666  exe "bwipe " . bnr
667  let l = []
668  bufdo call add(l, bufnr('%'))
669  call assert_equal(4, len(l))
670
671  syntax on
672
673  " This used to only enable syntax HL in the last buffer.
674  bufdo tab split
675  tabrewind
676  for tab in range(1, 4)
677    norm fm
678    call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
679    tabnext
680  endfor
681
682  bwipe! Xaaa.c
683  bwipe! Xbbb.c
684  bwipe! Xccc.c
685  bwipe! Xddd.c
686  syntax off
687  call delete('Xaaa.c')
688  call delete('Xbbb.c')
689  call delete('Xccc.c')
690  call delete('Xddd.c')
691endfunc
692
693func Test_syntax_foldlevel()
694  new
695  call setline(1, [
696   \ 'void f(int a)',
697   \ '{',
698   \ '    if (a == 1) {',
699   \ '        a = 0;',
700   \ '    } else if (a == 2) {',
701   \ '        a = 1;',
702   \ '    } else {',
703   \ '        a = 2;',
704   \ '    }',
705   \ '    if (a > 0) {',
706   \ '        if (a == 1) {',
707   \ '            a = 0;',
708   \ '        } /* missing newline */ } /* end of outer if */ else {',
709   \ '        a = 1;',
710   \ '    }',
711   \ '    if (a == 1)',
712   \ '    {',
713   \ '        a = 0;',
714   \ '    }',
715   \ '    else if (a == 2)',
716   \ '    {',
717   \ '        a = 1;',
718   \ '    }',
719   \ '    else',
720   \ '    {',
721   \ '        a = 2;',
722   \ '    }',
723   \ '}',
724   \ ])
725  setfiletype c
726  syntax on
727  set foldmethod=syntax
728
729  call assert_fails('syn foldlevel start start', 'E390:')
730  call assert_fails('syn foldlevel not_an_option', 'E390:')
731
732  set foldlevel=1
733
734  syn foldlevel start
735  redir @c
736  syn foldlevel
737  redir END
738  call assert_equal("\nsyntax foldlevel start", @c)
739  syn sync fromstart
740  call assert_match('from the first line$', execute('syn sync'))
741  let a = map(range(3,9), 'foldclosed(v:val)')
742  call assert_equal([3,3,3,3,3,3,3], a) " attached cascade folds together
743  let a = map(range(10,15), 'foldclosed(v:val)')
744  call assert_equal([10,10,10,10,10,10], a) " over-attached 'else' hidden
745  let a = map(range(16,27), 'foldclosed(v:val)')
746  let unattached_results = [-1,17,17,17,-1,21,21,21,-1,25,25,25]
747  call assert_equal(unattached_results, a) " unattached cascade folds separately
748
749  syn foldlevel minimum
750  redir @c
751  syn foldlevel
752  redir END
753  call assert_equal("\nsyntax foldlevel minimum", @c)
754  syn sync fromstart
755  let a = map(range(3,9), 'foldclosed(v:val)')
756  call assert_equal([3,3,5,5,7,7,7], a) " attached cascade folds separately
757  let a = map(range(10,15), 'foldclosed(v:val)')
758  call assert_equal([10,10,10,13,13,13], a) " over-attached 'else' visible
759  let a = map(range(16,27), 'foldclosed(v:val)')
760  call assert_equal(unattached_results, a) " unattached cascade folds separately
761
762  set foldlevel=2
763
764  syn foldlevel start
765  syn sync fromstart
766  let a = map(range(11,14), 'foldclosed(v:val)')
767  call assert_equal([11,11,11,-1], a) " over-attached 'else' hidden
768
769  syn foldlevel minimum
770  syn sync fromstart
771  let a = map(range(11,14), 'foldclosed(v:val)')
772  call assert_equal([11,11,-1,-1], a) " over-attached 'else' visible
773
774  quit!
775endfunc
776
777func Test_search_syntax_skip()
778  new
779  let lines =<< trim END
780
781        /* This is VIM */
782        Another Text for VIM
783         let a = "VIM"
784  END
785  call setline(1, lines)
786  syntax on
787  syntax match Comment "^/\*.*\*/"
788  syntax match String '".*"'
789
790  " Skip argument using string evaluation.
791  1
792  call search('VIM', 'w', '', 0, 'synIDattr(synID(line("."), col("."), 1), "name") =~? "comment"')
793  call assert_equal('Another Text for VIM', getline('.'))
794  1
795  call search('VIM', 'w', '', 0, 'synIDattr(synID(line("."), col("."), 1), "name") !~? "string"')
796  call assert_equal(' let a = "VIM"', getline('.'))
797
798  " Skip argument using Lambda.
799  1
800  call search('VIM', 'w', '', 0, { -> synIDattr(synID(line("."), col("."), 1), "name") =~? "comment"})
801  call assert_equal('Another Text for VIM', getline('.'))
802
803  1
804  call search('VIM', 'w', '', 0, { -> synIDattr(synID(line("."), col("."), 1), "name") !~? "string"})
805  call assert_equal(' let a = "VIM"', getline('.'))
806
807  " Skip argument using funcref.
808  func InComment()
809    return synIDattr(synID(line("."), col("."), 1), "name") =~? "comment"
810  endfunc
811  func InString()
812    return synIDattr(synID(line("."), col("."), 1), "name") !~? "string"
813  endfunc
814  1
815  call search('VIM', 'w', '', 0, function('InComment'))
816  call assert_equal('Another Text for VIM', getline('.'))
817
818  1
819  call search('VIM', 'w', '', 0, function('InString'))
820  call assert_equal(' let a = "VIM"', getline('.'))
821
822  delfunc InComment
823  delfunc InString
824  bwipe!
825endfunc
826
827" vim: shiftwidth=2 sts=2 expandtab
828