Bram Moolenaar | b8060fe | 2016-01-19 22:29:28 +0100 | [diff] [blame] | 1 | " Test for syntax and syntax iskeyword option |
| 2 | |
Bram Moolenaar | b46fecd | 2019-06-15 17:58:09 +0200 | [diff] [blame] | 3 | source check.vim |
| 4 | CheckFeature syntax |
Bram Moolenaar | b8060fe | 2016-01-19 22:29:28 +0100 | [diff] [blame] | 5 | |
Bram Moolenaar | 4d78589 | 2017-06-22 22:00:50 +0200 | [diff] [blame] | 6 | source view_util.vim |
Bram Moolenaar | 6bb2cdf | 2018-02-24 19:53:53 +0100 | [diff] [blame] | 7 | source screendump.vim |
Bram Moolenaar | 4d78589 | 2017-06-22 22:00:50 +0200 | [diff] [blame] | 8 | |
Bram Moolenaar | b8060fe | 2016-01-19 22:29:28 +0100 | [diff] [blame] | 9 | func 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 |
| 28 | endfunc |
| 29 | |
Bram Moolenaar | b46f57e | 2020-11-29 14:11:41 +0100 | [diff] [blame] | 30 | func 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 |
| 48 | endfunc |
| 49 | |
Bram Moolenaar | b8060fe | 2016-01-19 22:29:28 +0100 | [diff] [blame] | 50 | func Test_syn_iskeyword() |
| 51 | new |
| 52 | call setline(1, [ |
| 53 | \ 'CREATE TABLE FOOBAR(', |
| 54 | \ ' DLTD_BY VARCHAR2(100)', |
| 55 | \ ');', |
Bram Moolenaar | 037c54f | 2019-04-20 23:47:46 +0200 | [diff] [blame] | 56 | \ '']) |
Bram Moolenaar | b8060fe | 2016-01-19 22:29:28 +0100 | [diff] [blame] | 57 | |
| 58 | syntax on |
| 59 | set ft=sql |
| 60 | syn match SYN /C\k\+\>/ |
| 61 | hi link SYN ErrorMsg |
| 62 | call assert_equal('DLTD_BY', GetSyntaxItem('DLTD')) |
| 63 | /\<D\k\+\>/:norm! ygn |
| 64 | call assert_equal('DLTD_BY', @0) |
| 65 | redir @c |
| 66 | syn iskeyword |
| 67 | redir END |
| 68 | call assert_equal("\nsyntax iskeyword not set", @c) |
| 69 | |
| 70 | syn iskeyword @,48-57,_,192-255 |
| 71 | redir @c |
| 72 | syn iskeyword |
| 73 | redir END |
| 74 | call assert_equal("\nsyntax iskeyword @,48-57,_,192-255", @c) |
| 75 | |
| 76 | setlocal isk-=_ |
| 77 | call assert_equal('DLTD_BY', GetSyntaxItem('DLTD')) |
| 78 | /\<D\k\+\>/:norm! ygn |
Bram Moolenaar | 73b484c | 2016-12-11 15:11:17 +0100 | [diff] [blame] | 79 | let b2 = @0 |
Bram Moolenaar | b8060fe | 2016-01-19 22:29:28 +0100 | [diff] [blame] | 80 | call assert_equal('DLTD', @0) |
| 81 | |
| 82 | syn iskeyword clear |
| 83 | redir @c |
| 84 | syn iskeyword |
| 85 | redir END |
| 86 | call assert_equal("\nsyntax iskeyword not set", @c) |
| 87 | |
| 88 | quit! |
| 89 | endfunc |
Bram Moolenaar | c369133 | 2016-04-20 12:49:49 +0200 | [diff] [blame] | 90 | |
| 91 | func 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') |
| 104 | endfunc |
Bram Moolenaar | 73b484c | 2016-12-11 15:11:17 +0100 | [diff] [blame] | 105 | |
| 106 | func Test_syntime() |
Bram Moolenaar | 6d91bcb | 2020-08-12 18:50:36 +0200 | [diff] [blame] | 107 | CheckFeature profile |
Bram Moolenaar | 73b484c | 2016-12-11 15:11:17 +0100 | [diff] [blame] | 108 | |
| 109 | syntax on |
| 110 | syntime on |
| 111 | let a = execute('syntime report') |
| 112 | call assert_equal("\nNo Syntax items defined for this buffer", a) |
| 113 | |
Dominique Pelle | 6d37e8e | 2021-05-06 17:36:55 +0200 | [diff] [blame] | 114 | let a = execute('syntime clear') |
| 115 | call assert_equal("\nNo Syntax items defined for this buffer", a) |
| 116 | |
Bram Moolenaar | 73b484c | 2016-12-11 15:11:17 +0100 | [diff] [blame] | 117 | 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 Moolenaar | e2e4075 | 2020-09-04 21:18:46 +0200 | [diff] [blame] | 133 | call assert_fails('syntime abc', 'E475:') |
Bram Moolenaar | 73b484c | 2016-12-11 15:11:17 +0100 | [diff] [blame] | 134 | |
| 135 | syntax clear |
| 136 | let a = execute('syntime report') |
| 137 | call assert_equal("\nNo Syntax items defined for this buffer", a) |
| 138 | |
| 139 | bd |
| 140 | endfunc |
| 141 | |
Bram Moolenaar | b513d30 | 2018-12-02 14:55:08 +0100 | [diff] [blame] | 142 | func Test_syntime_completion() |
Bram Moolenaar | 6d91bcb | 2020-08-12 18:50:36 +0200 | [diff] [blame] | 143 | CheckFeature profile |
Bram Moolenaar | b513d30 | 2018-12-02 14:55:08 +0100 | [diff] [blame] | 144 | |
| 145 | call feedkeys(":syntime \<C-A>\<C-B>\"\<CR>", 'tx') |
| 146 | call assert_equal('"syntime clear off on report', @:) |
| 147 | endfunc |
| 148 | |
Bram Moolenaar | 73b484c | 2016-12-11 15:11:17 +0100 | [diff] [blame] | 149 | func 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 Moolenaar | 08f4157 | 2020-04-20 16:50:00 +0200 | [diff] [blame] | 173 | 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 Moolenaar | 73b484c | 2016-12-11 15:11:17 +0100 | [diff] [blame] | 177 | bd |
| 178 | endfunc |
| 179 | |
| 180 | func Test_syntax_completion() |
| 181 | call feedkeys(":syn \<C-A>\<C-B>\"\<CR>", 'tx') |
Bram Moolenaar | e35a52a | 2020-05-31 19:48:53 +0200 | [diff] [blame] | 182 | call assert_equal('"syn case clear cluster conceal enable foldlevel include iskeyword keyword list manual match off on region reset spell sync', @:) |
Bram Moolenaar | 73b484c | 2016-12-11 15:11:17 +0100 | [diff] [blame] | 183 | |
| 184 | call feedkeys(":syn case \<C-A>\<C-B>\"\<CR>", 'tx') |
| 185 | call assert_equal('"syn case ignore match', @:) |
| 186 | |
Bram Moolenaar | 2d02839 | 2017-01-08 18:28:22 +0100 | [diff] [blame] | 187 | 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 Moolenaar | d61e8aa | 2017-01-17 17:44:46 +0100 | [diff] [blame] | 193 | " 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 Moolenaar | 73b484c | 2016-12-11 15:11:17 +0100 | [diff] [blame] | 199 | 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 ', @:) |
| 204 | endfunc |
Bram Moolenaar | de318c5 | 2017-01-17 16:27:10 +0100 | [diff] [blame] | 205 | |
Bram Moolenaar | 297610b | 2019-12-27 17:20:55 +0100 | [diff] [blame] | 206 | func Test_echohl_completion() |
| 207 | call feedkeys(":echohl no\<C-A>\<C-B>\"\<CR>", 'tx') |
| 208 | call assert_equal('"echohl NonText Normal none', @:) |
| 209 | endfunc |
| 210 | |
Bram Moolenaar | de318c5 | 2017-01-17 16:27:10 +0100 | [diff] [blame] | 211 | func 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 Moolenaar | 58f60ca | 2017-01-17 17:19:00 +0100 | [diff] [blame] | 234 | |
| 235 | syntax conceal on |
| 236 | syntax conceal off |
| 237 | call assert_match('conceal off', execute('syntax conceal')) |
Bram Moolenaar | de318c5 | 2017-01-17 16:27:10 +0100 | [diff] [blame] | 238 | endif |
| 239 | |
Bram Moolenaar | d61e8aa | 2017-01-17 17:44:46 +0100 | [diff] [blame] | 240 | syntax region Bar start=/</ end=/>/ |
Bram Moolenaar | de318c5 | 2017-01-17 16:27:10 +0100 | [diff] [blame] | 241 | if 0 |
| 242 | syntax region NotTest start=/</ end=/>/ contains=@Spell |
| 243 | endif |
Bram Moolenaar | d61e8aa | 2017-01-17 17:44:46 +0100 | [diff] [blame] | 244 | call assert_match('Bar', execute('syntax')) |
Bram Moolenaar | de318c5 | 2017-01-17 16:27:10 +0100 | [diff] [blame] | 245 | 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 Moolenaar | d61e8aa | 2017-01-17 17:44:46 +0100 | [diff] [blame] | 254 | hi clear Bar |
| 255 | hi clear Foo |
Bram Moolenaar | de318c5 | 2017-01-17 16:27:10 +0100 | [diff] [blame] | 256 | |
| 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 Moolenaar | 58f60ca | 2017-01-17 17:19:00 +0100 | [diff] [blame] | 337 | syn sync clear |
Bram Moolenaar | de318c5 | 2017-01-17 16:27:10 +0100 | [diff] [blame] | 338 | if 0 |
| 339 | syn sync ccomment |
| 340 | endif |
| 341 | call assert_notmatch('on C-style comments', execute('syntax sync')) |
Bram Moolenaar | 9950280 | 2020-11-18 16:53:23 +0100 | [diff] [blame] | 342 | syn sync fromstart |
| 343 | call assert_match('syncing starts at the first line', execute('syntax sync')) |
Bram Moolenaar | de318c5 | 2017-01-17 16:27:10 +0100 | [diff] [blame] | 344 | |
| 345 | syn clear |
| 346 | endfunc |
| 347 | |
Bram Moolenaar | fbf2122 | 2020-04-19 18:31:25 +0200 | [diff] [blame] | 348 | " Check for an error. Used when multiple errors are thrown and we are checking |
| 349 | " for an earliest error. |
| 350 | func 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) |
| 358 | endfunc |
| 359 | |
Bram Moolenaar | ea58815 | 2017-04-10 22:45:30 +0200 | [diff] [blame] | 360 | func Test_syntax_invalid_arg() |
Bram Moolenaar | 58f60ca | 2017-01-17 17:19:00 +0100 | [diff] [blame] | 361 | call assert_fails('syntax case asdf', 'E390:') |
Bram Moolenaar | d61e8aa | 2017-01-17 17:44:46 +0100 | [diff] [blame] | 362 | if has('conceal') |
| 363 | call assert_fails('syntax conceal asdf', 'E390:') |
| 364 | endif |
Bram Moolenaar | 58f60ca | 2017-01-17 17:19:00 +0100 | [diff] [blame] | 365 | call assert_fails('syntax spell asdf', 'E390:') |
Bram Moolenaar | ea58815 | 2017-04-10 22:45:30 +0200 | [diff] [blame] | 366 | call assert_fails('syntax clear @ABCD', 'E391:') |
Bram Moolenaar | fbf2122 | 2020-04-19 18:31:25 +0200 | [diff] [blame] | 367 | call assert_fails('syntax include random_file', 'E484:') |
| 368 | call assert_fails('syntax include <afile>', 'E495:') |
Bram Moolenaar | ea58815 | 2017-04-10 22:45:30 +0200 | [diff] [blame] | 369 | 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 Moolenaar | 9b7bf9e | 2020-07-11 22:14:59 +0200 | [diff] [blame] | 372 | call assert_fails('syntax cluster Abc add=A add=', 'E406:') |
Bram Moolenaar | 476a613 | 2020-04-08 19:48:56 +0200 | [diff] [blame] | 373 | |
| 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 Moolenaar | fbf2122 | 2020-04-19 18:31:25 +0200 | [diff] [blame] | 378 | call AssertFails("syntax region MyRegion start='\\z\\(' end='\\*/'", 'E52:') |
Bram Moolenaar | 476a613 | 2020-04-08 19:48:56 +0200 | [diff] [blame] | 379 | |
Bram Moolenaar | fbf2122 | 2020-04-19 18:31:25 +0200 | [diff] [blame] | 380 | let cmd = "syntax region MyRegion start='" |
| 381 | let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'" |
| 382 | call AssertFails(cmd, 'E50:') |
Bram Moolenaar | 476a613 | 2020-04-08 19:48:56 +0200 | [diff] [blame] | 383 | |
| 384 | set regexpengine=2 |
Bram Moolenaar | fbf2122 | 2020-04-19 18:31:25 +0200 | [diff] [blame] | 385 | call AssertFails("syntax region MyRegion start='\\z\\(' end='\\*/'", 'E54:') |
Bram Moolenaar | 476a613 | 2020-04-08 19:48:56 +0200 | [diff] [blame] | 386 | |
Bram Moolenaar | fbf2122 | 2020-04-19 18:31:25 +0200 | [diff] [blame] | 387 | let cmd = "syntax region MyRegion start='" |
| 388 | let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'" |
| 389 | call AssertFails(cmd, 'E879:') |
Bram Moolenaar | 476a613 | 2020-04-08 19:48:56 +0200 | [diff] [blame] | 390 | set regexpengine& |
Bram Moolenaar | fbf2122 | 2020-04-19 18:31:25 +0200 | [diff] [blame] | 391 | |
| 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 Moolenaar | 531be47 | 2020-09-23 22:38:05 +0200 | [diff] [blame] | 401 | call assert_fails('syntax sync linecont /\%(/', 'E53:') |
Bram Moolenaar | fbf2122 | 2020-04-19 18:31:25 +0200 | [diff] [blame] | 402 | 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 Moolenaar | 531be47 | 2020-09-23 22:38:05 +0200 | [diff] [blame] | 411 | call assert_fails('syntax match Search /abc/ contains=ALLBUT,/\%(/', 'E53:') |
Bram Moolenaar | 58f60ca | 2017-01-17 17:19:00 +0100 | [diff] [blame] | 412 | endfunc |
| 413 | |
| 414 | func 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 |
| 421 | endfunc |
| 422 | |
| 423 | func Test_syn_clear() |
| 424 | syntax keyword Foo foo |
Bram Moolenaar | d61e8aa | 2017-01-17 17:44:46 +0100 | [diff] [blame] | 425 | syntax keyword Bar tar |
Bram Moolenaar | 58f60ca | 2017-01-17 17:19:00 +0100 | [diff] [blame] | 426 | call assert_match('Foo', execute('syntax')) |
Bram Moolenaar | d61e8aa | 2017-01-17 17:44:46 +0100 | [diff] [blame] | 427 | call assert_match('Bar', execute('syntax')) |
Bram Moolenaar | c96272e | 2017-03-26 13:50:09 +0200 | [diff] [blame] | 428 | call assert_equal('Foo', synIDattr(hlID("Foo"), "name")) |
Bram Moolenaar | 58f60ca | 2017-01-17 17:19:00 +0100 | [diff] [blame] | 429 | syn clear Foo |
| 430 | call assert_notmatch('Foo', execute('syntax')) |
Bram Moolenaar | d61e8aa | 2017-01-17 17:44:46 +0100 | [diff] [blame] | 431 | call assert_match('Bar', execute('syntax')) |
Bram Moolenaar | c96272e | 2017-03-26 13:50:09 +0200 | [diff] [blame] | 432 | call assert_equal('Foo', synIDattr(hlID("Foo"), "name")) |
Bram Moolenaar | d61e8aa | 2017-01-17 17:44:46 +0100 | [diff] [blame] | 433 | syn clear Foo Bar |
Bram Moolenaar | 58f60ca | 2017-01-17 17:19:00 +0100 | [diff] [blame] | 434 | call assert_notmatch('Foo', execute('syntax')) |
Bram Moolenaar | d61e8aa | 2017-01-17 17:44:46 +0100 | [diff] [blame] | 435 | call assert_notmatch('Bar', execute('syntax')) |
| 436 | hi clear Foo |
Bram Moolenaar | c96272e | 2017-03-26 13:50:09 +0200 | [diff] [blame] | 437 | call assert_equal('Foo', synIDattr(hlID("Foo"), "name")) |
Bram Moolenaar | d61e8aa | 2017-01-17 17:44:46 +0100 | [diff] [blame] | 438 | hi clear Bar |
Bram Moolenaar | fbf2122 | 2020-04-19 18:31:25 +0200 | [diff] [blame] | 439 | call assert_fails('syntax clear invalid_syngroup', 'E28:') |
Bram Moolenaar | 58f60ca | 2017-01-17 17:19:00 +0100 | [diff] [blame] | 440 | endfunc |
Bram Moolenaar | 4007ed4 | 2017-01-17 18:14:54 +0100 | [diff] [blame] | 441 | |
| 442 | func 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 |
| 451 | endfunc |
Bram Moolenaar | f8ec998 | 2017-04-09 15:41:31 +0200 | [diff] [blame] | 452 | |
| 453 | func Test_ownsyntax() |
| 454 | new Xfoo |
| 455 | call setline(1, '#define FOO') |
| 456 | syntax on |
| 457 | set filetype=c |
Bram Moolenaar | d1f76af | 2020-09-13 22:37:34 +0200 | [diff] [blame] | 458 | |
Bram Moolenaar | f8ec998 | 2017-04-09 15:41:31 +0200 | [diff] [blame] | 459 | ownsyntax perl |
Bram Moolenaar | d1f76af | 2020-09-13 22:37:34 +0200 | [diff] [blame] | 460 | " this should not crash |
| 461 | set |
| 462 | |
Bram Moolenaar | f8ec998 | 2017-04-09 15:41:31 +0200 | [diff] [blame] | 463 | 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! |
| 479 | endfunc |
| 480 | |
| 481 | func Test_ownsyntax_completion() |
| 482 | call feedkeys(":ownsyntax java\<C-A>\<C-B>\"\<CR>", 'tx') |
Bram Moolenaar | ea7a08a | 2019-08-26 22:38:22 +0200 | [diff] [blame] | 483 | call assert_equal('"ownsyntax java javacc javascript javascriptreact', @:) |
Bram Moolenaar | f8ec998 | 2017-04-09 15:41:31 +0200 | [diff] [blame] | 484 | endfunc |
Bram Moolenaar | ea58815 | 2017-04-10 22:45:30 +0200 | [diff] [blame] | 485 | |
| 486 | func 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:') |
| 500 | endfunc |
| 501 | |
Bram Moolenaar | 1615b36 | 2017-06-04 21:06:09 +0200 | [diff] [blame] | 502 | func Test_bg_detection() |
Bram Moolenaar | 8c5a278 | 2019-08-07 23:07:07 +0200 | [diff] [blame] | 503 | CheckNotGui |
| 504 | |
Dominique Pelle | 923dce2 | 2021-11-21 11:36:04 +0000 | [diff] [blame] | 505 | " auto-detection of &bg, make sure it isn't set anywhere before this test |
Bram Moolenaar | 1615b36 | 2017-06-04 21:06:09 +0200 | [diff] [blame] | 506 | 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 Moolenaar | 0b2eef2 | 2017-06-27 15:43:49 +0200 | [diff] [blame] | 515 | " manually-set &bg takes precedence over auto-detection |
Bram Moolenaar | 1615b36 | 2017-06-04 21:06:09 +0200 | [diff] [blame] | 516 | 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 Moolenaar | 6acadda | 2018-02-24 16:51:32 +0100 | [diff] [blame] | 522 | |
| 523 | hi Normal ctermbg=NONE |
Bram Moolenaar | 1615b36 | 2017-06-04 21:06:09 +0200 | [diff] [blame] | 524 | endfunc |
Bram Moolenaar | 06f1ed2 | 2017-06-18 22:41:03 +0200 | [diff] [blame] | 525 | |
| 526 | func Test_syntax_hangs() |
Bram Moolenaar | 6d91bcb | 2020-08-12 18:50:36 +0200 | [diff] [blame] | 527 | CheckFunction reltimefloat |
| 528 | CheckFeature syntax |
Bram Moolenaar | 06f1ed2 | 2017-06-18 22:41:03 +0200 | [diff] [blame] | 529 | |
Paul Ollis | 6574577 | 2022-06-05 16:55:54 +0100 | [diff] [blame] | 530 | " 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 Moolenaar | 06f1ed2 | 2017-06-18 22:41:03 +0200 | [diff] [blame] | 539 | " 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)) |
Paul Ollis | 6574577 | 2022-06-05 16:55:54 +0100 | [diff] [blame] | 547 | call assert_true(elapsed > min_timeout) |
Bram Moolenaar | 06f1ed2 | 2017-06-18 22:41:03 +0200 | [diff] [blame] | 548 | call assert_true(elapsed < 1.0) |
| 549 | |
| 550 | " second time syntax HL is disabled |
| 551 | let start = reltime() |
| 552 | redraw |
| 553 | let elapsed = reltimefloat(reltime(start)) |
| 554 | call assert_true(elapsed < 0.1) |
| 555 | |
| 556 | " after CTRL-L the timeout flag is reset |
| 557 | let start = reltime() |
| 558 | exe "normal \<C-L>" |
| 559 | redraw |
| 560 | let elapsed = reltimefloat(reltime(start)) |
Paul Ollis | 6574577 | 2022-06-05 16:55:54 +0100 | [diff] [blame] | 561 | call assert_true(elapsed > min_timeout) |
Bram Moolenaar | 06f1ed2 | 2017-06-18 22:41:03 +0200 | [diff] [blame] | 562 | call assert_true(elapsed < 1.0) |
| 563 | |
| 564 | set redrawtime& |
| 565 | bwipe! |
| 566 | endfunc |
Bram Moolenaar | 4d78589 | 2017-06-22 22:00:50 +0200 | [diff] [blame] | 567 | |
Bram Moolenaar | 4d78589 | 2017-06-22 22:00:50 +0200 | [diff] [blame] | 568 | func Test_conceal() |
Bram Moolenaar | 6d91bcb | 2020-08-12 18:50:36 +0200 | [diff] [blame] | 569 | CheckFeature conceal |
Bram Moolenaar | 4d78589 | 2017-06-22 22:00:50 +0200 | [diff] [blame] | 570 | |
| 571 | new |
| 572 | call setline(1, ['', '123456']) |
| 573 | syn match test23 "23" conceal cchar=X |
| 574 | syn match test45 "45" conceal |
| 575 | |
| 576 | set conceallevel=0 |
| 577 | call assert_equal('123456 ', ScreenLines(2, 7)[0]) |
Bram Moolenaar | cc0750d | 2017-06-24 22:29:24 +0200 | [diff] [blame] | 578 | call assert_equal([[0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)')) |
Bram Moolenaar | 4d78589 | 2017-06-22 22:00:50 +0200 | [diff] [blame] | 579 | |
| 580 | set conceallevel=1 |
| 581 | call assert_equal('1X 6 ', ScreenLines(2, 7)[0]) |
Bram Moolenaar | cc0750d | 2017-06-24 22:29:24 +0200 | [diff] [blame] | 582 | 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 Moolenaar | 4d78589 | 2017-06-22 22:00:50 +0200 | [diff] [blame] | 583 | |
| 584 | set conceallevel=1 |
| 585 | set listchars=conceal:Y |
Bram Moolenaar | cc0750d | 2017-06-24 22:29:24 +0200 | [diff] [blame] | 586 | 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 Moolenaar | 4d78589 | 2017-06-22 22:00:50 +0200 | [diff] [blame] | 587 | call assert_equal('1XY6 ', ScreenLines(2, 7)[0]) |
| 588 | |
| 589 | set conceallevel=2 |
| 590 | call assert_match('1X6 ', ScreenLines(2, 7)[0]) |
Bram Moolenaar | cc0750d | 2017-06-24 22:29:24 +0200 | [diff] [blame] | 591 | 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 Moolenaar | 4d78589 | 2017-06-22 22:00:50 +0200 | [diff] [blame] | 592 | |
| 593 | set conceallevel=3 |
| 594 | call assert_match('16 ', ScreenLines(2, 7)[0]) |
Bram Moolenaar | cc0750d | 2017-06-24 22:29:24 +0200 | [diff] [blame] | 595 | call assert_equal([[0, '', 0], [1, '', 1], [1, '', 1], [1, '', 2], [1, '', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)')) |
Bram Moolenaar | 4d78589 | 2017-06-22 22:00:50 +0200 | [diff] [blame] | 596 | |
Bram Moolenaar | fbf2122 | 2020-04-19 18:31:25 +0200 | [diff] [blame] | 597 | call AssertFails("syntax match Entity '&' conceal cchar=\<Tab>", 'E844:') |
| 598 | |
Bram Moolenaar | 4d78589 | 2017-06-22 22:00:50 +0200 | [diff] [blame] | 599 | syn clear |
| 600 | set conceallevel& |
| 601 | bw! |
| 602 | endfunc |
Bram Moolenaar | 0b2eef2 | 2017-06-27 15:43:49 +0200 | [diff] [blame] | 603 | |
Bram Moolenaar | da65058 | 2018-02-20 15:51:40 +0100 | [diff] [blame] | 604 | func Test_synstack_synIDtrans() |
Bram Moolenaar | 0b2eef2 | 2017-06-27 15:43:49 +0200 | [diff] [blame] | 605 | new |
| 606 | setfiletype c |
| 607 | syntax on |
| 608 | call setline(1, ' /* A comment with a TODO */') |
| 609 | |
| 610 | call assert_equal([], synstack(1, 1)) |
| 611 | |
| 612 | norm f/ |
Bram Moolenaar | a74e494 | 2019-08-04 17:35:53 +0200 | [diff] [blame] | 613 | eval synstack(line("."), col("."))->map('synIDattr(v:val, "name")')->assert_equal(['cComment', 'cCommentStart']) |
| 614 | eval synstack(line("."), col("."))->map('synIDattr(synIDtrans(v:val), "name")')->assert_equal(['Comment', 'Comment']) |
Bram Moolenaar | 0b2eef2 | 2017-06-27 15:43:49 +0200 | [diff] [blame] | 615 | |
| 616 | norm fA |
| 617 | call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")')) |
| 618 | call assert_equal(['Comment'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")')) |
| 619 | |
| 620 | norm fT |
| 621 | call assert_equal(['cComment', 'cTodo'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")')) |
| 622 | call assert_equal(['Comment', 'Todo'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")')) |
| 623 | |
Bram Moolenaar | 0e05de4 | 2020-03-25 22:23:46 +0100 | [diff] [blame] | 624 | call assert_fails("let n=synIDtrans([])", 'E745:') |
| 625 | |
Bram Moolenaar | 0b2eef2 | 2017-06-27 15:43:49 +0200 | [diff] [blame] | 626 | syn clear |
| 627 | bw! |
| 628 | endfunc |
Bram Moolenaar | da65058 | 2018-02-20 15:51:40 +0100 | [diff] [blame] | 629 | |
| 630 | " Check highlighting for a small piece of C code with a screen dump. |
| 631 | func Test_syntax_c() |
Bram Moolenaar | 494e906 | 2020-05-31 21:28:02 +0200 | [diff] [blame] | 632 | CheckRunVimInTerminal |
Bram Moolenaar | da65058 | 2018-02-20 15:51:40 +0100 | [diff] [blame] | 633 | call writefile([ |
| 634 | \ '/* comment line at the top */', |
Bram Moolenaar | 83e9a1c | 2019-10-20 14:51:23 +0200 | [diff] [blame] | 635 | \ 'int main(int argc, char **argv) { // another comment', |
Bram Moolenaar | da65058 | 2018-02-20 15:51:40 +0100 | [diff] [blame] | 636 | \ '#if 0', |
| 637 | \ ' int not_used;', |
| 638 | \ '#else', |
| 639 | \ ' int used;', |
| 640 | \ '#endif', |
| 641 | \ ' printf("Just an example piece of C code\n");', |
| 642 | \ ' return 0x0ff;', |
| 643 | \ '}', |
Bram Moolenaar | 82260af | 2019-10-20 13:16:22 +0200 | [diff] [blame] | 644 | \ "\t\t ", |
Bram Moolenaar | da65058 | 2018-02-20 15:51:40 +0100 | [diff] [blame] | 645 | \ ' static void', |
| 646 | \ 'myFunction(const double count, struct nothing, long there) {', |
Bram Moolenaar | 8459006 | 2019-10-18 23:12:20 +0200 | [diff] [blame] | 647 | \ "\t// 123: nothing to endif here", |
Bram Moolenaar | 9115c61 | 2019-10-16 16:57:06 +0200 | [diff] [blame] | 648 | \ "\tfor (int i = 0; i < count; ++i) {", |
| 649 | \ "\t break;", |
| 650 | \ "\t}", |
Bram Moolenaar | bbfd156 | 2019-10-19 20:38:15 +0200 | [diff] [blame] | 651 | \ "\tNote: asdf", |
Bram Moolenaar | da65058 | 2018-02-20 15:51:40 +0100 | [diff] [blame] | 652 | \ '}', |
| 653 | \ ], 'Xtest.c') |
Paul Ollis | 6574577 | 2022-06-05 16:55:54 +0100 | [diff] [blame] | 654 | |
Bram Moolenaar | b7ea7cb | 2018-02-24 14:38:51 +0100 | [diff] [blame] | 655 | " This makes the default for 'background' use "dark", check that the |
| 656 | " response to t_RB corrects it to "light". |
| 657 | let $COLORFGBG = '15;0' |
| 658 | |
Bram Moolenaar | 83e9a1c | 2019-10-20 14:51:23 +0200 | [diff] [blame] | 659 | let buf = RunVimInTerminal('Xtest.c', {}) |
Bram Moolenaar | bbfd156 | 2019-10-19 20:38:15 +0200 | [diff] [blame] | 660 | call term_sendkeys(buf, ":syn keyword Search Note\r") |
Bram Moolenaar | 82260af | 2019-10-20 13:16:22 +0200 | [diff] [blame] | 661 | call term_sendkeys(buf, ":syn match Error /^\\s\\+$/\r") |
Bram Moolenaar | 8459006 | 2019-10-18 23:12:20 +0200 | [diff] [blame] | 662 | call term_sendkeys(buf, ":set hlsearch\r") |
| 663 | call term_sendkeys(buf, "/endif\r") |
| 664 | call term_sendkeys(buf, "vjfC") |
Bram Moolenaar | 6bb2cdf | 2018-02-24 19:53:53 +0100 | [diff] [blame] | 665 | call VerifyScreenDump(buf, 'Test_syntax_c_01', {}) |
Bram Moolenaar | 8459006 | 2019-10-18 23:12:20 +0200 | [diff] [blame] | 666 | |
| 667 | call term_sendkeys(buf, "\<Esc>") |
Bram Moolenaar | da65058 | 2018-02-20 15:51:40 +0100 | [diff] [blame] | 668 | call StopVimInTerminal(buf) |
| 669 | |
Bram Moolenaar | b7ea7cb | 2018-02-24 14:38:51 +0100 | [diff] [blame] | 670 | let $COLORFGBG = '' |
Bram Moolenaar | da65058 | 2018-02-20 15:51:40 +0100 | [diff] [blame] | 671 | call delete('Xtest.c') |
| 672 | endfun |
Bram Moolenaar | bcf9442 | 2018-06-23 14:21:42 +0200 | [diff] [blame] | 673 | |
Dominique Pelle | 354b23a | 2021-12-17 17:32:29 +0000 | [diff] [blame] | 674 | " Test \z(...) along with \z1 |
| 675 | func Test_syn_zsub() |
| 676 | new |
| 677 | syntax on |
| 678 | call setline(1, 'xxx start foo xxx not end foo xxx end foo xxx') |
| 679 | let l:expected = ' ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ' |
| 680 | |
| 681 | for l:re in [0, 1, 2] |
| 682 | " Example taken from :help :syn-ext-match |
| 683 | syntax region Z start="start \z(\I\i*\)" skip="not end \z1" end="end \z1" |
| 684 | eval AssertHighlightGroups(1, 1, l:expected, 1, 'regexp=' .. l:re) |
| 685 | syntax clear Z |
| 686 | endfor |
| 687 | |
| 688 | set re& |
| 689 | bw! |
| 690 | endfunc |
| 691 | |
Bram Moolenaar | bcf9442 | 2018-06-23 14:21:42 +0200 | [diff] [blame] | 692 | " Using \z() in a region with NFA failing should not crash. |
| 693 | func Test_syn_wrong_z_one() |
| 694 | new |
| 695 | call setline(1, ['just some text', 'with foo and bar to match with']) |
| 696 | syn region FooBar start="foo\z(.*\)bar" end="\z1" |
| 697 | call test_override("nfa_fail", 1) |
| 698 | redraw! |
| 699 | redraw! |
| 700 | call test_override("ALL", 0) |
| 701 | bwipe! |
| 702 | endfunc |
Bram Moolenaar | c7f1e40 | 2019-08-03 13:29:46 +0200 | [diff] [blame] | 703 | |
| 704 | func Test_syntax_after_bufdo() |
| 705 | call writefile(['/* aaa comment */'], 'Xaaa.c') |
| 706 | call writefile(['/* bbb comment */'], 'Xbbb.c') |
| 707 | call writefile(['/* ccc comment */'], 'Xccc.c') |
| 708 | call writefile(['/* ddd comment */'], 'Xddd.c') |
| 709 | |
| 710 | let bnr = bufnr('%') |
| 711 | new Xaaa.c |
| 712 | badd Xbbb.c |
| 713 | badd Xccc.c |
| 714 | badd Xddd.c |
| 715 | exe "bwipe " . bnr |
| 716 | let l = [] |
| 717 | bufdo call add(l, bufnr('%')) |
| 718 | call assert_equal(4, len(l)) |
| 719 | |
| 720 | syntax on |
| 721 | |
| 722 | " This used to only enable syntax HL in the last buffer. |
| 723 | bufdo tab split |
| 724 | tabrewind |
| 725 | for tab in range(1, 4) |
| 726 | norm fm |
| 727 | call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")')) |
| 728 | tabnext |
| 729 | endfor |
| 730 | |
| 731 | bwipe! Xaaa.c |
| 732 | bwipe! Xbbb.c |
| 733 | bwipe! Xccc.c |
| 734 | bwipe! Xddd.c |
| 735 | syntax off |
| 736 | call delete('Xaaa.c') |
| 737 | call delete('Xbbb.c') |
| 738 | call delete('Xccc.c') |
| 739 | call delete('Xddd.c') |
| 740 | endfunc |
Bram Moolenaar | 0e05de4 | 2020-03-25 22:23:46 +0100 | [diff] [blame] | 741 | |
Bram Moolenaar | e35a52a | 2020-05-31 19:48:53 +0200 | [diff] [blame] | 742 | func Test_syntax_foldlevel() |
| 743 | new |
| 744 | call setline(1, [ |
| 745 | \ 'void f(int a)', |
| 746 | \ '{', |
| 747 | \ ' if (a == 1) {', |
| 748 | \ ' a = 0;', |
| 749 | \ ' } else if (a == 2) {', |
| 750 | \ ' a = 1;', |
| 751 | \ ' } else {', |
| 752 | \ ' a = 2;', |
| 753 | \ ' }', |
| 754 | \ ' if (a > 0) {', |
| 755 | \ ' if (a == 1) {', |
| 756 | \ ' a = 0;', |
| 757 | \ ' } /* missing newline */ } /* end of outer if */ else {', |
| 758 | \ ' a = 1;', |
| 759 | \ ' }', |
| 760 | \ ' if (a == 1)', |
| 761 | \ ' {', |
| 762 | \ ' a = 0;', |
| 763 | \ ' }', |
| 764 | \ ' else if (a == 2)', |
| 765 | \ ' {', |
| 766 | \ ' a = 1;', |
| 767 | \ ' }', |
| 768 | \ ' else', |
| 769 | \ ' {', |
| 770 | \ ' a = 2;', |
| 771 | \ ' }', |
| 772 | \ '}', |
| 773 | \ ]) |
| 774 | setfiletype c |
| 775 | syntax on |
| 776 | set foldmethod=syntax |
| 777 | |
Bram Moolenaar | e2e4075 | 2020-09-04 21:18:46 +0200 | [diff] [blame] | 778 | call assert_fails('syn foldlevel start start', 'E390:') |
| 779 | call assert_fails('syn foldlevel not_an_option', 'E390:') |
Bram Moolenaar | e35a52a | 2020-05-31 19:48:53 +0200 | [diff] [blame] | 780 | |
| 781 | set foldlevel=1 |
| 782 | |
| 783 | syn foldlevel start |
| 784 | redir @c |
| 785 | syn foldlevel |
| 786 | redir END |
| 787 | call assert_equal("\nsyntax foldlevel start", @c) |
| 788 | syn sync fromstart |
Bram Moolenaar | 9950280 | 2020-11-18 16:53:23 +0100 | [diff] [blame] | 789 | call assert_match('from the first line$', execute('syn sync')) |
Bram Moolenaar | e35a52a | 2020-05-31 19:48:53 +0200 | [diff] [blame] | 790 | let a = map(range(3,9), 'foldclosed(v:val)') |
| 791 | call assert_equal([3,3,3,3,3,3,3], a) " attached cascade folds together |
| 792 | let a = map(range(10,15), 'foldclosed(v:val)') |
| 793 | call assert_equal([10,10,10,10,10,10], a) " over-attached 'else' hidden |
| 794 | let a = map(range(16,27), 'foldclosed(v:val)') |
| 795 | let unattached_results = [-1,17,17,17,-1,21,21,21,-1,25,25,25] |
| 796 | call assert_equal(unattached_results, a) " unattached cascade folds separately |
| 797 | |
| 798 | syn foldlevel minimum |
| 799 | redir @c |
| 800 | syn foldlevel |
| 801 | redir END |
| 802 | call assert_equal("\nsyntax foldlevel minimum", @c) |
| 803 | syn sync fromstart |
| 804 | let a = map(range(3,9), 'foldclosed(v:val)') |
| 805 | call assert_equal([3,3,5,5,7,7,7], a) " attached cascade folds separately |
| 806 | let a = map(range(10,15), 'foldclosed(v:val)') |
| 807 | call assert_equal([10,10,10,13,13,13], a) " over-attached 'else' visible |
| 808 | let a = map(range(16,27), 'foldclosed(v:val)') |
| 809 | call assert_equal(unattached_results, a) " unattached cascade folds separately |
| 810 | |
| 811 | set foldlevel=2 |
| 812 | |
| 813 | syn foldlevel start |
| 814 | syn sync fromstart |
| 815 | let a = map(range(11,14), 'foldclosed(v:val)') |
| 816 | call assert_equal([11,11,11,-1], a) " over-attached 'else' hidden |
| 817 | |
| 818 | syn foldlevel minimum |
| 819 | syn sync fromstart |
| 820 | let a = map(range(11,14), 'foldclosed(v:val)') |
| 821 | call assert_equal([11,11,-1,-1], a) " over-attached 'else' visible |
| 822 | |
| 823 | quit! |
| 824 | endfunc |
| 825 | |
Bram Moolenaar | adc17a5 | 2020-06-06 18:37:51 +0200 | [diff] [blame] | 826 | func Test_search_syntax_skip() |
| 827 | new |
| 828 | let lines =<< trim END |
| 829 | |
| 830 | /* This is VIM */ |
| 831 | Another Text for VIM |
| 832 | let a = "VIM" |
| 833 | END |
| 834 | call setline(1, lines) |
| 835 | syntax on |
| 836 | syntax match Comment "^/\*.*\*/" |
| 837 | syntax match String '".*"' |
| 838 | |
| 839 | " Skip argument using string evaluation. |
| 840 | 1 |
| 841 | call search('VIM', 'w', '', 0, 'synIDattr(synID(line("."), col("."), 1), "name") =~? "comment"') |
| 842 | call assert_equal('Another Text for VIM', getline('.')) |
| 843 | 1 |
| 844 | call search('VIM', 'w', '', 0, 'synIDattr(synID(line("."), col("."), 1), "name") !~? "string"') |
| 845 | call assert_equal(' let a = "VIM"', getline('.')) |
| 846 | |
| 847 | " Skip argument using Lambda. |
| 848 | 1 |
| 849 | call search('VIM', 'w', '', 0, { -> synIDattr(synID(line("."), col("."), 1), "name") =~? "comment"}) |
| 850 | call assert_equal('Another Text for VIM', getline('.')) |
| 851 | |
| 852 | 1 |
| 853 | call search('VIM', 'w', '', 0, { -> synIDattr(synID(line("."), col("."), 1), "name") !~? "string"}) |
| 854 | call assert_equal(' let a = "VIM"', getline('.')) |
| 855 | |
| 856 | " Skip argument using funcref. |
| 857 | func InComment() |
| 858 | return synIDattr(synID(line("."), col("."), 1), "name") =~? "comment" |
| 859 | endfunc |
| 860 | func InString() |
| 861 | return synIDattr(synID(line("."), col("."), 1), "name") !~? "string" |
| 862 | endfunc |
| 863 | 1 |
| 864 | call search('VIM', 'w', '', 0, function('InComment')) |
| 865 | call assert_equal('Another Text for VIM', getline('.')) |
| 866 | |
| 867 | 1 |
| 868 | call search('VIM', 'w', '', 0, function('InString')) |
| 869 | call assert_equal(' let a = "VIM"', getline('.')) |
| 870 | |
| 871 | delfunc InComment |
| 872 | delfunc InString |
| 873 | bwipe! |
| 874 | endfunc |
| 875 | |
Bram Moolenaar | b46f57e | 2020-11-29 14:11:41 +0100 | [diff] [blame] | 876 | func Test_syn_contained_transparent() |
| 877 | " Comments starting with "Regression:" show the result when the highlighting |
| 878 | " span of the containing item is assigned to the contained region. |
| 879 | syntax on |
| 880 | |
| 881 | let l:case = "Transparent region contained in region" |
| 882 | new |
| 883 | syntax region X start=/\[/ end=/\]/ contained transparent |
| 884 | syntax region Y start=/(/ end=/)/ contains=X |
| 885 | |
| 886 | call setline(1, "==(--[~~]--)==") |
| 887 | let l:expected = " YYYYYYYYYY " |
| 888 | eval AssertHighlightGroups(1, 1, l:expected, 1, l:case) |
| 889 | syntax clear Y X |
| 890 | bw! |
| 891 | |
| 892 | let l:case = "Transparent region extends region" |
| 893 | new |
| 894 | syntax region X start=/\[/ end=/\]/ contained transparent |
| 895 | syntax region Y start=/(/ end=/)/ end=/e/ contains=X |
| 896 | |
| 897 | call setline(1, "==(--[~~e~~]--)==") |
| 898 | let l:expected = " YYYYYYYYYYYYY " |
| 899 | " Regression: " YYYYYYY YYY " |
| 900 | eval AssertHighlightGroups(1, 1, l:expected, 1, l:case) |
| 901 | syntax clear Y X |
| 902 | bw! |
| 903 | |
| 904 | let l:case = "Nested transparent regions extend region" |
| 905 | new |
| 906 | syntax region X start=/\[/ end=/\]/ contained transparent |
| 907 | syntax region Y start=/(/ end=/)/ end=/e/ contains=X |
| 908 | |
| 909 | call setline(1, "==(--[~~e~~[~~e~~]~~e~~]--)==") |
| 910 | let l:expected = " YYYYYYYYYYYYYYYYYYYYYYYYY " |
| 911 | " Regression: " YYYYYYY YYYYYYYYY " |
| 912 | eval AssertHighlightGroups(1, 1, l:expected, 1, l:case) |
| 913 | syntax clear Y X |
| 914 | bw! |
| 915 | |
| 916 | let l:case = "Transparent region contained in match" |
| 917 | new |
| 918 | syntax region X start=/\[/ end=/\]/ contained transparent |
| 919 | syntax match Y /(.\{-})/ contains=X |
| 920 | |
| 921 | call setline(1, "==(--[~~]--)==") |
| 922 | let l:expected = " YYYYYYYYYY " |
| 923 | eval AssertHighlightGroups(1, 1, l:expected, 1, l:case) |
| 924 | syntax clear Y X |
| 925 | bw! |
| 926 | |
| 927 | let l:case = "Transparent region extends match" |
| 928 | new |
| 929 | syntax region X start=/\[/ end=/\]/ contained transparent |
| 930 | syntax match Y /(.\{-}[e)]/ contains=X |
| 931 | |
| 932 | call setline(1, "==(--[~~e~~]--)==") |
| 933 | let l:expected = " YYYYYYYYYY " |
| 934 | " Regression: " YYYYYYY " |
| 935 | eval AssertHighlightGroups(1, 1, l:expected, 1, l:case) |
| 936 | syntax clear Y X |
| 937 | bw! |
| 938 | |
| 939 | let l:case = "Nested transparent regions extend match" |
| 940 | new |
| 941 | syntax region X start=/\[/ end=/\]/ contained transparent |
| 942 | syntax match Y /(.\{-}[e)]/ contains=X |
| 943 | |
| 944 | call setline(1, "==(--[~~e~~[~~e~~]~~e~~]--)==") |
| 945 | let l:expected = " YYYYYYYYYYYYYYYYYYYYYY " |
| 946 | " Regression: " YYYYYYY YYYYYY " |
| 947 | eval AssertHighlightGroups(1, 1, l:expected, 1, l:case) |
| 948 | syntax clear Y X |
| 949 | bw! |
| 950 | endfunc |
| 951 | |
Bram Moolenaar | 2e240bd | 2021-04-14 11:15:08 +0200 | [diff] [blame] | 952 | func Test_syn_include_contains_TOP() |
| 953 | let l:case = "TOP in included syntax means its group list name" |
| 954 | new |
| 955 | syntax include @INCLUDED syntax/c.vim |
| 956 | syntax region FencedCodeBlockC start=/```c/ end=/```/ contains=@INCLUDED |
| 957 | |
| 958 | call setline(1, ['```c', '#if 0', 'int', '#else', 'int', '#endif', '```' ]) |
| 959 | let l:expected = ["cCppOutIf2"] |
| 960 | eval AssertHighlightGroups(3, 1, l:expected, 1) |
| 961 | " cCppOutElse has contains=TOP |
| 962 | let l:expected = ["cType"] |
| 963 | eval AssertHighlightGroups(5, 1, l:expected, 1, l:case) |
| 964 | syntax clear |
| 965 | bw! |
| 966 | endfunc |
| 967 | |
zeertzjq | ca7e86c | 2022-04-16 16:49:24 +0100 | [diff] [blame] | 968 | " This was using freed memory |
| 969 | func Test_WinEnter_synstack_synID() |
| 970 | autocmd WinEnter * call synstack(line("."), col(".")) |
| 971 | autocmd WinEnter * call synID(line('.'), col('.') - 1, 1) |
| 972 | call setline(1, 'aaaaa') |
| 973 | normal! $ |
| 974 | new |
| 975 | close |
| 976 | |
| 977 | au! WinEnter |
| 978 | bw! |
| 979 | endfunc |
| 980 | |
Bram Moolenaar | 2e240bd | 2021-04-14 11:15:08 +0200 | [diff] [blame] | 981 | |
Bram Moolenaar | 0e05de4 | 2020-03-25 22:23:46 +0100 | [diff] [blame] | 982 | " vim: shiftwidth=2 sts=2 expandtab |