blob: 1a413f6ea9b9124faad0f97d06049edd45b07ca3 [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
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
Bram Moolenaare2e40752020-09-04 21:18:46 +0200130 call assert_fails('syntime abc', 'E475:')
Bram Moolenaar73b484c2016-12-11 15:11:17 +0100131
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
Bram Moolenaarb513d302018-12-02 14:55:08 +0100139func Test_syntime_completion()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200140 CheckFeature profile
Bram Moolenaarb513d302018-12-02 14:55:08 +0100141
142 call feedkeys(":syntime \<C-A>\<C-B>\"\<CR>", 'tx')
143 call assert_equal('"syntime clear off on report', @:)
144endfunc
145
Bram Moolenaar73b484c2016-12-11 15:11:17 +0100146func 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
Bram Moolenaar08f41572020-04-20 16:50:00 +0200170 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
Bram Moolenaar73b484c2016-12-11 15:11:17 +0100174 bd
175endfunc
176
177func Test_syntax_completion()
178 call feedkeys(":syn \<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaare35a52a2020-05-31 19:48:53 +0200179 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 +0100180
181 call feedkeys(":syn case \<C-A>\<C-B>\"\<CR>", 'tx')
182 call assert_equal('"syn case ignore match', @:)
183
Bram Moolenaar2d028392017-01-08 18:28:22 +0100184 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
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100190 " 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
Bram Moolenaar73b484c2016-12-11 15:11:17 +0100196 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
Bram Moolenaarde318c52017-01-17 16:27:10 +0100202
Bram Moolenaar297610b2019-12-27 17:20:55 +0100203func Test_echohl_completion()
204 call feedkeys(":echohl no\<C-A>\<C-B>\"\<CR>", 'tx')
205 call assert_equal('"echohl NonText Normal none', @:)
206endfunc
207
Bram Moolenaarde318c52017-01-17 16:27:10 +0100208func 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'))
Bram Moolenaar58f60ca2017-01-17 17:19:00 +0100231
232 syntax conceal on
233 syntax conceal off
234 call assert_match('conceal off', execute('syntax conceal'))
Bram Moolenaarde318c52017-01-17 16:27:10 +0100235 endif
236
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100237 syntax region Bar start=/</ end=/>/
Bram Moolenaarde318c52017-01-17 16:27:10 +0100238 if 0
239 syntax region NotTest start=/</ end=/>/ contains=@Spell
240 endif
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100241 call assert_match('Bar', execute('syntax'))
Bram Moolenaarde318c52017-01-17 16:27:10 +0100242 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'))
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100251 hi clear Bar
252 hi clear Foo
Bram Moolenaarde318c52017-01-17 16:27:10 +0100253
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'))
Bram Moolenaar58f60ca2017-01-17 17:19:00 +0100334 syn sync clear
Bram Moolenaarde318c52017-01-17 16:27:10 +0100335 if 0
336 syn sync ccomment
337 endif
338 call assert_notmatch('on C-style comments', execute('syntax sync'))
Bram Moolenaar99502802020-11-18 16:53:23 +0100339 syn sync fromstart
340 call assert_match('syncing starts at the first line', execute('syntax sync'))
Bram Moolenaarde318c52017-01-17 16:27:10 +0100341
342 syn clear
343endfunc
344
Bram Moolenaarfbf21222020-04-19 18:31:25 +0200345" 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
Bram Moolenaarea588152017-04-10 22:45:30 +0200357func Test_syntax_invalid_arg()
Bram Moolenaar58f60ca2017-01-17 17:19:00 +0100358 call assert_fails('syntax case asdf', 'E390:')
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100359 if has('conceal')
360 call assert_fails('syntax conceal asdf', 'E390:')
361 endif
Bram Moolenaar58f60ca2017-01-17 17:19:00 +0100362 call assert_fails('syntax spell asdf', 'E390:')
Bram Moolenaarea588152017-04-10 22:45:30 +0200363 call assert_fails('syntax clear @ABCD', 'E391:')
Bram Moolenaarfbf21222020-04-19 18:31:25 +0200364 call assert_fails('syntax include random_file', 'E484:')
365 call assert_fails('syntax include <afile>', 'E495:')
Bram Moolenaarea588152017-04-10 22:45:30 +0200366 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:')
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200369 call assert_fails('syntax cluster Abc add=A add=', 'E406:')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200370
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
Bram Moolenaarfbf21222020-04-19 18:31:25 +0200375 call AssertFails("syntax region MyRegion start='\\z\\(' end='\\*/'", 'E52:')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200376
Bram Moolenaarfbf21222020-04-19 18:31:25 +0200377 let cmd = "syntax region MyRegion start='"
378 let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'"
379 call AssertFails(cmd, 'E50:')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200380
381 set regexpengine=2
Bram Moolenaarfbf21222020-04-19 18:31:25 +0200382 call AssertFails("syntax region MyRegion start='\\z\\(' end='\\*/'", 'E54:')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200383
Bram Moolenaarfbf21222020-04-19 18:31:25 +0200384 let cmd = "syntax region MyRegion start='"
385 let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'"
386 call AssertFails(cmd, 'E879:')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200387 set regexpengine&
Bram Moolenaarfbf21222020-04-19 18:31:25 +0200388
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:')
Bram Moolenaar531be472020-09-23 22:38:05 +0200398 call assert_fails('syntax sync linecont /\%(/', 'E53:')
Bram Moolenaarfbf21222020-04-19 18:31:25 +0200399 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:')
Bram Moolenaar531be472020-09-23 22:38:05 +0200408 call assert_fails('syntax match Search /abc/ contains=ALLBUT,/\%(/', 'E53:')
Bram Moolenaar58f60ca2017-01-17 17:19:00 +0100409endfunc
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
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100422 syntax keyword Bar tar
Bram Moolenaar58f60ca2017-01-17 17:19:00 +0100423 call assert_match('Foo', execute('syntax'))
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100424 call assert_match('Bar', execute('syntax'))
Bram Moolenaarc96272e2017-03-26 13:50:09 +0200425 call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
Bram Moolenaar58f60ca2017-01-17 17:19:00 +0100426 syn clear Foo
427 call assert_notmatch('Foo', execute('syntax'))
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100428 call assert_match('Bar', execute('syntax'))
Bram Moolenaarc96272e2017-03-26 13:50:09 +0200429 call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100430 syn clear Foo Bar
Bram Moolenaar58f60ca2017-01-17 17:19:00 +0100431 call assert_notmatch('Foo', execute('syntax'))
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100432 call assert_notmatch('Bar', execute('syntax'))
433 hi clear Foo
Bram Moolenaarc96272e2017-03-26 13:50:09 +0200434 call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
Bram Moolenaard61e8aa2017-01-17 17:44:46 +0100435 hi clear Bar
Bram Moolenaarfbf21222020-04-19 18:31:25 +0200436 call assert_fails('syntax clear invalid_syngroup', 'E28:')
Bram Moolenaar58f60ca2017-01-17 17:19:00 +0100437endfunc
Bram Moolenaar4007ed42017-01-17 18:14:54 +0100438
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
Bram Moolenaarf8ec9982017-04-09 15:41:31 +0200449
450func Test_ownsyntax()
451 new Xfoo
452 call setline(1, '#define FOO')
453 syntax on
454 set filetype=c
Bram Moolenaard1f76af2020-09-13 22:37:34 +0200455
Bram Moolenaarf8ec9982017-04-09 15:41:31 +0200456 ownsyntax perl
Bram Moolenaard1f76af2020-09-13 22:37:34 +0200457 " this should not crash
458 set
459
Bram Moolenaarf8ec9982017-04-09 15:41:31 +0200460 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')
Bram Moolenaarea7a08a2019-08-26 22:38:22 +0200480 call assert_equal('"ownsyntax java javacc javascript javascriptreact', @:)
Bram Moolenaarf8ec9982017-04-09 15:41:31 +0200481endfunc
Bram Moolenaarea588152017-04-10 22:45:30 +0200482
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
Bram Moolenaar1615b362017-06-04 21:06:09 +0200499func Test_bg_detection()
Bram Moolenaar8c5a2782019-08-07 23:07:07 +0200500 CheckNotGui
501
Bram Moolenaar1615b362017-06-04 21:06:09 +0200502 " 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
Bram Moolenaar0b2eef22017-06-27 15:43:49 +0200513 " manually-set &bg takes precedence over auto-detection
Bram Moolenaar1615b362017-06-04 21:06:09 +0200514 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)
Bram Moolenaar6acadda2018-02-24 16:51:32 +0100520
521 hi Normal ctermbg=NONE
Bram Moolenaar1615b362017-06-04 21:06:09 +0200522endfunc
Bram Moolenaar06f1ed22017-06-18 22:41:03 +0200523
524func Test_syntax_hangs()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200525 CheckFunction reltimefloat
526 CheckFeature syntax
Bram Moolenaar06f1ed22017-06-18 22:41:03 +0200527
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
Bram Moolenaar4d785892017-06-22 22:00:50 +0200556
Bram Moolenaar4d785892017-06-22 22:00:50 +0200557func Test_conceal()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200558 CheckFeature conceal
Bram Moolenaar4d785892017-06-22 22:00:50 +0200559
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])
Bram Moolenaarcc0750d2017-06-24 22:29:24 +0200567 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 +0200568
569 set conceallevel=1
570 call assert_equal('1X 6 ', ScreenLines(2, 7)[0])
Bram Moolenaarcc0750d2017-06-24 22:29:24 +0200571 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 +0200572
573 set conceallevel=1
574 set listchars=conceal:Y
Bram Moolenaarcc0750d2017-06-24 22:29:24 +0200575 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 +0200576 call assert_equal('1XY6 ', ScreenLines(2, 7)[0])
577
578 set conceallevel=2
579 call assert_match('1X6 ', 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=3
583 call assert_match('16 ', ScreenLines(2, 7)[0])
Bram Moolenaarcc0750d2017-06-24 22:29:24 +0200584 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 +0200585
Bram Moolenaarfbf21222020-04-19 18:31:25 +0200586 call AssertFails("syntax match Entity '&amp;' conceal cchar=\<Tab>", 'E844:')
587
Bram Moolenaar4d785892017-06-22 22:00:50 +0200588 syn clear
589 set conceallevel&
590 bw!
591endfunc
Bram Moolenaar0b2eef22017-06-27 15:43:49 +0200592
Bram Moolenaarda650582018-02-20 15:51:40 +0100593func Test_synstack_synIDtrans()
Bram Moolenaar0b2eef22017-06-27 15:43:49 +0200594 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/
Bram Moolenaara74e4942019-08-04 17:35:53 +0200602 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'])
Bram Moolenaar0b2eef22017-06-27 15:43:49 +0200604
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
Bram Moolenaar0e05de42020-03-25 22:23:46 +0100613 call assert_fails("let n=synIDtrans([])", 'E745:')
614
Bram Moolenaar0b2eef22017-06-27 15:43:49 +0200615 syn clear
616 bw!
617endfunc
Bram Moolenaarda650582018-02-20 15:51:40 +0100618
619" Check highlighting for a small piece of C code with a screen dump.
620func Test_syntax_c()
Bram Moolenaar494e9062020-05-31 21:28:02 +0200621 CheckRunVimInTerminal
Bram Moolenaarda650582018-02-20 15:51:40 +0100622 call writefile([
623 \ '/* comment line at the top */',
Bram Moolenaar83e9a1c2019-10-20 14:51:23 +0200624 \ 'int main(int argc, char **argv) { // another comment',
Bram Moolenaarda650582018-02-20 15:51:40 +0100625 \ '#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 \ '}',
Bram Moolenaar82260af2019-10-20 13:16:22 +0200633 \ "\t\t ",
Bram Moolenaarda650582018-02-20 15:51:40 +0100634 \ ' static void',
635 \ 'myFunction(const double count, struct nothing, long there) {',
Bram Moolenaar84590062019-10-18 23:12:20 +0200636 \ "\t// 123: nothing to endif here",
Bram Moolenaar9115c612019-10-16 16:57:06 +0200637 \ "\tfor (int i = 0; i < count; ++i) {",
638 \ "\t break;",
639 \ "\t}",
Bram Moolenaarbbfd1562019-10-19 20:38:15 +0200640 \ "\tNote: asdf",
Bram Moolenaarda650582018-02-20 15:51:40 +0100641 \ '}',
642 \ ], 'Xtest.c')
Bram Moolenaarb7ea7cb2018-02-24 14:38:51 +0100643
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
Bram Moolenaar83e9a1c2019-10-20 14:51:23 +0200648 let buf = RunVimInTerminal('Xtest.c', {})
Bram Moolenaarbbfd1562019-10-19 20:38:15 +0200649 call term_sendkeys(buf, ":syn keyword Search Note\r")
Bram Moolenaar82260af2019-10-20 13:16:22 +0200650 call term_sendkeys(buf, ":syn match Error /^\\s\\+$/\r")
Bram Moolenaar84590062019-10-18 23:12:20 +0200651 call term_sendkeys(buf, ":set hlsearch\r")
652 call term_sendkeys(buf, "/endif\r")
653 call term_sendkeys(buf, "vjfC")
Bram Moolenaar6bb2cdf2018-02-24 19:53:53 +0100654 call VerifyScreenDump(buf, 'Test_syntax_c_01', {})
Bram Moolenaar84590062019-10-18 23:12:20 +0200655
656 call term_sendkeys(buf, "\<Esc>")
Bram Moolenaarda650582018-02-20 15:51:40 +0100657 call StopVimInTerminal(buf)
658
Bram Moolenaarb7ea7cb2018-02-24 14:38:51 +0100659 let $COLORFGBG = ''
Bram Moolenaarda650582018-02-20 15:51:40 +0100660 call delete('Xtest.c')
661endfun
Bram Moolenaarbcf94422018-06-23 14:21:42 +0200662
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
Bram Moolenaarc7f1e402019-08-03 13:29:46 +0200674
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
Bram Moolenaar0e05de42020-03-25 22:23:46 +0100712
Bram Moolenaare35a52a2020-05-31 19:48:53 +0200713func 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
Bram Moolenaare2e40752020-09-04 21:18:46 +0200749 call assert_fails('syn foldlevel start start', 'E390:')
750 call assert_fails('syn foldlevel not_an_option', 'E390:')
Bram Moolenaare35a52a2020-05-31 19:48:53 +0200751
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
Bram Moolenaar99502802020-11-18 16:53:23 +0100760 call assert_match('from the first line$', execute('syn sync'))
Bram Moolenaare35a52a2020-05-31 19:48:53 +0200761 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
Bram Moolenaaradc17a52020-06-06 18:37:51 +0200797func 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
Bram Moolenaarb46f57e2020-11-29 14:11:41 +0100847func 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
Bram Moolenaar0e05de42020-03-25 22:23:46 +0100923" vim: shiftwidth=2 sts=2 expandtab