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