xref: /vim-8.2.3635/src/testdir/test_syntax.vim (revision 4e63f942)
1" Test for syntax and syntax iskeyword option
2
3source check.vim
4CheckFeature syntax
5
6source view_util.vim
7source screendump.vim
8
9func GetSyntaxItem(pat)
10  let c = ''
11  let a = ['a', getreg('a'), getregtype('a')]
12  0
13  redraw!
14  call search(a:pat, 'W')
15  let synid = synID(line('.'), col('.'), 1)
16  while synid == synID(line('.'), col('.'), 1)
17    norm! v"ay
18    " stop at whitespace
19    if @a =~# '\s'
20      break
21    endif
22    let c .= @a
23    norm! l
24  endw
25  call call('setreg', a)
26  0
27  return c
28endfunc
29
30func Test_syn_iskeyword()
31  new
32  call setline(1, [
33	\ 'CREATE TABLE FOOBAR(',
34	\ '    DLTD_BY VARCHAR2(100)',
35	\ ');',
36	\ ''])
37
38  syntax on
39  set ft=sql
40  syn match SYN /C\k\+\>/
41  hi link SYN ErrorMsg
42  call assert_equal('DLTD_BY', GetSyntaxItem('DLTD'))
43  /\<D\k\+\>/:norm! ygn
44  call assert_equal('DLTD_BY', @0)
45  redir @c
46  syn iskeyword
47  redir END
48  call assert_equal("\nsyntax iskeyword not set", @c)
49
50  syn iskeyword @,48-57,_,192-255
51  redir @c
52  syn iskeyword
53  redir END
54  call assert_equal("\nsyntax iskeyword @,48-57,_,192-255", @c)
55
56  setlocal isk-=_
57  call assert_equal('DLTD_BY', GetSyntaxItem('DLTD'))
58  /\<D\k\+\>/:norm! ygn
59  let b2 = @0
60  call assert_equal('DLTD', @0)
61
62  syn iskeyword clear
63  redir @c
64  syn iskeyword
65  redir END
66  call assert_equal("\nsyntax iskeyword not set", @c)
67
68  quit!
69endfunc
70
71func Test_syntax_after_reload()
72  split Xsomefile
73  call setline(1, ['hello', 'there'])
74  w!
75  only!
76  setl filetype=hello
77  au FileType hello let g:gotit = 1
78  call assert_false(exists('g:gotit'))
79  edit other
80  buf Xsomefile
81  call assert_equal('hello', &filetype)
82  call assert_true(exists('g:gotit'))
83  call delete('Xsomefile')
84endfunc
85
86func Test_syntime()
87  if !has('profile')
88    return
89  endif
90
91  syntax on
92  syntime on
93  let a = execute('syntime report')
94  call assert_equal("\nNo Syntax items defined for this buffer", a)
95
96  view ../memfile_test.c
97  setfiletype cpp
98  redraw
99  let a = execute('syntime report')
100  call assert_match('^  TOTAL *COUNT *MATCH *SLOWEST *AVERAGE *NAME *PATTERN', a)
101  call assert_match(' \d*\.\d* \+[^0]\d* .* cppRawString ', a)
102  call assert_match(' \d*\.\d* \+[^0]\d* .* cppNumber ', a)
103
104  syntime off
105  syntime clear
106  let a = execute('syntime report')
107  call assert_match('^  TOTAL *COUNT *MATCH *SLOWEST *AVERAGE *NAME *PATTERN', a)
108  call assert_notmatch('.* cppRawString *', a)
109  call assert_notmatch('.* cppNumber*', a)
110  call assert_notmatch('[1-9]', a)
111
112  call assert_fails('syntime abc', 'E475')
113
114  syntax clear
115  let a = execute('syntime report')
116  call assert_equal("\nNo Syntax items defined for this buffer", a)
117
118  bd
119endfunc
120
121func Test_syntime_completion()
122  if !has('profile')
123    return
124  endif
125
126  call feedkeys(":syntime \<C-A>\<C-B>\"\<CR>", 'tx')
127  call assert_equal('"syntime clear off on report', @:)
128endfunc
129
130func Test_syntax_list()
131  syntax on
132  let a = execute('syntax list')
133  call assert_equal("\nNo Syntax items defined for this buffer", a)
134
135  view ../memfile_test.c
136  setfiletype c
137
138  let a = execute('syntax list')
139  call assert_match('cInclude*', a)
140  call assert_match('cDefine', a)
141
142  let a = execute('syntax list cDefine')
143  call assert_notmatch('cInclude*', a)
144  call assert_match('cDefine', a)
145  call assert_match(' links to Macro$', a)
146
147  call assert_fails('syntax list ABCD', 'E28:')
148  call assert_fails('syntax list @ABCD', 'E392:')
149
150  syntax clear
151  let a = execute('syntax list')
152  call assert_equal("\nNo Syntax items defined for this buffer", a)
153
154  bd
155endfunc
156
157func Test_syntax_completion()
158  call feedkeys(":syn \<C-A>\<C-B>\"\<CR>", 'tx')
159  call assert_equal('"syn case clear cluster conceal enable include iskeyword keyword list manual match off on region reset spell sync', @:)
160
161  call feedkeys(":syn case \<C-A>\<C-B>\"\<CR>", 'tx')
162  call assert_equal('"syn case ignore match', @:)
163
164  call feedkeys(":syn spell \<C-A>\<C-B>\"\<CR>", 'tx')
165  call assert_equal('"syn spell default notoplevel toplevel', @:)
166
167  call feedkeys(":syn sync \<C-A>\<C-B>\"\<CR>", 'tx')
168  call assert_equal('"syn sync ccomment clear fromstart linebreaks= linecont lines= match maxlines= minlines= region', @:)
169
170  " Check that clearing "Aap" avoids it showing up before Boolean.
171  hi Aap ctermfg=blue
172  call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx')
173  call assert_match('^"syn list Aap Boolean Character ', @:)
174  hi clear Aap
175
176  call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx')
177  call assert_match('^"syn list Boolean Character ', @:)
178
179  call feedkeys(":syn match \<C-A>\<C-B>\"\<CR>", 'tx')
180  call assert_match('^"syn match Boolean Character ', @:)
181endfunc
182
183func Test_syntax_arg_skipped()
184  syn clear
185  syntax case ignore
186  if 0
187    syntax case match
188  endif
189  call assert_match('case ignore', execute('syntax case'))
190
191  syn keyword Foo foo
192  call assert_match('Foo', execute('syntax'))
193  syn clear
194  call assert_match('case match', execute('syntax case'))
195  call assert_notmatch('Foo', execute('syntax'))
196
197  if has('conceal')
198    syn clear
199    syntax conceal on
200    if 0
201      syntax conceal off
202    endif
203    call assert_match('conceal on', execute('syntax conceal'))
204    syn clear
205    call assert_match('conceal off', execute('syntax conceal'))
206
207    syntax conceal on
208    syntax conceal off
209    call assert_match('conceal off', execute('syntax conceal'))
210  endif
211
212  syntax region Bar start=/</ end=/>/
213  if 0
214    syntax region NotTest start=/</ end=/>/ contains=@Spell
215  endif
216  call assert_match('Bar', execute('syntax'))
217  call assert_notmatch('NotTest', execute('syntax'))
218  call assert_notmatch('Spell', execute('syntax'))
219
220  hi Foo ctermfg=blue
221  let a = execute('hi Foo')
222  if 0
223    syntax rest
224  endif
225  call assert_equal(a, execute('hi Foo'))
226  hi clear Bar
227  hi clear Foo
228
229  set ft=tags
230  syn off
231  if 0
232    syntax enable
233  endif
234  call assert_match('No Syntax items defined', execute('syntax'))
235  syntax enable
236  call assert_match('tagComment', execute('syntax'))
237  set ft=
238
239  syn clear
240  if 0
241    syntax include @Spell nothing
242  endif
243  call assert_notmatch('Spell', execute('syntax'))
244
245  syn clear
246  syn iskeyword 48-57,$,_
247  call assert_match('48-57,$,_', execute('syntax iskeyword'))
248  if 0
249    syn clear
250    syn iskeyword clear
251  endif
252  call assert_match('48-57,$,_', execute('syntax iskeyword'))
253  syn iskeyword clear
254  call assert_match('not set', execute('syntax iskeyword'))
255  syn iskeyword 48-57,$,_
256  syn clear
257  call assert_match('not set', execute('syntax iskeyword'))
258
259  syn clear
260  syn keyword Foo foo
261  if 0
262    syn keyword NotAdded bar
263  endif
264  call assert_match('Foo', execute('syntax'))
265  call assert_notmatch('NotAdded', execute('highlight'))
266
267  syn clear
268  syn keyword Foo foo
269  call assert_match('Foo', execute('syntax'))
270  call assert_match('Foo', execute('syntax list'))
271  call assert_notmatch('Foo', execute('if 0 | syntax | endif'))
272  call assert_notmatch('Foo', execute('if 0 | syntax list | endif'))
273
274  syn clear
275  syn match Fopi /asdf/
276  if 0
277    syn match Fopx /asdf/
278  endif
279  call assert_match('Fopi', execute('syntax'))
280  call assert_notmatch('Fopx', execute('syntax'))
281
282  syn clear
283  syn spell toplevel
284  call assert_match('spell toplevel', execute('syntax spell'))
285  if 0
286    syn spell notoplevel
287  endif
288  call assert_match('spell toplevel', execute('syntax spell'))
289  syn spell notoplevel
290  call assert_match('spell notoplevel', execute('syntax spell'))
291  syn spell default
292  call assert_match('spell default', execute('syntax spell'))
293
294  syn clear
295  if 0
296    syntax cluster Spell
297  endif
298  call assert_notmatch('Spell', execute('syntax'))
299
300  syn clear
301  syn keyword Foo foo
302  syn sync ccomment
303  syn sync maxlines=5
304  if 0
305    syn sync maxlines=11
306  endif
307  call assert_match('on C-style comments', execute('syntax sync'))
308  call assert_match('maximal 5 lines', execute('syntax sync'))
309  syn sync clear
310  if 0
311    syn sync ccomment
312  endif
313  call assert_notmatch('on C-style comments', execute('syntax sync'))
314
315  syn clear
316endfunc
317
318func Test_syntax_invalid_arg()
319  call assert_fails('syntax case asdf', 'E390:')
320  if has('conceal')
321    call assert_fails('syntax conceal asdf', 'E390:')
322  endif
323  call assert_fails('syntax spell asdf', 'E390:')
324  call assert_fails('syntax clear @ABCD', 'E391:')
325  call assert_fails('syntax include @Xxx', 'E397:')
326  call assert_fails('syntax region X start="{"', 'E399:')
327  call assert_fails('syntax sync x', 'E404:')
328  call assert_fails('syntax keyword Abc a[', 'E789:')
329  call assert_fails('syntax keyword Abc a[bc]d', 'E890:')
330endfunc
331
332func Test_syn_sync()
333  syntax region HereGroup start=/this/ end=/that/
334  syntax sync match SyncHere grouphere HereGroup "pattern"
335  call assert_match('SyncHere', execute('syntax sync'))
336  syn sync clear
337  call assert_notmatch('SyncHere', execute('syntax sync'))
338  syn clear
339endfunc
340
341func Test_syn_clear()
342  syntax keyword Foo foo
343  syntax keyword Bar tar
344  call assert_match('Foo', execute('syntax'))
345  call assert_match('Bar', execute('syntax'))
346  call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
347  syn clear Foo
348  call assert_notmatch('Foo', execute('syntax'))
349  call assert_match('Bar', execute('syntax'))
350  call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
351  syn clear Foo Bar
352  call assert_notmatch('Foo', execute('syntax'))
353  call assert_notmatch('Bar', execute('syntax'))
354  hi clear Foo
355  call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
356  hi clear Bar
357endfunc
358
359func Test_invalid_name()
360  syn clear
361  syn keyword Nop yes
362  call assert_fails("syntax keyword Wr\x17ong bar", 'E669:')
363  syntax keyword @Wrong bar
364  call assert_match('W18:', execute('1messages'))
365  syn clear
366  hi clear Nop
367  hi clear @Wrong
368endfunc
369
370func Test_ownsyntax()
371  new Xfoo
372  call setline(1, '#define FOO')
373  syntax on
374  set filetype=c
375  ownsyntax perl
376  call assert_equal('perlComment', synIDattr(synID(line('.'), col('.'), 1), 'name'))
377  call assert_equal('c',    b:current_syntax)
378  call assert_equal('perl', w:current_syntax)
379
380  " A new split window should have the original syntax.
381  split
382  call assert_equal('cDefine', synIDattr(synID(line('.'), col('.'), 1), 'name'))
383  call assert_equal('c', b:current_syntax)
384  call assert_equal(0, exists('w:current_syntax'))
385
386  wincmd x
387  call assert_equal('perlComment', synIDattr(synID(line("."), col("."), 1), "name"))
388
389  syntax off
390  set filetype&
391  %bw!
392endfunc
393
394func Test_ownsyntax_completion()
395  call feedkeys(":ownsyntax java\<C-A>\<C-B>\"\<CR>", 'tx')
396  call assert_equal('"ownsyntax java javacc javascript', @:)
397endfunc
398
399func Test_highlight_invalid_arg()
400  if has('gui_running')
401    call assert_fails('hi XXX guifg=xxx', 'E254:')
402  endif
403  call assert_fails('hi DoesNotExist', 'E411:')
404  call assert_fails('hi link', 'E412:')
405  call assert_fails('hi link a', 'E412:')
406  call assert_fails('hi link a b c', 'E413:')
407  call assert_fails('hi XXX =', 'E415:')
408  call assert_fails('hi XXX cterm', 'E416:')
409  call assert_fails('hi XXX cterm=', 'E417:')
410  call assert_fails('hi XXX cterm=DoesNotExist', 'E418:')
411  call assert_fails('hi XXX ctermfg=DoesNotExist', 'E421:')
412  call assert_fails('hi XXX xxx=White', 'E423:')
413endfunc
414
415func Test_bg_detection()
416  if has('gui_running')
417    return
418  endif
419  " auto-detection of &bg, make sure sure it isn't set anywhere before
420  " this test
421  hi Normal ctermbg=0
422  call assert_equal('dark', &bg)
423  hi Normal ctermbg=4
424  call assert_equal('dark', &bg)
425  hi Normal ctermbg=12
426  call assert_equal('light', &bg)
427  hi Normal ctermbg=15
428  call assert_equal('light', &bg)
429
430  " manually-set &bg takes precedence over auto-detection
431  set bg=light
432  hi Normal ctermbg=4
433  call assert_equal('light', &bg)
434  set bg=dark
435  hi Normal ctermbg=12
436  call assert_equal('dark', &bg)
437
438  hi Normal ctermbg=NONE
439endfunc
440
441func Test_syntax_hangs()
442  if !has('reltime') || !has('float') || !has('syntax')
443    return
444  endif
445
446  " This pattern takes a long time to match, it should timeout.
447  new
448  call setline(1, ['aaa', repeat('abc ', 1000), 'ccc'])
449  let start = reltime()
450  set nolazyredraw redrawtime=101
451  syn match Error /\%#=1a*.*X\@<=b*/
452  redraw
453  let elapsed = reltimefloat(reltime(start))
454  call assert_true(elapsed > 0.1)
455  call assert_true(elapsed < 1.0)
456
457  " second time syntax HL is disabled
458  let start = reltime()
459  redraw
460  let elapsed = reltimefloat(reltime(start))
461  call assert_true(elapsed < 0.1)
462
463  " after CTRL-L the timeout flag is reset
464  let start = reltime()
465  exe "normal \<C-L>"
466  redraw
467  let elapsed = reltimefloat(reltime(start))
468  call assert_true(elapsed > 0.1)
469  call assert_true(elapsed < 1.0)
470
471  set redrawtime&
472  bwipe!
473endfunc
474
475func Test_conceal()
476  if !has('conceal')
477    return
478  endif
479
480  new
481  call setline(1, ['', '123456'])
482  syn match test23 "23" conceal cchar=X
483  syn match test45 "45" conceal
484
485  set conceallevel=0
486  call assert_equal('123456 ', ScreenLines(2, 7)[0])
487  call assert_equal([[0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
488
489  set conceallevel=1
490  call assert_equal('1X 6   ', ScreenLines(2, 7)[0])
491  call assert_equal([[0, '', 0], [1, 'X', 1], [1, 'X', 1], [1, ' ', 2], [1, ' ', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
492
493  set conceallevel=1
494  set listchars=conceal:Y
495  call assert_equal([[0, '', 0], [1, 'X', 1], [1, 'X', 1], [1, 'Y', 2], [1, 'Y', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
496  call assert_equal('1XY6   ', ScreenLines(2, 7)[0])
497
498  set conceallevel=2
499  call assert_match('1X6    ', ScreenLines(2, 7)[0])
500  call assert_equal([[0, '', 0], [1, 'X', 1], [1, 'X', 1], [1, '', 2], [1, '', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
501
502  set conceallevel=3
503  call assert_match('16     ', ScreenLines(2, 7)[0])
504  call assert_equal([[0, '', 0], [1, '', 1], [1, '', 1], [1, '', 2], [1, '', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
505
506  syn clear
507  set conceallevel&
508  bw!
509endfunc
510
511func Test_synstack_synIDtrans()
512  new
513  setfiletype c
514  syntax on
515  call setline(1, ' /* A comment with a TODO */')
516
517  call assert_equal([], synstack(1, 1))
518
519  norm f/
520  call assert_equal(['cComment', 'cCommentStart'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
521  call assert_equal(['Comment', 'Comment'],	   map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
522
523  norm fA
524  call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
525  call assert_equal(['Comment'],  map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
526
527  norm fT
528  call assert_equal(['cComment', 'cTodo'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
529  call assert_equal(['Comment', 'Todo'],   map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
530
531  syn clear
532  bw!
533endfunc
534
535" Check highlighting for a small piece of C code with a screen dump.
536func Test_syntax_c()
537  if !CanRunVimInTerminal()
538    throw 'Skipped: cannot make screendumps'
539  endif
540  call writefile([
541	\ '/* comment line at the top */',
542	\ '  int',
543	\ 'main(int argc, char **argv)// another comment',
544	\ '{',
545	\ '#if 0',
546	\ '   int   not_used;',
547	\ '#else',
548	\ '   int   used;',
549	\ '#endif',
550	\ '   printf("Just an example piece of C code\n");',
551	\ '   return 0x0ff;',
552	\ '}',
553	\ '   static void',
554	\ 'myFunction(const double count, struct nothing, long there) {',
555	\ '  // 123: nothing to read here',
556	\ '  for (int i = 0; i < count; ++i) {',
557	\ '    break;',
558	\ '  }',
559	\ '}',
560	\ ], 'Xtest.c')
561
562  " This makes the default for 'background' use "dark", check that the
563  " response to t_RB corrects it to "light".
564  let $COLORFGBG = '15;0'
565
566  let buf = RunVimInTerminal('Xtest.c', {})
567  call VerifyScreenDump(buf, 'Test_syntax_c_01', {})
568  call StopVimInTerminal(buf)
569
570  let $COLORFGBG = ''
571  call delete('Xtest.c')
572endfun
573
574" Using \z() in a region with NFA failing should not crash.
575func Test_syn_wrong_z_one()
576  new
577  call setline(1, ['just some text', 'with foo and bar to match with'])
578  syn region FooBar start="foo\z(.*\)bar" end="\z1"
579  call test_override("nfa_fail", 1)
580  redraw!
581  redraw!
582  call test_override("ALL", 0)
583  bwipe!
584endfunc
585