test_syntax.vim 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989
  1. " Test for syntax and syntax iskeyword option
  2. source check.vim
  3. CheckFeature syntax
  4. source view_util.vim
  5. source screendump.vim
  6. func GetSyntaxItem(pat)
  7. let c = ''
  8. let a = ['a', getreg('a'), getregtype('a')]
  9. 0
  10. redraw!
  11. call search(a:pat, 'W')
  12. let synid = synID(line('.'), col('.'), 1)
  13. while synid == synID(line('.'), col('.'), 1)
  14. norm! v"ay
  15. " stop at whitespace
  16. if @a =~# '\s'
  17. break
  18. endif
  19. let c .= @a
  20. norm! l
  21. endw
  22. call call('setreg', a)
  23. 0
  24. return c
  25. endfunc
  26. func AssertHighlightGroups(lnum, startcol, expected, trans = 1, msg = "")
  27. " Assert that the characters starting at a given (line, col)
  28. " sequentially match the expected highlight groups.
  29. " If groups are provided as a string, each character is assumed to be a
  30. " group and spaces represent no group, useful for visually describing tests.
  31. let l:expectedGroups = type(a:expected) == v:t_string
  32. \ ? a:expected->split('\zs')->map({_, v -> trim(v)})
  33. \ : a:expected
  34. let l:errors = 0
  35. let l:msg = (a:msg->empty() ? "" : a:msg .. ": ")
  36. \ .. "Wrong highlight group at " .. a:lnum .. ","
  37. for l:i in range(a:startcol, a:startcol + l:expectedGroups->len() - 1)
  38. let l:errors += synID(a:lnum, l:i, a:trans)
  39. \ ->synIDattr("name")
  40. \ ->assert_equal(l:expectedGroups[l:i - 1],
  41. \ l:msg .. l:i)
  42. endfor
  43. endfunc
  44. func Test_syn_iskeyword()
  45. new
  46. call setline(1, [
  47. \ 'CREATE TABLE FOOBAR(',
  48. \ ' DLTD_BY VARCHAR2(100)',
  49. \ ');',
  50. \ ''])
  51. syntax on
  52. set ft=sql
  53. syn match SYN /C\k\+\>/
  54. hi link SYN ErrorMsg
  55. call assert_equal('DLTD_BY', GetSyntaxItem('DLTD'))
  56. /\<D\k\+\>/:norm! ygn
  57. call assert_equal('DLTD_BY', @0)
  58. redir @c
  59. syn iskeyword
  60. redir END
  61. call assert_equal("\nsyntax iskeyword not set", @c)
  62. syn iskeyword @,48-57,_,192-255
  63. redir @c
  64. syn iskeyword
  65. redir END
  66. call assert_equal("\nsyntax iskeyword @,48-57,_,192-255", @c)
  67. setlocal isk-=_
  68. call assert_equal('DLTD_BY', GetSyntaxItem('DLTD'))
  69. /\<D\k\+\>/:norm! ygn
  70. let b2 = @0
  71. call assert_equal('DLTD', @0)
  72. syn iskeyword clear
  73. redir @c
  74. syn iskeyword
  75. redir END
  76. call assert_equal("\nsyntax iskeyword not set", @c)
  77. quit!
  78. endfunc
  79. func Test_syntax_after_reload()
  80. split Xsomefile
  81. call setline(1, ['hello', 'there'])
  82. w!
  83. only!
  84. setl filetype=hello
  85. au FileType hello let g:gotit = 1
  86. call assert_false(exists('g:gotit'))
  87. edit other
  88. buf Xsomefile
  89. call assert_equal('hello', &filetype)
  90. call assert_true(exists('g:gotit'))
  91. call delete('Xsomefile')
  92. endfunc
  93. func Test_syntime()
  94. if !has('profile')
  95. return
  96. endif
  97. syntax on
  98. syntime on
  99. let a = execute('syntime report')
  100. call assert_equal("\nNo Syntax items defined for this buffer", a)
  101. let a = execute('syntime clear')
  102. call assert_equal("\nNo Syntax items defined for this buffer", a)
  103. view ../memfile_test.c
  104. setfiletype cpp
  105. redraw
  106. let a = execute('syntime report')
  107. call assert_match('^ TOTAL *COUNT *MATCH *SLOWEST *AVERAGE *NAME *PATTERN', a)
  108. call assert_match(' \d*\.\d* \+[^0]\d* .* cppRawString ', a)
  109. call assert_match(' \d*\.\d* \+[^0]\d* .* cppNumber ', a)
  110. syntime off
  111. syntime clear
  112. let a = execute('syntime report')
  113. call assert_match('^ TOTAL *COUNT *MATCH *SLOWEST *AVERAGE *NAME *PATTERN', a)
  114. call assert_notmatch('.* cppRawString *', a)
  115. call assert_notmatch('.* cppNumber*', a)
  116. call assert_notmatch('[1-9]', a)
  117. call assert_fails('syntime abc', 'E475')
  118. syntax clear
  119. let a = execute('syntime report')
  120. call assert_equal("\nNo Syntax items defined for this buffer", a)
  121. bd
  122. endfunc
  123. func Test_syntime_completion()
  124. if !has('profile')
  125. return
  126. endif
  127. call feedkeys(":syntime \<C-A>\<C-B>\"\<CR>", 'tx')
  128. call assert_equal('"syntime clear off on report', @:)
  129. endfunc
  130. func Test_syntax_list()
  131. syntax on
  132. let a = execute('syntax list')
  133. call assert_equal("\nNo Syntax items defined for this buffer", a)
  134. view ../memfile_test.c
  135. setfiletype c
  136. let a = execute('syntax list')
  137. call assert_match('cInclude*', a)
  138. call assert_match('cDefine', a)
  139. let a = execute('syntax list cDefine')
  140. call assert_notmatch('cInclude*', a)
  141. call assert_match('cDefine', a)
  142. call assert_match(' links to Macro$', a)
  143. call assert_fails('syntax list ABCD', 'E28:')
  144. call assert_fails('syntax list @ABCD', 'E392:')
  145. syntax clear
  146. let a = execute('syntax list')
  147. call assert_equal("\nNo Syntax items defined for this buffer", a)
  148. syntax keyword Type int containedin=g1 skipwhite skipempty skipnl nextgroup=Abc
  149. let exp = "Type xxx containedin=g1 nextgroup=Abc skipnl skipwhite skipempty int"
  150. call assert_equal(exp, split(execute("syntax list"), "\n")[1])
  151. bd
  152. endfunc
  153. func Test_syntax_completion()
  154. call feedkeys(":syn \<C-A>\<C-B>\"\<CR>", 'tx')
  155. call assert_equal('"syn case clear cluster conceal enable foldlevel include iskeyword keyword list manual match off on region reset spell sync', @:)
  156. call feedkeys(":syn case \<C-A>\<C-B>\"\<CR>", 'tx')
  157. call assert_equal('"syn case ignore match', @:)
  158. call feedkeys(":syn spell \<C-A>\<C-B>\"\<CR>", 'tx')
  159. call assert_equal('"syn spell default notoplevel toplevel', @:)
  160. call feedkeys(":syn sync \<C-A>\<C-B>\"\<CR>", 'tx')
  161. call assert_equal('"syn sync ccomment clear fromstart linebreaks= linecont lines= match maxlines= minlines= region', @:)
  162. " Check that clearing "Aap" avoids it showing up before Boolean.
  163. hi @Aap ctermfg=blue
  164. call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx')
  165. call assert_match('^"syn list @Aap @attribute @attribute.builtin @boolean @character ', @:)
  166. hi clear @Aap
  167. call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx')
  168. call assert_match('^"syn list @attribute @attribute.builtin @boolean @character ', @:)
  169. call feedkeys(":syn match \<C-A>\<C-B>\"\<CR>", 'tx')
  170. call assert_match('^"syn match @attribute @attribute.builtin @boolean @character ', @:)
  171. syn cluster Aax contains=Aap
  172. call feedkeys(":syn list @A\<C-A>\<C-B>\"\<CR>", 'tx')
  173. call assert_match('^"syn list @Aax', @:)
  174. endfunc
  175. func Test_echohl_completion()
  176. call feedkeys(":echohl no\<C-A>\<C-B>\"\<CR>", 'tx')
  177. " call assert_equal('"echohl NonText Normal none', @:)
  178. call assert_equal('"echohl NonText Normal NormalFloat NormalNC none', @:)
  179. endfunc
  180. func Test_syntax_arg_skipped()
  181. syn clear
  182. syntax case ignore
  183. if 0
  184. syntax case match
  185. endif
  186. call assert_match('case ignore', execute('syntax case'))
  187. syn keyword Foo foo
  188. call assert_match('Foo', execute('syntax'))
  189. syn clear
  190. call assert_match('case match', execute('syntax case'))
  191. call assert_notmatch('Foo', execute('syntax'))
  192. if has('conceal')
  193. syn clear
  194. syntax conceal on
  195. if 0
  196. syntax conceal off
  197. endif
  198. call assert_match('conceal on', execute('syntax conceal'))
  199. syn clear
  200. call assert_match('conceal off', execute('syntax conceal'))
  201. endif
  202. syntax conceal on
  203. syntax conceal off
  204. call assert_match('conceal off', execute('syntax conceal'))
  205. syntax region Bar start=/</ end=/>/
  206. if 0
  207. syntax region NotTest start=/</ end=/>/ contains=@Spell
  208. endif
  209. call assert_match('Bar', execute('syntax'))
  210. call assert_notmatch('NotTest', execute('syntax'))
  211. call assert_notmatch('Spell', execute('syntax'))
  212. hi Foo ctermfg=blue
  213. let a = execute('hi Foo')
  214. if 0
  215. syntax rest
  216. endif
  217. call assert_equal(a, execute('hi Foo'))
  218. hi clear Bar
  219. hi clear Foo
  220. set ft=tags
  221. syn off
  222. if 0
  223. syntax enable
  224. endif
  225. call assert_match('No Syntax items defined', execute('syntax'))
  226. syntax enable
  227. call assert_match('tagComment', execute('syntax'))
  228. set ft=
  229. syn clear
  230. if 0
  231. syntax include @Spell nothing
  232. endif
  233. call assert_notmatch('Spell', execute('syntax'))
  234. syn clear
  235. syn iskeyword 48-57,$,_
  236. call assert_match('48-57,$,_', execute('syntax iskeyword'))
  237. if 0
  238. syn clear
  239. syn iskeyword clear
  240. endif
  241. call assert_match('48-57,$,_', execute('syntax iskeyword'))
  242. syn iskeyword clear
  243. call assert_match('not set', execute('syntax iskeyword'))
  244. syn iskeyword 48-57,$,_
  245. syn clear
  246. call assert_match('not set', execute('syntax iskeyword'))
  247. syn clear
  248. syn keyword Foo foo
  249. if 0
  250. syn keyword NotAdded bar
  251. endif
  252. call assert_match('Foo', execute('syntax'))
  253. call assert_notmatch('NotAdded', execute('highlight'))
  254. syn clear
  255. syn keyword Foo foo
  256. call assert_match('Foo', execute('syntax'))
  257. call assert_match('Foo', execute('syntax list'))
  258. call assert_notmatch('Foo', execute('if 0 | syntax | endif'))
  259. call assert_notmatch('Foo', execute('if 0 | syntax list | endif'))
  260. syn clear
  261. syn match Fopi /asdf/
  262. if 0
  263. syn match Fopx /asdf/
  264. endif
  265. call assert_match('Fopi', execute('syntax'))
  266. call assert_notmatch('Fopx', execute('syntax'))
  267. syn clear
  268. syn spell toplevel
  269. call assert_match('spell toplevel', execute('syntax spell'))
  270. if 0
  271. syn spell notoplevel
  272. endif
  273. call assert_match('spell toplevel', execute('syntax spell'))
  274. syn spell notoplevel
  275. call assert_match('spell notoplevel', execute('syntax spell'))
  276. syn spell default
  277. call assert_match('spell default', execute('syntax spell'))
  278. syn clear
  279. if 0
  280. syntax cluster Spell
  281. endif
  282. call assert_notmatch('Spell', execute('syntax'))
  283. syn clear
  284. syn keyword Foo foo
  285. syn sync ccomment
  286. syn sync maxlines=5
  287. if 0
  288. syn sync maxlines=11
  289. endif
  290. call assert_match('on C-style comments', execute('syntax sync'))
  291. call assert_match('maximal 5 lines', execute('syntax sync'))
  292. syn sync clear
  293. if 0
  294. syn sync ccomment
  295. endif
  296. call assert_notmatch('on C-style comments', execute('syntax sync'))
  297. syn sync fromstart
  298. call assert_match('syncing starts at the first line', execute('syntax sync'))
  299. syn clear
  300. endfunc
  301. " Check for an error. Used when multiple errors are thrown and we are checking
  302. " for an earliest error.
  303. func AssertFails(cmd, errcode)
  304. let save_exception = ''
  305. try
  306. exe a:cmd
  307. catch
  308. let save_exception = v:exception
  309. endtry
  310. call assert_match(a:errcode, save_exception)
  311. endfunc
  312. func Test_syntax_invalid_arg()
  313. call assert_fails('syntax case asdf', 'E390:')
  314. if has('conceal')
  315. call assert_fails('syntax conceal asdf', 'E390:')
  316. endif
  317. call assert_fails('syntax spell asdf', 'E390:')
  318. call assert_fails('syntax clear @ABCD', 'E391:')
  319. call assert_fails('syntax include random_file', 'E484:')
  320. call assert_fails('syntax include <afile>', 'E495:')
  321. call assert_fails('syntax sync x', 'E404:')
  322. call assert_fails('syntax keyword Abc a[', 'E789:')
  323. call assert_fails('syntax keyword Abc a[bc]d', 'E890:')
  324. call assert_fails('syntax cluster Abc add=A add=', 'E406:')
  325. " Test for too many \z\( and unmatched \z\(
  326. " Not able to use assert_fails() here because both E50:/E879: and E475:
  327. " messages are emitted.
  328. set regexpengine=1
  329. call AssertFails("syntax region MyRegion start='\\z\\(' end='\\*/'", 'E52:')
  330. let cmd = "syntax region MyRegion start='"
  331. let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'"
  332. call AssertFails(cmd, 'E50:')
  333. set regexpengine=2
  334. call AssertFails("syntax region MyRegion start='\\z\\(' end='\\*/'", 'E54:')
  335. let cmd = "syntax region MyRegion start='"
  336. let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'"
  337. call AssertFails(cmd, 'E879:')
  338. set regexpengine&
  339. call AssertFails('syntax keyword cMyItem grouphere G1', 'E393:')
  340. call AssertFails('syntax sync match Abc grouphere MyItem "abc"', 'E394:')
  341. call AssertFails('syn keyword Type contains int', 'E395:')
  342. call assert_fails('syntax include @Xxx', 'E397:')
  343. call AssertFails('syntax region X start', 'E398:')
  344. call assert_fails('syntax region X start="{"', 'E399:')
  345. call AssertFails('syntax cluster contains=Abc', 'E400:')
  346. call AssertFails("syntax match Character /'.'", 'E401:')
  347. call AssertFails("syntax match Character /'.'/a", 'E402:')
  348. call assert_fails('syntax sync linecont /\%(/', 'E53:')
  349. call assert_fails('syntax sync linecont /pat', 'E404:')
  350. call assert_fails('syntax sync linecont', 'E404:')
  351. call assert_fails('syntax sync linecont /pat1/ linecont /pat2/', 'E403:')
  352. call assert_fails('syntax sync minlines=a', 'E404:')
  353. call AssertFails('syntax match ABC /x/ contains=', 'E406:')
  354. call AssertFails("syntax match Character contains /'.'/", 'E405:')
  355. call AssertFails('syntax match ccFoo "Foo" nextgroup=ALLBUT,F', 'E407:')
  356. call AssertFails('syntax region Block start="{" contains=F,ALLBUT', 'E408:')
  357. call AssertFails("syntax match Characters contains=a.*x /'.'/", 'E409:')
  358. call assert_fails('syntax match Search /abc/ contains=ALLBUT,/\%(/', 'E53:')
  359. endfunc
  360. func Test_syn_sync()
  361. syntax region HereGroup start=/this/ end=/that/
  362. syntax sync match SyncHere grouphere HereGroup "pattern"
  363. call assert_match('SyncHere', execute('syntax sync'))
  364. syn sync clear
  365. call assert_notmatch('SyncHere', execute('syntax sync'))
  366. syn clear
  367. endfunc
  368. func Test_syn_clear()
  369. syntax keyword Foo foo
  370. syntax keyword Bar tar
  371. call assert_match('Foo', execute('syntax'))
  372. call assert_match('Bar', execute('syntax'))
  373. call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
  374. syn clear Foo
  375. call assert_notmatch('Foo', execute('syntax'))
  376. call assert_match('Bar', execute('syntax'))
  377. call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
  378. syn clear Foo Bar
  379. call assert_notmatch('Foo', execute('syntax'))
  380. call assert_notmatch('Bar', execute('syntax'))
  381. hi clear Foo
  382. call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
  383. hi clear Bar
  384. call assert_fails('syntax clear invalid_syngroup', 'E28:')
  385. endfunc
  386. func Test_invalid_name()
  387. syn clear
  388. syn keyword Nop yes
  389. call assert_fails("syntax keyword Wr\x17ong bar", 'E669:')
  390. syntax keyword @Wrong bar
  391. call assert_fails("syntax keyword @#Wrong bar", 'E5248:')
  392. syn clear
  393. hi clear Nop
  394. hi clear @Wrong
  395. endfunc
  396. func Test_ownsyntax()
  397. new XfooOwnSyntax
  398. call setline(1, '#define FOO')
  399. syntax on
  400. set filetype=c
  401. ownsyntax perl
  402. " this should not crash
  403. set
  404. call assert_equal('perlComment', synIDattr(synID(line('.'), col('.'), 1), 'name'))
  405. call assert_equal('c', b:current_syntax)
  406. call assert_equal('perl', w:current_syntax)
  407. " A new split window should have the original syntax.
  408. split
  409. call assert_equal('cDefine', synIDattr(synID(line('.'), col('.'), 1), 'name'))
  410. call assert_equal('c', b:current_syntax)
  411. call assert_equal(0, exists('w:current_syntax'))
  412. wincmd x
  413. call assert_equal('perlComment', synIDattr(synID(line("."), col("."), 1), "name"))
  414. syntax off
  415. set filetype&
  416. %bw!
  417. endfunc
  418. func Test_ownsyntax_completion()
  419. call feedkeys(":ownsyntax java\<C-A>\<C-B>\"\<CR>", 'tx')
  420. call assert_equal('"ownsyntax java javacc javascript javascriptreact', @:)
  421. endfunc
  422. func Test_highlight_invalid_arg()
  423. if has('gui_running')
  424. call assert_fails('hi XXX guifg=xxx', 'E254:')
  425. endif
  426. call assert_fails('hi DoesNotExist', 'E411:')
  427. call assert_fails('hi link', 'E412:')
  428. call assert_fails('hi link a', 'E412:')
  429. call assert_fails('hi link a b c', 'E413:')
  430. call assert_fails('hi XXX =', 'E415:')
  431. call assert_fails('hi XXX cterm', 'E416:')
  432. call assert_fails('hi XXX cterm=', 'E417:')
  433. call assert_fails('hi XXX cterm=DoesNotExist', 'E418:')
  434. call assert_fails('hi XXX ctermfg=DoesNotExist', 'E421:')
  435. call assert_fails('hi XXX xxx=White', 'E423:')
  436. endfunc
  437. func Test_conceal()
  438. if !has('conceal')
  439. return
  440. endif
  441. new
  442. call setline(1, ['', '123456'])
  443. syn match test23 "23" conceal cchar=X
  444. syn match test45 "45" conceal
  445. set conceallevel=0
  446. call assert_equal('123456 ', ScreenLines(2, 7)[0])
  447. call assert_equal([[0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
  448. set conceallevel=1
  449. call assert_equal('1X 6 ', ScreenLines(2, 7)[0])
  450. 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)'))
  451. set conceallevel=1
  452. set listchars=conceal:Y
  453. 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)'))
  454. call assert_equal('1XY6 ', ScreenLines(2, 7)[0])
  455. set conceallevel=2
  456. call assert_match('1X6 ', ScreenLines(2, 7)[0])
  457. 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)'))
  458. set conceallevel=3
  459. call assert_match('16 ', ScreenLines(2, 7)[0])
  460. call assert_equal([[0, '', 0], [1, '', 1], [1, '', 1], [1, '', 2], [1, '', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
  461. call AssertFails("syntax match Entity '&amp;' conceal cchar=\<Tab>", 'E844:')
  462. syn clear
  463. set conceallevel&
  464. bw!
  465. endfunc
  466. func Test_bg_detection()
  467. CheckNotGui
  468. " auto-detection of &bg, make sure it isn't set anywhere before this test
  469. hi Normal ctermbg=0
  470. call assert_equal('dark', &bg)
  471. hi Normal ctermbg=4
  472. call assert_equal('dark', &bg)
  473. hi Normal ctermbg=12
  474. call assert_equal('light', &bg)
  475. hi Normal ctermbg=15
  476. call assert_equal('light', &bg)
  477. " manually-set &bg takes precedence over auto-detection
  478. set bg=light
  479. hi Normal ctermbg=4
  480. call assert_equal('light', &bg)
  481. set bg=dark
  482. hi Normal ctermbg=12
  483. call assert_equal('dark', &bg)
  484. hi Normal ctermbg=NONE
  485. endfunc
  486. func Test_syntax_hangs()
  487. if !has('reltime') || !has('float') || !has('syntax')
  488. return
  489. endif
  490. " This pattern takes a long time to match, it should timeout.
  491. new
  492. call setline(1, ['aaa', repeat('abc ', 1000), 'ccc'])
  493. let start = reltime()
  494. set nolazyredraw redrawtime=101
  495. syn match Error /\%#=1a*.*X\@<=b*/
  496. redraw
  497. let elapsed = reltimefloat(reltime(start))
  498. call assert_true(elapsed > 0.1)
  499. call assert_true(elapsed < 1.0)
  500. " second time syntax HL is disabled
  501. let start = reltime()
  502. redraw
  503. let elapsed = reltimefloat(reltime(start))
  504. call assert_true(elapsed < 0.1)
  505. " after CTRL-L the timeout flag is reset
  506. let start = reltime()
  507. exe "normal \<C-L>"
  508. redraw
  509. let elapsed = reltimefloat(reltime(start))
  510. call assert_true(elapsed > 0.1)
  511. call assert_true(elapsed < 1.0)
  512. set redrawtime&
  513. bwipe!
  514. endfunc
  515. func Test_synstack_synIDtrans()
  516. new
  517. setfiletype c
  518. syntax on
  519. call setline(1, ' /* A comment with a TODO */')
  520. call assert_equal([], synstack(1, 1))
  521. norm f/
  522. eval synstack(line("."), col("."))->map('synIDattr(v:val, "name")')->assert_equal(['cComment', 'cCommentStart'])
  523. eval synstack(line("."), col("."))->map('synIDattr(synIDtrans(v:val), "name")')->assert_equal(['Comment', 'Comment'])
  524. norm fA
  525. call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
  526. call assert_equal(['Comment'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
  527. norm fT
  528. call assert_equal(['cComment', 'cTodo'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
  529. call assert_equal(['Comment', 'Todo'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
  530. call assert_fails("let n=synIDtrans([])", 'E745:')
  531. syn clear
  532. bw!
  533. endfunc
  534. " Check highlighting for a small piece of C code with a screen dump.
  535. func Test_syntax_c()
  536. CheckRunVimInTerminal
  537. call writefile([
  538. \ '/* comment line at the top */',
  539. \ 'int main(int argc, char **argv) { // another comment',
  540. \ '#if 0',
  541. \ ' int not_used;',
  542. \ '#else',
  543. \ ' int used;',
  544. \ '#endif',
  545. \ ' printf("Just an example piece of C code\n");',
  546. \ ' return 0x0ff;',
  547. \ '}',
  548. \ "\t\t ",
  549. \ ' static void',
  550. \ 'myFunction(const double count, struct nothing, long there) {',
  551. \ "\t// 123: nothing to endif here",
  552. \ "\tfor (int i = 0; i < count; ++i) {",
  553. \ "\t break;",
  554. \ "\t}",
  555. \ "\tNote: asdf",
  556. \ '}',
  557. \ ], 'Xtest.c', 'D')
  558. " This makes the default for 'background' use "dark", check that the
  559. " response to t_RB corrects it to "light".
  560. let $COLORFGBG = '15;0'
  561. let buf = RunVimInTerminal('Xtest.c', {})
  562. call term_sendkeys(buf, ":syn keyword Search Note\r")
  563. call VerifyScreenDump(buf, 'Test_syntax_c_01', {})
  564. call StopVimInTerminal(buf)
  565. let $COLORFGBG = ''
  566. endfun
  567. " Test \z(...) along with \z1
  568. func Test_syn_zsub()
  569. new
  570. syntax on
  571. call setline(1, 'xxx start foo xxx not end foo xxx end foo xxx')
  572. let l:expected = ' ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ '
  573. for l:re in [0, 1, 2]
  574. " Example taken from :help :syn-ext-match
  575. syntax region Z start="start \z(\I\i*\)" skip="not end \z1" end="end \z1"
  576. eval AssertHighlightGroups(1, 1, l:expected, 1, 'regexp=' .. l:re)
  577. syntax clear Z
  578. endfor
  579. set re&
  580. bw!
  581. endfunc
  582. " Using \z() in a region with NFA failing should not crash.
  583. func Test_syn_wrong_z_one()
  584. new
  585. call setline(1, ['just some text', 'with foo and bar to match with'])
  586. syn region FooBar start="foo\z(.*\)bar" end="\z1"
  587. " call test_override("nfa_fail", 1)
  588. redraw!
  589. redraw!
  590. " call test_override("ALL", 0)
  591. bwipe!
  592. endfunc
  593. func Test_syntax_after_bufdo()
  594. call writefile(['/* aaa comment */'], 'Xaaa.c', 'D')
  595. call writefile(['/* bbb comment */'], 'Xbbb.c', 'D')
  596. call writefile(['/* ccc comment */'], 'Xccc.c', 'D')
  597. call writefile(['/* ddd comment */'], 'Xddd.c', 'D')
  598. let bnr = bufnr('%')
  599. new Xaaa.c
  600. badd Xbbb.c
  601. badd Xccc.c
  602. badd Xddd.c
  603. exe "bwipe " . bnr
  604. let l = []
  605. bufdo call add(l, bufnr('%'))
  606. call assert_equal(4, len(l))
  607. syntax on
  608. " This used to only enable syntax HL in the last buffer.
  609. bufdo tab split
  610. tabrewind
  611. for tab in range(1, 4)
  612. norm fm
  613. call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
  614. tabnext
  615. endfor
  616. bwipe! Xaaa.c
  617. bwipe! Xbbb.c
  618. bwipe! Xccc.c
  619. bwipe! Xddd.c
  620. syntax off
  621. endfunc
  622. func Test_syntax_foldlevel()
  623. new
  624. call setline(1, [
  625. \ 'void f(int a)',
  626. \ '{',
  627. \ ' if (a == 1) {',
  628. \ ' a = 0;',
  629. \ ' } else if (a == 2) {',
  630. \ ' a = 1;',
  631. \ ' } else {',
  632. \ ' a = 2;',
  633. \ ' }',
  634. \ ' if (a > 0) {',
  635. \ ' if (a == 1) {',
  636. \ ' a = 0;',
  637. \ ' } /* missing newline */ } /* end of outer if */ else {',
  638. \ ' a = 1;',
  639. \ ' }',
  640. \ ' if (a == 1)',
  641. \ ' {',
  642. \ ' a = 0;',
  643. \ ' }',
  644. \ ' else if (a == 2)',
  645. \ ' {',
  646. \ ' a = 1;',
  647. \ ' }',
  648. \ ' else',
  649. \ ' {',
  650. \ ' a = 2;',
  651. \ ' }',
  652. \ '}',
  653. \ ])
  654. setfiletype c
  655. syntax on
  656. set foldmethod=syntax
  657. call assert_fails('syn foldlevel start start', 'E390')
  658. call assert_fails('syn foldlevel not_an_option', 'E390')
  659. set foldlevel=1
  660. syn foldlevel start
  661. redir @c
  662. syn foldlevel
  663. redir END
  664. call assert_equal("\nsyntax foldlevel start", @c)
  665. syn sync fromstart
  666. call assert_match('from the first line$', execute('syn sync'))
  667. let a = map(range(3,9), 'foldclosed(v:val)')
  668. call assert_equal([3,3,3,3,3,3,3], a) " attached cascade folds together
  669. let a = map(range(10,15), 'foldclosed(v:val)')
  670. call assert_equal([10,10,10,10,10,10], a) " over-attached 'else' hidden
  671. let a = map(range(16,27), 'foldclosed(v:val)')
  672. let unattached_results = [-1,17,17,17,-1,21,21,21,-1,25,25,25]
  673. call assert_equal(unattached_results, a) " unattached cascade folds separately
  674. syn foldlevel minimum
  675. redir @c
  676. syn foldlevel
  677. redir END
  678. call assert_equal("\nsyntax foldlevel minimum", @c)
  679. syn sync fromstart
  680. let a = map(range(3,9), 'foldclosed(v:val)')
  681. call assert_equal([3,3,5,5,7,7,7], a) " attached cascade folds separately
  682. let a = map(range(10,15), 'foldclosed(v:val)')
  683. call assert_equal([10,10,10,13,13,13], a) " over-attached 'else' visible
  684. let a = map(range(16,27), 'foldclosed(v:val)')
  685. call assert_equal(unattached_results, a) " unattached cascade folds separately
  686. set foldlevel=2
  687. syn foldlevel start
  688. syn sync fromstart
  689. let a = map(range(11,14), 'foldclosed(v:val)')
  690. call assert_equal([11,11,11,-1], a) " over-attached 'else' hidden
  691. syn foldlevel minimum
  692. syn sync fromstart
  693. let a = map(range(11,14), 'foldclosed(v:val)')
  694. call assert_equal([11,11,-1,-1], a) " over-attached 'else' visible
  695. quit!
  696. endfunc
  697. func Test_search_syntax_skip()
  698. new
  699. let lines =<< trim END
  700. /* This is VIM */
  701. Another Text for VIM
  702. let a = "VIM"
  703. END
  704. call setline(1, lines)
  705. syntax on
  706. syntax match Comment "^/\*.*\*/"
  707. syntax match String '".*"'
  708. " Skip argument using string evaluation.
  709. 1
  710. call search('VIM', 'w', '', 0, 'synIDattr(synID(line("."), col("."), 1), "name") =~? "comment"')
  711. call assert_equal('Another Text for VIM', getline('.'))
  712. 1
  713. call search('VIM', 'cw', '', 0, 'synIDattr(synID(line("."), col("."), 1), "name") !~? "string"')
  714. call assert_equal(' let a = "VIM"', getline('.'))
  715. " Skip argument using Lambda.
  716. 1
  717. call search('VIM', 'w', '', 0, { -> synIDattr(synID(line("."), col("."), 1), "name") =~? "comment"})
  718. call assert_equal('Another Text for VIM', getline('.'))
  719. 1
  720. call search('VIM', 'cw', '', 0, { -> synIDattr(synID(line("."), col("."), 1), "name") !~? "string"})
  721. call assert_equal(' let a = "VIM"', getline('.'))
  722. " Skip argument using funcref.
  723. func InComment()
  724. return synIDattr(synID(line("."), col("."), 1), "name") =~? "comment"
  725. endfunc
  726. func NotInString()
  727. return synIDattr(synID(line("."), col("."), 1), "name") !~? "string"
  728. endfunc
  729. 1
  730. call search('VIM', 'w', '', 0, function('InComment'))
  731. call assert_equal('Another Text for VIM', getline('.'))
  732. 1
  733. call search('VIM', 'cw', '', 0, function('NotInString'))
  734. call assert_equal(' let a = "VIM"', getline('.'))
  735. delfunc InComment
  736. delfunc NotInString
  737. bwipe!
  738. endfunc
  739. func Test_syn_contained_transparent()
  740. " Comments starting with "Regression:" show the result when the highlighting
  741. " span of the containing item is assigned to the contained region.
  742. syntax on
  743. let l:case = "Transparent region contained in region"
  744. new
  745. syntax region X start=/\[/ end=/\]/ contained transparent
  746. syntax region Y start=/(/ end=/)/ contains=X
  747. call setline(1, "==(--[~~]--)==")
  748. let l:expected = " YYYYYYYYYY "
  749. eval AssertHighlightGroups(1, 1, l:expected, 1, l:case)
  750. syntax clear Y X
  751. bw!
  752. let l:case = "Transparent region extends region"
  753. new
  754. syntax region X start=/\[/ end=/\]/ contained transparent
  755. syntax region Y start=/(/ end=/)/ end=/e/ contains=X
  756. call setline(1, "==(--[~~e~~]--)==")
  757. let l:expected = " YYYYYYYYYYYYY "
  758. " Regression: " YYYYYYY YYY "
  759. eval AssertHighlightGroups(1, 1, l:expected, 1, l:case)
  760. syntax clear Y X
  761. bw!
  762. let l:case = "Nested transparent regions extend region"
  763. new
  764. syntax region X start=/\[/ end=/\]/ contained transparent
  765. syntax region Y start=/(/ end=/)/ end=/e/ contains=X
  766. call setline(1, "==(--[~~e~~[~~e~~]~~e~~]--)==")
  767. let l:expected = " YYYYYYYYYYYYYYYYYYYYYYYYY "
  768. " Regression: " YYYYYYY YYYYYYYYY "
  769. eval AssertHighlightGroups(1, 1, l:expected, 1, l:case)
  770. syntax clear Y X
  771. bw!
  772. let l:case = "Transparent region contained in match"
  773. new
  774. syntax region X start=/\[/ end=/\]/ contained transparent
  775. syntax match Y /(.\{-})/ contains=X
  776. call setline(1, "==(--[~~]--)==")
  777. let l:expected = " YYYYYYYYYY "
  778. eval AssertHighlightGroups(1, 1, l:expected, 1, l:case)
  779. syntax clear Y X
  780. bw!
  781. let l:case = "Transparent region extends match"
  782. new
  783. syntax region X start=/\[/ end=/\]/ contained transparent
  784. syntax match Y /(.\{-}[e)]/ contains=X
  785. call setline(1, "==(--[~~e~~]--)==")
  786. let l:expected = " YYYYYYYYYY "
  787. " Regression: " YYYYYYY "
  788. eval AssertHighlightGroups(1, 1, l:expected, 1, l:case)
  789. syntax clear Y X
  790. bw!
  791. let l:case = "Nested transparent regions extend match"
  792. new
  793. syntax region X start=/\[/ end=/\]/ contained transparent
  794. syntax match Y /(.\{-}[e)]/ contains=X
  795. call setline(1, "==(--[~~e~~[~~e~~]~~e~~]--)==")
  796. let l:expected = " YYYYYYYYYYYYYYYYYYYYYY "
  797. " Regression: " YYYYYYY YYYYYY "
  798. eval AssertHighlightGroups(1, 1, l:expected, 1, l:case)
  799. syntax clear Y X
  800. bw!
  801. endfunc
  802. func Test_syn_include_contains_TOP()
  803. let l:case = "TOP in included syntax refers to top level of that included syntax"
  804. new
  805. syntax include @INCLUDED syntax/c.vim
  806. syntax region FencedCodeBlockC start=/```c/ end=/```/ contains=@INCLUDED
  807. call setline(1, ['```c', '#if 0', 'int', '#else', 'int', '#endif', '```' ])
  808. let l:expected = ["cCppOutIf2"]
  809. eval AssertHighlightGroups(3, 1, l:expected, 1)
  810. " cCppOutElse has contains=TOP
  811. let l:expected = ["cType"]
  812. eval AssertHighlightGroups(5, 1, l:expected, 1, l:case)
  813. syntax clear
  814. bw!
  815. endfunc
  816. func Test_syn_include_contains_TOP_excluding()
  817. new
  818. syntax include @INCLUDED syntax/c.vim
  819. syntax region FencedCodeBlockC start=/```c/ end=/```/ contains=@INCLUDED
  820. call setline(1, ['```c', '#if 0', 'int', '#else', 'int', '#if', '#endif', '```' ])
  821. let l:expected = ["cCppOutElse", "cConditional"]
  822. eval AssertHighlightGroups(6, 1, l:expected, 1)
  823. syntax clear
  824. bw!
  825. endfunc
  826. " This was using freed memory
  827. func Test_WinEnter_synstack_synID()
  828. autocmd WinEnter * call synstack(line("."), col("."))
  829. autocmd WinEnter * call synID(line('.'), col('.') - 1, 1)
  830. call setline(1, 'aaaaa')
  831. normal! $
  832. new
  833. close
  834. au! WinEnter
  835. bw!
  836. endfunc
  837. " vim: shiftwidth=2 sts=2 expandtab