blob: 589470b684d6bc285f85179ab1837836961d5772 [file] [log] [blame]
Bram Moolenaarb8060fe2016-01-19 22:29:28 +01001" Test for syntax and syntax iskeyword option
2
Bram Moolenaarb46fecd2019-06-15 17:58:09 +02003source check.vim
4CheckFeature syntax
Bram Moolenaarb8060fe2016-01-19 22:29:28 +01005
Bram Moolenaar4d785892017-06-22 22:00:50 +02006source view_util.vim
Bram Moolenaar6bb2cdf2018-02-24 19:53:53 +01007source screendump.vim
Bram Moolenaar4d785892017-06-22 22:00:50 +02008
Bram Moolenaarb8060fe2016-01-19 22:29:28 +01009func 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
Bram Moolenaarb46f57e2020-11-29 14:11:41 +010030func 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
Bram Moolenaarb8060fe2016-01-19 22:29:28 +010050func Test_syn_iskeyword()
51 new
52 call setline(1, [
53 \ 'CREATE TABLE FOOBAR(',
54 \ ' DLTD_BY VARCHAR2(100)',
55 \ ');',
Bram Moolenaar037c54f2019-04-20 23:47:46 +020056 \ ''])
Bram Moolenaarb8060fe2016-01-19 22:29:28 +010057
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
Bram Moolenaar73b484c2016-12-11 15:11:17 +010079 let b2 = @0
Bram Moolenaarb8060fe2016-01-19 22:29:28 +010080 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
Bram Moolenaarc3691332016-04-20 12:49:49 +020090
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
Bram Moolenaar73b484c2016-12-11 15:11:17 +0100105
106func Test_syntime()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200107 CheckFeature profile
Bram Moolenaar73b484c2016-12-11 15:11:17 +0100108
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
Dominique Pelle6d37e8e2021-05-06 17:36:55 +0200114 let a = execute('syntime clear')
115 call assert_equal("\nNo Syntax items defined for this buffer", a)
116
Bram Moolenaar73b484c2016-12-11 15:11:17 +0100117 view ../memfile_test.c
118 setfiletype cpp
119 redraw
120 let a = execute('syntime report')
121 call assert_match('^ TOTAL *COUNT *MATCH *SLOWEST *AVERAGE *NAME *PATTERN', a)
122 call assert_match(' \d*\.\d* \+[^0]\d* .* cppRawString ', a)
123 call assert_match(' \d*\.\d* \+[^0]\d* .* cppNumber ', a)
124
125 syntime off
126 syntime clear
127 let a = execute('syntime report')
128 call assert_match('^ TOTAL *COUNT *MATCH *SLOWEST *AVERAGE *NAME *PATTERN', a)
129 call assert_notmatch('.* cppRawString *', a)
130 call assert_notmatch('.* cppNumber*', a)
131 call assert_notmatch('[1-9]', a)
132
Bram Moolenaare2e40752020-09-04 21:18:46 +0200133 call assert_fails('syntime abc', 'E475:')
Bram Moolenaar73b484c2016-12-11 15:11:17 +0100134
135 syntax clear
136 let a = execute('syntime report')
137 call assert_equal("\nNo Syntax items defined for this buffer", a)
138
139 bd
140endfunc
141
Bram Moolenaarb513d302018-12-02 14:55:08 +0100142func Test_syntime_completion()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200143 CheckFeature profile
Bram Moolenaarb513d302018-12-02 14:55:08 +0100144
145 call feedkeys(":syntime \<C-A>\<C-B>\"\<CR>", 'tx')
146 call assert_equal('"syntime clear off on report', @:)
147endfunc
148
Bram Moolenaar73b484c2016-12-11 15:11:17 +0100149func Test_syntax_list()
150 syntax on
151 let a = execute('syntax list')
152 call assert_equal("\nNo Syntax items defined for this buffer", a)
153
154 view ../memfile_test.c
155 setfiletype c
156
157 let a = execute('syntax list')
158 call assert_match('cInclude*', a)
159 call assert_match('cDefine', a)
160
161 let a = execute('syntax list cDefine')
162 call assert_notmatch('cInclude*', a)
163 call assert_match('cDefine', a)
164 call assert_match(' links to Macro$', a)
165
166 call assert_fails('syntax list ABCD', 'E28:')
167 call assert_fails('syntax list @ABCD', 'E392:')
168
169 syntax clear
170 let a = execute('syntax list')
171 call assert_equal("\nNo Syntax items defined for this buffer", a)
172
Bram Moolenaar08f41572020-04-20 16:50:00 +0200173 syntax keyword Type int containedin=g1 skipwhite skipempty skipnl nextgroup=Abc
174 let exp = "Type xxx containedin=g1 nextgroup=Abc skipnl skipwhite skipempty int"
175 call assert_equal(exp, split(execute("syntax list"), "\n")[1])
176
Bram Moolenaar73b484c2016-12-11 15:11:17 +0100177 bd
178endfunc
179
180func Test_syntax_completion()
181 call feedkeys(":syn \<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaare35a52a2020-05-31 19:48:53 +0200182 call assert_equal('"syn case clear cluster conceal enable foldlevel include iskeyword keyword list manual match off on region reset spell sync', @:)
Bram Moolenaar73b484c2016-12-11 15:11:17 +0100183
184 call feedkeys(":syn case \<C-A>\<C-B>\"\<CR>", 'tx')
185 call assert_equal('"syn case ignore match', @:)
186
Bram Moolenaar2d028392017-01-08 18:28:22 +0100187 call feedkeys(":syn spell \<C-A>\<C-B>\"\<CR>", 'tx')
188 call assert_equal('"syn spell default notoplevel toplevel', @:)
189
190 call feedkeys(":syn sync \<C-A>\<C-B>\"\<CR>", 'tx')
191 call assert_equal('"syn sync ccomment clear fromstart linebreaks= linecont lines= match maxlines= minlines= region', @:)
192
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100193 " Check that clearing "Aap" avoids it showing up before Boolean.
194 hi Aap ctermfg=blue
195 call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx')
196 call assert_match('^"syn list Aap Boolean Character ', @:)
197 hi clear Aap
198
Bram Moolenaar73b484c2016-12-11 15:11:17 +0100199 call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx')
200 call assert_match('^"syn list Boolean Character ', @:)
201
202 call feedkeys(":syn match \<C-A>\<C-B>\"\<CR>", 'tx')
203 call assert_match('^"syn match Boolean Character ', @:)
204endfunc
Bram Moolenaarde318c52017-01-17 16:27:10 +0100205
Bram Moolenaar297610b2019-12-27 17:20:55 +0100206func Test_echohl_completion()
207 call feedkeys(":echohl no\<C-A>\<C-B>\"\<CR>", 'tx')
208 call assert_equal('"echohl NonText Normal none', @:)
209endfunc
210
Bram Moolenaarde318c52017-01-17 16:27:10 +0100211func Test_syntax_arg_skipped()
212 syn clear
213 syntax case ignore
214 if 0
215 syntax case match
216 endif
217 call assert_match('case ignore', execute('syntax case'))
218
219 syn keyword Foo foo
220 call assert_match('Foo', execute('syntax'))
221 syn clear
222 call assert_match('case match', execute('syntax case'))
223 call assert_notmatch('Foo', execute('syntax'))
224
225 if has('conceal')
226 syn clear
227 syntax conceal on
228 if 0
229 syntax conceal off
230 endif
231 call assert_match('conceal on', execute('syntax conceal'))
232 syn clear
233 call assert_match('conceal off', execute('syntax conceal'))
Bram Moolenaar58f60ca2017-01-17 17:19:00 +0100234
235 syntax conceal on
236 syntax conceal off
237 call assert_match('conceal off', execute('syntax conceal'))
Bram Moolenaarde318c52017-01-17 16:27:10 +0100238 endif
239
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100240 syntax region Bar start=/</ end=/>/
Bram Moolenaarde318c52017-01-17 16:27:10 +0100241 if 0
242 syntax region NotTest start=/</ end=/>/ contains=@Spell
243 endif
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100244 call assert_match('Bar', execute('syntax'))
Bram Moolenaarde318c52017-01-17 16:27:10 +0100245 call assert_notmatch('NotTest', execute('syntax'))
246 call assert_notmatch('Spell', execute('syntax'))
247
248 hi Foo ctermfg=blue
249 let a = execute('hi Foo')
250 if 0
251 syntax rest
252 endif
253 call assert_equal(a, execute('hi Foo'))
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100254 hi clear Bar
255 hi clear Foo
Bram Moolenaarde318c52017-01-17 16:27:10 +0100256
257 set ft=tags
258 syn off
259 if 0
260 syntax enable
261 endif
262 call assert_match('No Syntax items defined', execute('syntax'))
263 syntax enable
264 call assert_match('tagComment', execute('syntax'))
265 set ft=
266
267 syn clear
268 if 0
269 syntax include @Spell nothing
270 endif
271 call assert_notmatch('Spell', execute('syntax'))
272
273 syn clear
274 syn iskeyword 48-57,$,_
275 call assert_match('48-57,$,_', execute('syntax iskeyword'))
276 if 0
277 syn clear
278 syn iskeyword clear
279 endif
280 call assert_match('48-57,$,_', execute('syntax iskeyword'))
281 syn iskeyword clear
282 call assert_match('not set', execute('syntax iskeyword'))
283 syn iskeyword 48-57,$,_
284 syn clear
285 call assert_match('not set', execute('syntax iskeyword'))
286
287 syn clear
288 syn keyword Foo foo
289 if 0
290 syn keyword NotAdded bar
291 endif
292 call assert_match('Foo', execute('syntax'))
293 call assert_notmatch('NotAdded', execute('highlight'))
294
295 syn clear
296 syn keyword Foo foo
297 call assert_match('Foo', execute('syntax'))
298 call assert_match('Foo', execute('syntax list'))
299 call assert_notmatch('Foo', execute('if 0 | syntax | endif'))
300 call assert_notmatch('Foo', execute('if 0 | syntax list | endif'))
301
302 syn clear
303 syn match Fopi /asdf/
304 if 0
305 syn match Fopx /asdf/
306 endif
307 call assert_match('Fopi', execute('syntax'))
308 call assert_notmatch('Fopx', execute('syntax'))
309
310 syn clear
311 syn spell toplevel
312 call assert_match('spell toplevel', execute('syntax spell'))
313 if 0
314 syn spell notoplevel
315 endif
316 call assert_match('spell toplevel', execute('syntax spell'))
317 syn spell notoplevel
318 call assert_match('spell notoplevel', execute('syntax spell'))
319 syn spell default
320 call assert_match('spell default', execute('syntax spell'))
321
322 syn clear
323 if 0
324 syntax cluster Spell
325 endif
326 call assert_notmatch('Spell', execute('syntax'))
327
328 syn clear
329 syn keyword Foo foo
330 syn sync ccomment
331 syn sync maxlines=5
332 if 0
333 syn sync maxlines=11
334 endif
335 call assert_match('on C-style comments', execute('syntax sync'))
336 call assert_match('maximal 5 lines', execute('syntax sync'))
Bram Moolenaar58f60ca2017-01-17 17:19:00 +0100337 syn sync clear
Bram Moolenaarde318c52017-01-17 16:27:10 +0100338 if 0
339 syn sync ccomment
340 endif
341 call assert_notmatch('on C-style comments', execute('syntax sync'))
Bram Moolenaar99502802020-11-18 16:53:23 +0100342 syn sync fromstart
343 call assert_match('syncing starts at the first line', execute('syntax sync'))
Bram Moolenaarde318c52017-01-17 16:27:10 +0100344
345 syn clear
346endfunc
347
Bram Moolenaarfbf21222020-04-19 18:31:25 +0200348" Check for an error. Used when multiple errors are thrown and we are checking
349" for an earliest error.
350func AssertFails(cmd, errcode)
351 let save_exception = ''
352 try
353 exe a:cmd
354 catch
355 let save_exception = v:exception
356 endtry
357 call assert_match(a:errcode, save_exception)
358endfunc
359
Bram Moolenaarea588152017-04-10 22:45:30 +0200360func Test_syntax_invalid_arg()
Bram Moolenaar58f60ca2017-01-17 17:19:00 +0100361 call assert_fails('syntax case asdf', 'E390:')
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100362 if has('conceal')
363 call assert_fails('syntax conceal asdf', 'E390:')
364 endif
Bram Moolenaar58f60ca2017-01-17 17:19:00 +0100365 call assert_fails('syntax spell asdf', 'E390:')
Bram Moolenaarea588152017-04-10 22:45:30 +0200366 call assert_fails('syntax clear @ABCD', 'E391:')
Bram Moolenaarfbf21222020-04-19 18:31:25 +0200367 call assert_fails('syntax include random_file', 'E484:')
368 call assert_fails('syntax include <afile>', 'E495:')
Bram Moolenaarea588152017-04-10 22:45:30 +0200369 call assert_fails('syntax sync x', 'E404:')
370 call assert_fails('syntax keyword Abc a[', 'E789:')
371 call assert_fails('syntax keyword Abc a[bc]d', 'E890:')
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200372 call assert_fails('syntax cluster Abc add=A add=', 'E406:')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200373
374 " Test for too many \z\( and unmatched \z\(
375 " Not able to use assert_fails() here because both E50:/E879: and E475:
376 " messages are emitted.
377 set regexpengine=1
Bram Moolenaarfbf21222020-04-19 18:31:25 +0200378 call AssertFails("syntax region MyRegion start='\\z\\(' end='\\*/'", 'E52:')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200379
Bram Moolenaarfbf21222020-04-19 18:31:25 +0200380 let cmd = "syntax region MyRegion start='"
381 let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'"
382 call AssertFails(cmd, 'E50:')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200383
384 set regexpengine=2
Bram Moolenaarfbf21222020-04-19 18:31:25 +0200385 call AssertFails("syntax region MyRegion start='\\z\\(' end='\\*/'", 'E54:')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200386
Bram Moolenaarfbf21222020-04-19 18:31:25 +0200387 let cmd = "syntax region MyRegion start='"
388 let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'"
389 call AssertFails(cmd, 'E879:')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200390 set regexpengine&
Bram Moolenaarfbf21222020-04-19 18:31:25 +0200391
392 call AssertFails('syntax keyword cMyItem grouphere G1', 'E393:')
393 call AssertFails('syntax sync match Abc grouphere MyItem "abc"', 'E394:')
394 call AssertFails('syn keyword Type contains int', 'E395:')
395 call assert_fails('syntax include @Xxx', 'E397:')
396 call AssertFails('syntax region X start', 'E398:')
397 call assert_fails('syntax region X start="{"', 'E399:')
398 call AssertFails('syntax cluster contains=Abc', 'E400:')
399 call AssertFails("syntax match Character /'.'", 'E401:')
400 call AssertFails("syntax match Character /'.'/a", 'E402:')
Bram Moolenaar531be472020-09-23 22:38:05 +0200401 call assert_fails('syntax sync linecont /\%(/', 'E53:')
Bram Moolenaarfbf21222020-04-19 18:31:25 +0200402 call assert_fails('syntax sync linecont /pat', 'E404:')
403 call assert_fails('syntax sync linecont', 'E404:')
404 call assert_fails('syntax sync linecont /pat1/ linecont /pat2/', 'E403:')
405 call assert_fails('syntax sync minlines=a', 'E404:')
406 call AssertFails('syntax match ABC /x/ contains=', 'E406:')
407 call AssertFails("syntax match Character contains /'.'/", 'E405:')
408 call AssertFails('syntax match ccFoo "Foo" nextgroup=ALLBUT,F', 'E407:')
409 call AssertFails('syntax region Block start="{" contains=F,ALLBUT', 'E408:')
410 call AssertFails("syntax match Characters contains=a.*x /'.'/", 'E409:')
Bram Moolenaar531be472020-09-23 22:38:05 +0200411 call assert_fails('syntax match Search /abc/ contains=ALLBUT,/\%(/', 'E53:')
Bram Moolenaar58f60ca2017-01-17 17:19:00 +0100412endfunc
413
414func Test_syn_sync()
415 syntax region HereGroup start=/this/ end=/that/
416 syntax sync match SyncHere grouphere HereGroup "pattern"
417 call assert_match('SyncHere', execute('syntax sync'))
418 syn sync clear
419 call assert_notmatch('SyncHere', execute('syntax sync'))
420 syn clear
421endfunc
422
423func Test_syn_clear()
424 syntax keyword Foo foo
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100425 syntax keyword Bar tar
Bram Moolenaar58f60ca2017-01-17 17:19:00 +0100426 call assert_match('Foo', execute('syntax'))
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100427 call assert_match('Bar', execute('syntax'))
Bram Moolenaarc96272e2017-03-26 13:50:09 +0200428 call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
Bram Moolenaar58f60ca2017-01-17 17:19:00 +0100429 syn clear Foo
430 call assert_notmatch('Foo', execute('syntax'))
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100431 call assert_match('Bar', execute('syntax'))
Bram Moolenaarc96272e2017-03-26 13:50:09 +0200432 call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100433 syn clear Foo Bar
Bram Moolenaar58f60ca2017-01-17 17:19:00 +0100434 call assert_notmatch('Foo', execute('syntax'))
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100435 call assert_notmatch('Bar', execute('syntax'))
436 hi clear Foo
Bram Moolenaarc96272e2017-03-26 13:50:09 +0200437 call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100438 hi clear Bar
Bram Moolenaarfbf21222020-04-19 18:31:25 +0200439 call assert_fails('syntax clear invalid_syngroup', 'E28:')
Bram Moolenaar58f60ca2017-01-17 17:19:00 +0100440endfunc
Bram Moolenaar4007ed42017-01-17 18:14:54 +0100441
442func Test_invalid_name()
443 syn clear
444 syn keyword Nop yes
445 call assert_fails("syntax keyword Wr\x17ong bar", 'E669:')
446 syntax keyword @Wrong bar
447 call assert_match('W18:', execute('1messages'))
448 syn clear
449 hi clear Nop
450 hi clear @Wrong
451endfunc
Bram Moolenaarf8ec9982017-04-09 15:41:31 +0200452
453func Test_ownsyntax()
454 new Xfoo
455 call setline(1, '#define FOO')
456 syntax on
457 set filetype=c
Bram Moolenaard1f76af2020-09-13 22:37:34 +0200458
Bram Moolenaarf8ec9982017-04-09 15:41:31 +0200459 ownsyntax perl
Bram Moolenaard1f76af2020-09-13 22:37:34 +0200460 " this should not crash
461 set
462
Bram Moolenaarf8ec9982017-04-09 15:41:31 +0200463 call assert_equal('perlComment', synIDattr(synID(line('.'), col('.'), 1), 'name'))
464 call assert_equal('c', b:current_syntax)
465 call assert_equal('perl', w:current_syntax)
466
467 " A new split window should have the original syntax.
468 split
469 call assert_equal('cDefine', synIDattr(synID(line('.'), col('.'), 1), 'name'))
470 call assert_equal('c', b:current_syntax)
471 call assert_equal(0, exists('w:current_syntax'))
472
473 wincmd x
474 call assert_equal('perlComment', synIDattr(synID(line("."), col("."), 1), "name"))
475
476 syntax off
477 set filetype&
478 %bw!
479endfunc
480
481func Test_ownsyntax_completion()
482 call feedkeys(":ownsyntax java\<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaarea7a08a2019-08-26 22:38:22 +0200483 call assert_equal('"ownsyntax java javacc javascript javascriptreact', @:)
Bram Moolenaarf8ec9982017-04-09 15:41:31 +0200484endfunc
Bram Moolenaarea588152017-04-10 22:45:30 +0200485
486func Test_highlight_invalid_arg()
487 if has('gui_running')
488 call assert_fails('hi XXX guifg=xxx', 'E254:')
489 endif
490 call assert_fails('hi DoesNotExist', 'E411:')
491 call assert_fails('hi link', 'E412:')
492 call assert_fails('hi link a', 'E412:')
493 call assert_fails('hi link a b c', 'E413:')
494 call assert_fails('hi XXX =', 'E415:')
495 call assert_fails('hi XXX cterm', 'E416:')
496 call assert_fails('hi XXX cterm=', 'E417:')
497 call assert_fails('hi XXX cterm=DoesNotExist', 'E418:')
498 call assert_fails('hi XXX ctermfg=DoesNotExist', 'E421:')
499 call assert_fails('hi XXX xxx=White', 'E423:')
500endfunc
501
Bram Moolenaar1615b362017-06-04 21:06:09 +0200502func Test_bg_detection()
Bram Moolenaar8c5a2782019-08-07 23:07:07 +0200503 CheckNotGui
504
Dominique Pelle923dce22021-11-21 11:36:04 +0000505 " auto-detection of &bg, make sure it isn't set anywhere before this test
Bram Moolenaar1615b362017-06-04 21:06:09 +0200506 hi Normal ctermbg=0
507 call assert_equal('dark', &bg)
508 hi Normal ctermbg=4
509 call assert_equal('dark', &bg)
510 hi Normal ctermbg=12
511 call assert_equal('light', &bg)
512 hi Normal ctermbg=15
513 call assert_equal('light', &bg)
514
Bram Moolenaar0b2eef22017-06-27 15:43:49 +0200515 " manually-set &bg takes precedence over auto-detection
Bram Moolenaar1615b362017-06-04 21:06:09 +0200516 set bg=light
517 hi Normal ctermbg=4
518 call assert_equal('light', &bg)
519 set bg=dark
520 hi Normal ctermbg=12
521 call assert_equal('dark', &bg)
Bram Moolenaar6acadda2018-02-24 16:51:32 +0100522
523 hi Normal ctermbg=NONE
Bram Moolenaar1615b362017-06-04 21:06:09 +0200524endfunc
Bram Moolenaar06f1ed22017-06-18 22:41:03 +0200525
526func Test_syntax_hangs()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200527 CheckFunction reltimefloat
528 CheckFeature syntax
Bram Moolenaar06f1ed22017-06-18 22:41:03 +0200529
Paul Ollis65745772022-06-05 16:55:54 +0100530 " So, it turns out the Windows 7 implements TimerQueue timers differently
531 " and they can expire *before* the requested time has elapsed. So allow for
532 " the timeout occurring after 80 ms (5 * 16 (the typical clock tick)).
533 if has("win32")
534 let min_timeout = 0.08
535 else
536 let min_timeout = 0.1
537 endif
538
Bram Moolenaar06f1ed22017-06-18 22:41:03 +0200539 " This pattern takes a long time to match, it should timeout.
540 new
541 call setline(1, ['aaa', repeat('abc ', 1000), 'ccc'])
542 let start = reltime()
543 set nolazyredraw redrawtime=101
544 syn match Error /\%#=1a*.*X\@<=b*/
545 redraw
546 let elapsed = reltimefloat(reltime(start))
Bram Moolenaar620aa8e2022-06-18 16:05:32 +0100547 call assert_inrange(min_timeout, 1.0, elapsed)
Bram Moolenaar06f1ed22017-06-18 22:41:03 +0200548
549 " second time syntax HL is disabled
550 let start = reltime()
551 redraw
552 let elapsed = reltimefloat(reltime(start))
Bram Moolenaar620aa8e2022-06-18 16:05:32 +0100553 call assert_inrange(0, 0.1, elapsed)
Bram Moolenaar06f1ed22017-06-18 22:41:03 +0200554
555 " after CTRL-L the timeout flag is reset
556 let start = reltime()
557 exe "normal \<C-L>"
558 redraw
559 let elapsed = reltimefloat(reltime(start))
Bram Moolenaar620aa8e2022-06-18 16:05:32 +0100560 call assert_inrange(min_timeout, 1.0, elapsed)
Bram Moolenaar06f1ed22017-06-18 22:41:03 +0200561
562 set redrawtime&
563 bwipe!
564endfunc
Bram Moolenaar4d785892017-06-22 22:00:50 +0200565
Bram Moolenaar4d785892017-06-22 22:00:50 +0200566func Test_conceal()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200567 CheckFeature conceal
Bram Moolenaar4d785892017-06-22 22:00:50 +0200568
569 new
570 call setline(1, ['', '123456'])
571 syn match test23 "23" conceal cchar=X
572 syn match test45 "45" conceal
573
574 set conceallevel=0
575 call assert_equal('123456 ', ScreenLines(2, 7)[0])
Bram Moolenaarcc0750d2017-06-24 22:29:24 +0200576 call assert_equal([[0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
Bram Moolenaar4d785892017-06-22 22:00:50 +0200577
578 set conceallevel=1
579 call assert_equal('1X 6 ', ScreenLines(2, 7)[0])
Bram Moolenaarcc0750d2017-06-24 22:29:24 +0200580 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)'))
Bram Moolenaar4d785892017-06-22 22:00:50 +0200581
582 set conceallevel=1
583 set listchars=conceal:Y
Bram Moolenaarcc0750d2017-06-24 22:29:24 +0200584 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)'))
Bram Moolenaar4d785892017-06-22 22:00:50 +0200585 call assert_equal('1XY6 ', ScreenLines(2, 7)[0])
586
587 set conceallevel=2
588 call assert_match('1X6 ', ScreenLines(2, 7)[0])
Bram Moolenaarcc0750d2017-06-24 22:29:24 +0200589 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)'))
Bram Moolenaar4d785892017-06-22 22:00:50 +0200590
591 set conceallevel=3
592 call assert_match('16 ', ScreenLines(2, 7)[0])
Bram Moolenaarcc0750d2017-06-24 22:29:24 +0200593 call assert_equal([[0, '', 0], [1, '', 1], [1, '', 1], [1, '', 2], [1, '', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
Bram Moolenaar4d785892017-06-22 22:00:50 +0200594
Bram Moolenaarfbf21222020-04-19 18:31:25 +0200595 call AssertFails("syntax match Entity '&amp;' conceal cchar=\<Tab>", 'E844:')
596
Bram Moolenaar4d785892017-06-22 22:00:50 +0200597 syn clear
598 set conceallevel&
599 bw!
600endfunc
Bram Moolenaar0b2eef22017-06-27 15:43:49 +0200601
Bram Moolenaarda650582018-02-20 15:51:40 +0100602func Test_synstack_synIDtrans()
Bram Moolenaar0b2eef22017-06-27 15:43:49 +0200603 new
604 setfiletype c
605 syntax on
606 call setline(1, ' /* A comment with a TODO */')
607
608 call assert_equal([], synstack(1, 1))
609
610 norm f/
Bram Moolenaara74e4942019-08-04 17:35:53 +0200611 eval synstack(line("."), col("."))->map('synIDattr(v:val, "name")')->assert_equal(['cComment', 'cCommentStart'])
612 eval synstack(line("."), col("."))->map('synIDattr(synIDtrans(v:val), "name")')->assert_equal(['Comment', 'Comment'])
Bram Moolenaar0b2eef22017-06-27 15:43:49 +0200613
614 norm fA
615 call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
616 call assert_equal(['Comment'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
617
618 norm fT
619 call assert_equal(['cComment', 'cTodo'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
620 call assert_equal(['Comment', 'Todo'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
621
Bram Moolenaar0e05de42020-03-25 22:23:46 +0100622 call assert_fails("let n=synIDtrans([])", 'E745:')
623
Bram Moolenaar0b2eef22017-06-27 15:43:49 +0200624 syn clear
625 bw!
626endfunc
Bram Moolenaarda650582018-02-20 15:51:40 +0100627
628" Check highlighting for a small piece of C code with a screen dump.
629func Test_syntax_c()
Bram Moolenaar494e9062020-05-31 21:28:02 +0200630 CheckRunVimInTerminal
Bram Moolenaarda650582018-02-20 15:51:40 +0100631 call writefile([
632 \ '/* comment line at the top */',
Bram Moolenaar83e9a1c2019-10-20 14:51:23 +0200633 \ 'int main(int argc, char **argv) { // another comment',
Bram Moolenaarda650582018-02-20 15:51:40 +0100634 \ '#if 0',
635 \ ' int not_used;',
636 \ '#else',
637 \ ' int used;',
638 \ '#endif',
639 \ ' printf("Just an example piece of C code\n");',
640 \ ' return 0x0ff;',
641 \ '}',
Bram Moolenaar82260af2019-10-20 13:16:22 +0200642 \ "\t\t ",
Bram Moolenaarda650582018-02-20 15:51:40 +0100643 \ ' static void',
644 \ 'myFunction(const double count, struct nothing, long there) {',
Bram Moolenaar84590062019-10-18 23:12:20 +0200645 \ "\t// 123: nothing to endif here",
Bram Moolenaar9115c612019-10-16 16:57:06 +0200646 \ "\tfor (int i = 0; i < count; ++i) {",
647 \ "\t break;",
648 \ "\t}",
Bram Moolenaarbbfd1562019-10-19 20:38:15 +0200649 \ "\tNote: asdf",
Bram Moolenaarda650582018-02-20 15:51:40 +0100650 \ '}',
651 \ ], 'Xtest.c')
Paul Ollis65745772022-06-05 16:55:54 +0100652
Bram Moolenaarb7ea7cb2018-02-24 14:38:51 +0100653 " This makes the default for 'background' use "dark", check that the
654 " response to t_RB corrects it to "light".
655 let $COLORFGBG = '15;0'
656
Bram Moolenaar83e9a1c2019-10-20 14:51:23 +0200657 let buf = RunVimInTerminal('Xtest.c', {})
Bram Moolenaarbbfd1562019-10-19 20:38:15 +0200658 call term_sendkeys(buf, ":syn keyword Search Note\r")
Bram Moolenaar82260af2019-10-20 13:16:22 +0200659 call term_sendkeys(buf, ":syn match Error /^\\s\\+$/\r")
Bram Moolenaar84590062019-10-18 23:12:20 +0200660 call term_sendkeys(buf, ":set hlsearch\r")
661 call term_sendkeys(buf, "/endif\r")
662 call term_sendkeys(buf, "vjfC")
Bram Moolenaar6bb2cdf2018-02-24 19:53:53 +0100663 call VerifyScreenDump(buf, 'Test_syntax_c_01', {})
Bram Moolenaar84590062019-10-18 23:12:20 +0200664
665 call term_sendkeys(buf, "\<Esc>")
Bram Moolenaarda650582018-02-20 15:51:40 +0100666 call StopVimInTerminal(buf)
667
Bram Moolenaarb7ea7cb2018-02-24 14:38:51 +0100668 let $COLORFGBG = ''
Bram Moolenaarda650582018-02-20 15:51:40 +0100669 call delete('Xtest.c')
670endfun
Bram Moolenaarbcf94422018-06-23 14:21:42 +0200671
Dominique Pelle354b23a2021-12-17 17:32:29 +0000672" Test \z(...) along with \z1
673func Test_syn_zsub()
674 new
675 syntax on
676 call setline(1, 'xxx start foo xxx not end foo xxx end foo xxx')
677 let l:expected = ' ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ '
678
679 for l:re in [0, 1, 2]
680 " Example taken from :help :syn-ext-match
681 syntax region Z start="start \z(\I\i*\)" skip="not end \z1" end="end \z1"
682 eval AssertHighlightGroups(1, 1, l:expected, 1, 'regexp=' .. l:re)
683 syntax clear Z
684 endfor
685
686 set re&
687 bw!
688endfunc
689
Bram Moolenaarbcf94422018-06-23 14:21:42 +0200690" Using \z() in a region with NFA failing should not crash.
691func Test_syn_wrong_z_one()
692 new
693 call setline(1, ['just some text', 'with foo and bar to match with'])
694 syn region FooBar start="foo\z(.*\)bar" end="\z1"
695 call test_override("nfa_fail", 1)
696 redraw!
697 redraw!
698 call test_override("ALL", 0)
699 bwipe!
700endfunc
Bram Moolenaarc7f1e402019-08-03 13:29:46 +0200701
702func Test_syntax_after_bufdo()
703 call writefile(['/* aaa comment */'], 'Xaaa.c')
704 call writefile(['/* bbb comment */'], 'Xbbb.c')
705 call writefile(['/* ccc comment */'], 'Xccc.c')
706 call writefile(['/* ddd comment */'], 'Xddd.c')
707
708 let bnr = bufnr('%')
709 new Xaaa.c
710 badd Xbbb.c
711 badd Xccc.c
712 badd Xddd.c
713 exe "bwipe " . bnr
714 let l = []
715 bufdo call add(l, bufnr('%'))
716 call assert_equal(4, len(l))
717
718 syntax on
719
720 " This used to only enable syntax HL in the last buffer.
721 bufdo tab split
722 tabrewind
723 for tab in range(1, 4)
724 norm fm
725 call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
726 tabnext
727 endfor
728
729 bwipe! Xaaa.c
730 bwipe! Xbbb.c
731 bwipe! Xccc.c
732 bwipe! Xddd.c
733 syntax off
734 call delete('Xaaa.c')
735 call delete('Xbbb.c')
736 call delete('Xccc.c')
737 call delete('Xddd.c')
738endfunc
Bram Moolenaar0e05de42020-03-25 22:23:46 +0100739
Bram Moolenaare35a52a2020-05-31 19:48:53 +0200740func Test_syntax_foldlevel()
741 new
742 call setline(1, [
743 \ 'void f(int a)',
744 \ '{',
745 \ ' if (a == 1) {',
746 \ ' a = 0;',
747 \ ' } else if (a == 2) {',
748 \ ' a = 1;',
749 \ ' } else {',
750 \ ' a = 2;',
751 \ ' }',
752 \ ' if (a > 0) {',
753 \ ' if (a == 1) {',
754 \ ' a = 0;',
755 \ ' } /* missing newline */ } /* end of outer if */ else {',
756 \ ' a = 1;',
757 \ ' }',
758 \ ' if (a == 1)',
759 \ ' {',
760 \ ' a = 0;',
761 \ ' }',
762 \ ' else if (a == 2)',
763 \ ' {',
764 \ ' a = 1;',
765 \ ' }',
766 \ ' else',
767 \ ' {',
768 \ ' a = 2;',
769 \ ' }',
770 \ '}',
771 \ ])
772 setfiletype c
773 syntax on
774 set foldmethod=syntax
775
Bram Moolenaare2e40752020-09-04 21:18:46 +0200776 call assert_fails('syn foldlevel start start', 'E390:')
777 call assert_fails('syn foldlevel not_an_option', 'E390:')
Bram Moolenaare35a52a2020-05-31 19:48:53 +0200778
779 set foldlevel=1
780
781 syn foldlevel start
782 redir @c
783 syn foldlevel
784 redir END
785 call assert_equal("\nsyntax foldlevel start", @c)
786 syn sync fromstart
Bram Moolenaar99502802020-11-18 16:53:23 +0100787 call assert_match('from the first line$', execute('syn sync'))
Bram Moolenaare35a52a2020-05-31 19:48:53 +0200788 let a = map(range(3,9), 'foldclosed(v:val)')
789 call assert_equal([3,3,3,3,3,3,3], a) " attached cascade folds together
790 let a = map(range(10,15), 'foldclosed(v:val)')
791 call assert_equal([10,10,10,10,10,10], a) " over-attached 'else' hidden
792 let a = map(range(16,27), 'foldclosed(v:val)')
793 let unattached_results = [-1,17,17,17,-1,21,21,21,-1,25,25,25]
794 call assert_equal(unattached_results, a) " unattached cascade folds separately
795
796 syn foldlevel minimum
797 redir @c
798 syn foldlevel
799 redir END
800 call assert_equal("\nsyntax foldlevel minimum", @c)
801 syn sync fromstart
802 let a = map(range(3,9), 'foldclosed(v:val)')
803 call assert_equal([3,3,5,5,7,7,7], a) " attached cascade folds separately
804 let a = map(range(10,15), 'foldclosed(v:val)')
805 call assert_equal([10,10,10,13,13,13], a) " over-attached 'else' visible
806 let a = map(range(16,27), 'foldclosed(v:val)')
807 call assert_equal(unattached_results, a) " unattached cascade folds separately
808
809 set foldlevel=2
810
811 syn foldlevel start
812 syn sync fromstart
813 let a = map(range(11,14), 'foldclosed(v:val)')
814 call assert_equal([11,11,11,-1], a) " over-attached 'else' hidden
815
816 syn foldlevel minimum
817 syn sync fromstart
818 let a = map(range(11,14), 'foldclosed(v:val)')
819 call assert_equal([11,11,-1,-1], a) " over-attached 'else' visible
820
821 quit!
822endfunc
823
Bram Moolenaaradc17a52020-06-06 18:37:51 +0200824func Test_search_syntax_skip()
825 new
826 let lines =<< trim END
827
828 /* This is VIM */
829 Another Text for VIM
830 let a = "VIM"
831 END
832 call setline(1, lines)
833 syntax on
834 syntax match Comment "^/\*.*\*/"
835 syntax match String '".*"'
836
837 " Skip argument using string evaluation.
838 1
839 call search('VIM', 'w', '', 0, 'synIDattr(synID(line("."), col("."), 1), "name") =~? "comment"')
840 call assert_equal('Another Text for VIM', getline('.'))
841 1
842 call search('VIM', 'w', '', 0, 'synIDattr(synID(line("."), col("."), 1), "name") !~? "string"')
843 call assert_equal(' let a = "VIM"', getline('.'))
844
845 " Skip argument using Lambda.
846 1
847 call search('VIM', 'w', '', 0, { -> synIDattr(synID(line("."), col("."), 1), "name") =~? "comment"})
848 call assert_equal('Another Text for VIM', getline('.'))
849
850 1
851 call search('VIM', 'w', '', 0, { -> synIDattr(synID(line("."), col("."), 1), "name") !~? "string"})
852 call assert_equal(' let a = "VIM"', getline('.'))
853
854 " Skip argument using funcref.
855 func InComment()
856 return synIDattr(synID(line("."), col("."), 1), "name") =~? "comment"
857 endfunc
858 func InString()
859 return synIDattr(synID(line("."), col("."), 1), "name") !~? "string"
860 endfunc
861 1
862 call search('VIM', 'w', '', 0, function('InComment'))
863 call assert_equal('Another Text for VIM', getline('.'))
864
865 1
866 call search('VIM', 'w', '', 0, function('InString'))
867 call assert_equal(' let a = "VIM"', getline('.'))
868
869 delfunc InComment
870 delfunc InString
871 bwipe!
872endfunc
873
Bram Moolenaarb46f57e2020-11-29 14:11:41 +0100874func Test_syn_contained_transparent()
875 " Comments starting with "Regression:" show the result when the highlighting
876 " span of the containing item is assigned to the contained region.
877 syntax on
878
879 let l:case = "Transparent region contained in region"
880 new
881 syntax region X start=/\[/ end=/\]/ contained transparent
882 syntax region Y start=/(/ end=/)/ contains=X
883
884 call setline(1, "==(--[~~]--)==")
885 let l:expected = " YYYYYYYYYY "
886 eval AssertHighlightGroups(1, 1, l:expected, 1, l:case)
887 syntax clear Y X
888 bw!
889
890 let l:case = "Transparent region extends region"
891 new
892 syntax region X start=/\[/ end=/\]/ contained transparent
893 syntax region Y start=/(/ end=/)/ end=/e/ contains=X
894
895 call setline(1, "==(--[~~e~~]--)==")
896 let l:expected = " YYYYYYYYYYYYY "
897 " Regression: " YYYYYYY YYY "
898 eval AssertHighlightGroups(1, 1, l:expected, 1, l:case)
899 syntax clear Y X
900 bw!
901
902 let l:case = "Nested transparent regions extend region"
903 new
904 syntax region X start=/\[/ end=/\]/ contained transparent
905 syntax region Y start=/(/ end=/)/ end=/e/ contains=X
906
907 call setline(1, "==(--[~~e~~[~~e~~]~~e~~]--)==")
908 let l:expected = " YYYYYYYYYYYYYYYYYYYYYYYYY "
909 " Regression: " YYYYYYY YYYYYYYYY "
910 eval AssertHighlightGroups(1, 1, l:expected, 1, l:case)
911 syntax clear Y X
912 bw!
913
914 let l:case = "Transparent region contained in match"
915 new
916 syntax region X start=/\[/ end=/\]/ contained transparent
917 syntax match Y /(.\{-})/ contains=X
918
919 call setline(1, "==(--[~~]--)==")
920 let l:expected = " YYYYYYYYYY "
921 eval AssertHighlightGroups(1, 1, l:expected, 1, l:case)
922 syntax clear Y X
923 bw!
924
925 let l:case = "Transparent region extends match"
926 new
927 syntax region X start=/\[/ end=/\]/ contained transparent
928 syntax match Y /(.\{-}[e)]/ contains=X
929
930 call setline(1, "==(--[~~e~~]--)==")
931 let l:expected = " YYYYYYYYYY "
932 " Regression: " YYYYYYY "
933 eval AssertHighlightGroups(1, 1, l:expected, 1, l:case)
934 syntax clear Y X
935 bw!
936
937 let l:case = "Nested transparent regions extend match"
938 new
939 syntax region X start=/\[/ end=/\]/ contained transparent
940 syntax match Y /(.\{-}[e)]/ contains=X
941
942 call setline(1, "==(--[~~e~~[~~e~~]~~e~~]--)==")
943 let l:expected = " YYYYYYYYYYYYYYYYYYYYYY "
944 " Regression: " YYYYYYY YYYYYY "
945 eval AssertHighlightGroups(1, 1, l:expected, 1, l:case)
946 syntax clear Y X
947 bw!
948endfunc
949
Bram Moolenaar2e240bd2021-04-14 11:15:08 +0200950func Test_syn_include_contains_TOP()
951 let l:case = "TOP in included syntax means its group list name"
952 new
953 syntax include @INCLUDED syntax/c.vim
954 syntax region FencedCodeBlockC start=/```c/ end=/```/ contains=@INCLUDED
955
956 call setline(1, ['```c', '#if 0', 'int', '#else', 'int', '#endif', '```' ])
957 let l:expected = ["cCppOutIf2"]
958 eval AssertHighlightGroups(3, 1, l:expected, 1)
959 " cCppOutElse has contains=TOP
960 let l:expected = ["cType"]
961 eval AssertHighlightGroups(5, 1, l:expected, 1, l:case)
962 syntax clear
963 bw!
964endfunc
965
zeertzjqca7e86c2022-04-16 16:49:24 +0100966" This was using freed memory
967func Test_WinEnter_synstack_synID()
968 autocmd WinEnter * call synstack(line("."), col("."))
969 autocmd WinEnter * call synID(line('.'), col('.') - 1, 1)
970 call setline(1, 'aaaaa')
971 normal! $
972 new
973 close
974
975 au! WinEnter
976 bw!
977endfunc
978
Bram Moolenaar2e240bd2021-04-14 11:15:08 +0200979
Bram Moolenaar0e05de42020-03-25 22:23:46 +0100980" vim: shiftwidth=2 sts=2 expandtab