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