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