fold_spec.lua 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local Screen = require('test.functional.ui.screen')
  4. local clear = n.clear
  5. local eq = t.eq
  6. local insert = n.insert
  7. local write_file = t.write_file
  8. local exec_lua = n.exec_lua
  9. local command = n.command
  10. local feed = n.feed
  11. local poke_eventloop = n.poke_eventloop
  12. before_each(clear)
  13. describe('treesitter foldexpr', function()
  14. clear()
  15. before_each(function()
  16. -- open folds to avoid deleting entire folded region
  17. exec_lua([[vim.opt.foldlevel = 9]])
  18. end)
  19. local test_text = [[
  20. void ui_refresh(void)
  21. {
  22. int width = INT_MAX, height = INT_MAX;
  23. bool ext_widgets[kUIExtCount];
  24. for (UIExtension i = 0; (int)i < kUIExtCount; i++) {
  25. ext_widgets[i] = true;
  26. }
  27. bool inclusive = ui_override();
  28. for (size_t i = 0; i < ui_count; i++) {
  29. UI *ui = uis[i];
  30. width = MIN(ui->width, width);
  31. height = MIN(ui->height, height);
  32. foo = BAR(ui->bazaar, bazaar);
  33. for (UIExtension j = 0; (int)j < kUIExtCount; j++) {
  34. ext_widgets[j] &= (ui->ui_ext[j] || inclusive);
  35. }
  36. }
  37. }]]
  38. local function parse(lang)
  39. exec_lua(
  40. ([[vim.treesitter.get_parser(0, %s):parse()]]):format(lang and '"' .. lang .. '"' or 'nil')
  41. )
  42. end
  43. local function get_fold_levels()
  44. return exec_lua(function()
  45. local res = {}
  46. for i = 1, vim.api.nvim_buf_line_count(0) do
  47. res[i] = vim.treesitter.foldexpr(i)
  48. end
  49. return res
  50. end)
  51. end
  52. it('can compute fold levels', function()
  53. insert(test_text)
  54. parse('c')
  55. eq({
  56. [1] = '>1',
  57. [2] = '1',
  58. [3] = '1',
  59. [4] = '1',
  60. [5] = '>2',
  61. [6] = '2',
  62. [7] = '2',
  63. [8] = '1',
  64. [9] = '1',
  65. [10] = '>2',
  66. [11] = '2',
  67. [12] = '2',
  68. [13] = '2',
  69. [14] = '2',
  70. [15] = '>3',
  71. [16] = '3',
  72. [17] = '3',
  73. [18] = '2',
  74. [19] = '1',
  75. }, get_fold_levels())
  76. end)
  77. it('recomputes fold levels after lines are added/removed', function()
  78. insert(test_text)
  79. parse('c')
  80. command('1,2d')
  81. poke_eventloop()
  82. eq({
  83. [1] = '0',
  84. [2] = '0',
  85. [3] = '>1',
  86. [4] = '1',
  87. [5] = '1',
  88. [6] = '0',
  89. [7] = '0',
  90. [8] = '>1',
  91. [9] = '1',
  92. [10] = '1',
  93. [11] = '1',
  94. [12] = '1',
  95. [13] = '>2',
  96. [14] = '2',
  97. [15] = '2',
  98. [16] = '1',
  99. [17] = '0',
  100. }, get_fold_levels())
  101. command('1put!')
  102. poke_eventloop()
  103. eq({
  104. [1] = '>1',
  105. [2] = '1',
  106. [3] = '1',
  107. [4] = '1',
  108. [5] = '>2',
  109. [6] = '2',
  110. [7] = '2',
  111. [8] = '1',
  112. [9] = '1',
  113. [10] = '>2',
  114. [11] = '2',
  115. [12] = '2',
  116. [13] = '2',
  117. [14] = '2',
  118. [15] = '>3',
  119. [16] = '3',
  120. [17] = '3',
  121. [18] = '2',
  122. [19] = '1',
  123. }, get_fold_levels())
  124. end)
  125. it('handles changes close to start/end of folds', function()
  126. insert([[
  127. # h1
  128. t1
  129. # h2
  130. t2]])
  131. exec_lua([[vim.treesitter.query.set('markdown', 'folds', '(section) @fold')]])
  132. parse('markdown')
  133. eq({
  134. [1] = '>1',
  135. [2] = '1',
  136. [3] = '>1',
  137. [4] = '1',
  138. }, get_fold_levels())
  139. feed('2ggo<Esc>')
  140. poke_eventloop()
  141. eq({
  142. [1] = '>1',
  143. [2] = '1',
  144. [3] = '1',
  145. [4] = '>1',
  146. [5] = '1',
  147. }, get_fold_levels())
  148. feed('dd')
  149. poke_eventloop()
  150. eq({
  151. [1] = '>1',
  152. [2] = '1',
  153. [3] = '>1',
  154. [4] = '1',
  155. }, get_fold_levels())
  156. feed('2ggdd')
  157. poke_eventloop()
  158. eq({
  159. [1] = '0',
  160. [2] = '>1',
  161. [3] = '1',
  162. }, get_fold_levels())
  163. feed('u')
  164. poke_eventloop()
  165. eq({
  166. [1] = '>1',
  167. [2] = '1',
  168. [3] = '>1',
  169. [4] = '1',
  170. }, get_fold_levels())
  171. feed('3ggdd')
  172. poke_eventloop()
  173. eq({
  174. [1] = '>1',
  175. [2] = '1',
  176. [3] = '1',
  177. }, get_fold_levels())
  178. feed('u')
  179. poke_eventloop()
  180. eq({
  181. [1] = '>1',
  182. [2] = '1',
  183. [3] = '>1',
  184. [4] = '1',
  185. }, get_fold_levels())
  186. feed('3ggI#<Esc>')
  187. parse()
  188. poke_eventloop()
  189. eq({
  190. [1] = '>1',
  191. [2] = '1',
  192. [3] = '>2',
  193. [4] = '2',
  194. }, get_fold_levels())
  195. feed('x')
  196. parse()
  197. poke_eventloop()
  198. eq({
  199. [1] = '>1',
  200. [2] = '1',
  201. [3] = '>1',
  202. [4] = '1',
  203. }, get_fold_levels())
  204. end)
  205. it('handles changes that trigger multiple on_bytes', function()
  206. insert([[
  207. function f()
  208. asdf()
  209. asdf()
  210. end
  211. -- comment]])
  212. exec_lua(function()
  213. vim.treesitter.query.set(
  214. 'lua',
  215. 'folds',
  216. '[(function_declaration) (parameters) (arguments)] @fold'
  217. )
  218. end)
  219. parse('lua')
  220. eq({
  221. [1] = '>1',
  222. [2] = '1',
  223. [3] = '1',
  224. [4] = '1',
  225. [5] = '0',
  226. }, get_fold_levels())
  227. command('1,4join')
  228. poke_eventloop()
  229. eq({
  230. [1] = '0',
  231. [2] = '0',
  232. }, get_fold_levels())
  233. feed('u')
  234. poke_eventloop()
  235. eq({
  236. [1] = '>1',
  237. [2] = '1',
  238. [3] = '1',
  239. [4] = '1',
  240. [5] = '0',
  241. }, get_fold_levels())
  242. end)
  243. it('handles multiple folds that overlap at the end and start', function()
  244. insert([[
  245. function f()
  246. g(
  247. function()
  248. asdf()
  249. end, function()
  250. end
  251. )
  252. end]])
  253. exec_lua(function()
  254. vim.treesitter.query.set(
  255. 'lua',
  256. 'folds',
  257. '[(function_declaration) (function_definition) (parameters) (arguments)] @fold'
  258. )
  259. end)
  260. parse('lua')
  261. -- If fold1.stop = fold2.start, then move fold1's stop up so that fold2.start gets proper level.
  262. eq({
  263. [1] = '>1',
  264. [2] = '>2',
  265. [3] = '>3',
  266. [4] = '3',
  267. [5] = '>3',
  268. [6] = '3',
  269. [7] = '2',
  270. [8] = '1',
  271. }, get_fold_levels())
  272. command('1,8join')
  273. feed('u')
  274. poke_eventloop()
  275. eq({
  276. [1] = '>1',
  277. [2] = '>2',
  278. [3] = '>3',
  279. [4] = '3',
  280. [5] = '>3',
  281. [6] = '3',
  282. [7] = '2',
  283. [8] = '1',
  284. }, get_fold_levels())
  285. end)
  286. it('handles multiple folds that start at the same line', function()
  287. insert([[
  288. function f(a)
  289. if #(g({
  290. k = v,
  291. })) > 0 then
  292. return
  293. end
  294. end]])
  295. exec_lua(function()
  296. vim.treesitter.query.set(
  297. 'lua',
  298. 'folds',
  299. '[(if_statement) (function_declaration) (parameters) (arguments) (table_constructor)] @fold'
  300. )
  301. end)
  302. parse('lua')
  303. eq({
  304. [1] = '>1',
  305. [2] = '>3',
  306. [3] = '3',
  307. [4] = '3',
  308. [5] = '2',
  309. [6] = '2',
  310. [7] = '1',
  311. }, get_fold_levels())
  312. command('2,6join')
  313. poke_eventloop()
  314. eq({
  315. [1] = '>1',
  316. [2] = '1',
  317. [3] = '1',
  318. }, get_fold_levels())
  319. feed('u')
  320. poke_eventloop()
  321. eq({
  322. [1] = '>1',
  323. [2] = '>3',
  324. [3] = '3',
  325. [4] = '3',
  326. [5] = '2',
  327. [6] = '2',
  328. [7] = '1',
  329. }, get_fold_levels())
  330. end)
  331. it('takes account of relevant options', function()
  332. insert([[
  333. # h1
  334. t1
  335. ## h2
  336. t2
  337. ### h3
  338. t3]])
  339. exec_lua([[vim.treesitter.query.set('markdown', 'folds', '(section) @fold')]])
  340. parse('markdown')
  341. command([[set foldminlines=2]])
  342. eq({
  343. [1] = '>1',
  344. [2] = '1',
  345. [3] = '>2',
  346. [4] = '2',
  347. [5] = '2',
  348. [6] = '2',
  349. }, get_fold_levels())
  350. command([[set foldminlines=1 foldnestmax=1]])
  351. eq({
  352. [1] = '>1',
  353. [2] = '1',
  354. [3] = '1',
  355. [4] = '1',
  356. [5] = '1',
  357. [6] = '1',
  358. }, get_fold_levels())
  359. end)
  360. it('handles quantified patterns', function()
  361. insert([[
  362. -- hello
  363. -- hello
  364. -- hello
  365. -- hello
  366. -- hello
  367. -- hello]])
  368. exec_lua([[vim.treesitter.query.set('lua', 'folds', '(comment)+ @fold')]])
  369. parse('lua')
  370. eq({
  371. [1] = '>1',
  372. [2] = '1',
  373. [3] = '1',
  374. [4] = '1',
  375. [5] = '1',
  376. [6] = '1',
  377. }, get_fold_levels())
  378. end)
  379. it('updates folds in all windows', function()
  380. local screen = Screen.new(60, 48)
  381. screen:set_default_attr_ids({
  382. [1] = { background = Screen.colors.Grey, foreground = Screen.colors.DarkBlue },
  383. [2] = { bold = true, foreground = Screen.colors.Blue1 },
  384. [3] = { bold = true, reverse = true },
  385. [4] = { reverse = true },
  386. })
  387. parse('c')
  388. command([[set foldmethod=expr foldexpr=v:lua.vim.treesitter.foldexpr() foldcolumn=1]])
  389. command('split')
  390. insert(test_text)
  391. screen:expect {
  392. grid = [[
  393. {1:-}void ui_refresh(void) |
  394. {1:│}{ |
  395. {1:│} int width = INT_MAX, height = INT_MAX; |
  396. {1:│} bool ext_widgets[kUIExtCount]; |
  397. {1:-} for (UIExtension i = 0; (int)i < kUIExtCount; i++) { |
  398. {1:2} ext_widgets[i] = true; |
  399. {1:2} } |
  400. {1:│} |
  401. {1:│} bool inclusive = ui_override(); |
  402. {1:-} for (size_t i = 0; i < ui_count; i++) { |
  403. {1:2} UI *ui = uis[i]; |
  404. {1:2} width = MIN(ui->width, width); |
  405. {1:2} height = MIN(ui->height, height); |
  406. {1:2} foo = BAR(ui->bazaar, bazaar); |
  407. {1:-} for (UIExtension j = 0; (int)j < kUIExtCount; j++) { |
  408. {1:3} ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
  409. {1:3} } |
  410. {1:2} } |
  411. {1:│}^} |
  412. {2:~ }|*4
  413. {3:[No Name] [+] }|
  414. {1:-}void ui_refresh(void) |
  415. {1:│}{ |
  416. {1:│} int width = INT_MAX, height = INT_MAX; |
  417. {1:│} bool ext_widgets[kUIExtCount]; |
  418. {1:-} for (UIExtension i = 0; (int)i < kUIExtCount; i++) { |
  419. {1:2} ext_widgets[i] = true; |
  420. {1:2} } |
  421. {1:│} |
  422. {1:│} bool inclusive = ui_override(); |
  423. {1:-} for (size_t i = 0; i < ui_count; i++) { |
  424. {1:2} UI *ui = uis[i]; |
  425. {1:2} width = MIN(ui->width, width); |
  426. {1:2} height = MIN(ui->height, height); |
  427. {1:2} foo = BAR(ui->bazaar, bazaar); |
  428. {1:-} for (UIExtension j = 0; (int)j < kUIExtCount; j++) { |
  429. {1:3} ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
  430. {1:3} } |
  431. {1:2} } |
  432. {1:│}} |
  433. {2:~ }|*3
  434. {4:[No Name] [+] }|
  435. |
  436. ]],
  437. }
  438. command('1,2d')
  439. screen:expect {
  440. grid = [[
  441. {1: } ^int width = INT_MAX, height = INT_MAX; |
  442. {1: } bool ext_widgets[kUIExtCount]; |
  443. {1:-} for (UIExtension i = 0; (int)i < kUIExtCount; i++) { |
  444. {1:│} ext_widgets[i] = true; |
  445. {1:│} } |
  446. {1: } |
  447. {1: } bool inclusive = ui_override(); |
  448. {1:-} for (size_t i = 0; i < ui_count; i++) { |
  449. {1:│} UI *ui = uis[i]; |
  450. {1:│} width = MIN(ui->width, width); |
  451. {1:│} height = MIN(ui->height, height); |
  452. {1:│} foo = BAR(ui->bazaar, bazaar); |
  453. {1:-} for (UIExtension j = 0; (int)j < kUIExtCount; j++) { |
  454. {1:2} ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
  455. {1:2} } |
  456. {1:│} } |
  457. {1: }} |
  458. {2:~ }|*6
  459. {3:[No Name] [+] }|
  460. {1: } int width = INT_MAX, height = INT_MAX; |
  461. {1: } bool ext_widgets[kUIExtCount]; |
  462. {1:-} for (UIExtension i = 0; (int)i < kUIExtCount; i++) { |
  463. {1:│} ext_widgets[i] = true; |
  464. {1:│} } |
  465. {1: } |
  466. {1: } bool inclusive = ui_override(); |
  467. {1:-} for (size_t i = 0; i < ui_count; i++) { |
  468. {1:│} UI *ui = uis[i]; |
  469. {1:│} width = MIN(ui->width, width); |
  470. {1:│} height = MIN(ui->height, height); |
  471. {1:│} foo = BAR(ui->bazaar, bazaar); |
  472. {1:-} for (UIExtension j = 0; (int)j < kUIExtCount; j++) { |
  473. {1:2} ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
  474. {1:2} } |
  475. {1:│} } |
  476. {1: }} |
  477. {2:~ }|*5
  478. {4:[No Name] [+] }|
  479. |
  480. ]],
  481. }
  482. feed([[O<C-u><C-r>"<BS><Esc>]])
  483. screen:expect {
  484. grid = [[
  485. {1:-}void ui_refresh(void) |
  486. {1:│}^{ |
  487. {1:│} int width = INT_MAX, height = INT_MAX; |
  488. {1:│} bool ext_widgets[kUIExtCount]; |
  489. {1:-} for (UIExtension i = 0; (int)i < kUIExtCount; i++) { |
  490. {1:2} ext_widgets[i] = true; |
  491. {1:2} } |
  492. {1:│} |
  493. {1:│} bool inclusive = ui_override(); |
  494. {1:-} for (size_t i = 0; i < ui_count; i++) { |
  495. {1:2} UI *ui = uis[i]; |
  496. {1:2} width = MIN(ui->width, width); |
  497. {1:2} height = MIN(ui->height, height); |
  498. {1:2} foo = BAR(ui->bazaar, bazaar); |
  499. {1:-} for (UIExtension j = 0; (int)j < kUIExtCount; j++) { |
  500. {1:3} ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
  501. {1:3} } |
  502. {1:2} } |
  503. {1:│}} |
  504. {2:~ }|*4
  505. {3:[No Name] [+] }|
  506. {1:-}void ui_refresh(void) |
  507. {1:│}{ |
  508. {1:│} int width = INT_MAX, height = INT_MAX; |
  509. {1:│} bool ext_widgets[kUIExtCount]; |
  510. {1:-} for (UIExtension i = 0; (int)i < kUIExtCount; i++) { |
  511. {1:2} ext_widgets[i] = true; |
  512. {1:2} } |
  513. {1:│} |
  514. {1:│} bool inclusive = ui_override(); |
  515. {1:-} for (size_t i = 0; i < ui_count; i++) { |
  516. {1:2} UI *ui = uis[i]; |
  517. {1:2} width = MIN(ui->width, width); |
  518. {1:2} height = MIN(ui->height, height); |
  519. {1:2} foo = BAR(ui->bazaar, bazaar); |
  520. {1:-} for (UIExtension j = 0; (int)j < kUIExtCount; j++) { |
  521. {1:3} ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
  522. {1:3} } |
  523. {1:2} } |
  524. {1:│}} |
  525. {2:~ }|*3
  526. {4:[No Name] [+] }|
  527. |
  528. ]],
  529. }
  530. end)
  531. it("doesn't open folds in diff mode", function()
  532. local screen = Screen.new(60, 36)
  533. parse('c')
  534. command(
  535. [[set foldmethod=expr foldexpr=v:lua.vim.treesitter.foldexpr() foldcolumn=1 foldlevel=9]]
  536. )
  537. insert(test_text)
  538. command('16d')
  539. command('new')
  540. insert(test_text)
  541. command('windo diffthis')
  542. feed('do')
  543. screen:expect {
  544. grid = [[
  545. {1:+ }{2:+-- 9 lines: void ui_refresh(void)·······················}|
  546. {1: } for (size_t i = 0; i < ui_count; i++) { |
  547. {1: } UI *ui = uis[i]; |
  548. {1: } width = MIN(ui->width, width); |
  549. {1: } height = MIN(ui->height, height); |
  550. {1: } foo = BAR(ui->bazaar, bazaar); |
  551. {1: } for (UIExtension j = 0; (int)j < kUIExtCount; j++) { |
  552. {1: } ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
  553. {1: } } |
  554. {1: } } |
  555. {1: }} |
  556. {3:~ }|*6
  557. {4:[No Name] [+] }|
  558. {1:+ }{2:+-- 9 lines: void ui_refresh(void)·······················}|
  559. {1: } for (size_t i = 0; i < ui_count; i++) { |
  560. {1: } UI *ui = uis[i]; |
  561. {1: } width = MIN(ui->width, width); |
  562. {1: } height = MIN(ui->height, height); |
  563. {1: } foo = BAR(ui->bazaar, bazaar); |
  564. {1: } for (UIExtension j = 0; (int)j < kUIExtCount; j++) { |
  565. {1: } ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
  566. {1: } ^} |
  567. {1: } } |
  568. {1: }} |
  569. {3:~ }|*5
  570. {5:[No Name] [+] }|
  571. |
  572. ]],
  573. attr_ids = {
  574. [1] = { background = Screen.colors.Grey, foreground = Screen.colors.Blue4 },
  575. [2] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Blue4 },
  576. [3] = { foreground = Screen.colors.Blue, bold = true },
  577. [4] = { reverse = true },
  578. [5] = { reverse = true, bold = true },
  579. },
  580. }
  581. end)
  582. it('does not extend closed fold with `o`/`O`', function()
  583. local screen = Screen.new(60, 24)
  584. insert(test_text)
  585. parse('c')
  586. command([[set foldmethod=expr foldexpr=v:lua.vim.treesitter.foldexpr() foldcolumn=1]])
  587. feed('5ggzco')
  588. screen:expect({
  589. grid = [[
  590. {7:-}void ui_refresh(void) |
  591. {7:│}{ |
  592. {7:│} int width = INT_MAX, height = INT_MAX; |
  593. {7:│} bool ext_widgets[kUIExtCount]; |
  594. {7:+}{13:+--- 3 lines: for (UIExtension i = 0; (int)i < kUIExtCount}|
  595. {7:│}^ |
  596. {7:│} |
  597. {7:│} bool inclusive = ui_override(); |
  598. {7:-} for (size_t i = 0; i < ui_count; i++) { |
  599. {7:2} UI *ui = uis[i]; |
  600. {7:2} width = MIN(ui->width, width); |
  601. {7:2} height = MIN(ui->height, height); |
  602. {7:2} foo = BAR(ui->bazaar, bazaar); |
  603. {7:-} for (UIExtension j = 0; (int)j < kUIExtCount; j++) { |
  604. {7:3} ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
  605. {7:3} } |
  606. {7:2} } |
  607. {7:│}} |
  608. {1:~ }|*5
  609. {5:-- INSERT --} |
  610. ]],
  611. })
  612. feed('<Esc>O')
  613. screen:expect({
  614. grid = [[
  615. {7:-}void ui_refresh(void) |
  616. {7:│}{ |
  617. {7:│} int width = INT_MAX, height = INT_MAX; |
  618. {7:│} bool ext_widgets[kUIExtCount]; |
  619. {7:+}{13:+--- 3 lines: for (UIExtension i = 0; (int)i < kUIExtCount}|
  620. {7:│}^ |
  621. {7:│} |*2
  622. {7:│} bool inclusive = ui_override(); |
  623. {7:-} for (size_t i = 0; i < ui_count; i++) { |
  624. {7:2} UI *ui = uis[i]; |
  625. {7:2} width = MIN(ui->width, width); |
  626. {7:2} height = MIN(ui->height, height); |
  627. {7:2} foo = BAR(ui->bazaar, bazaar); |
  628. {7:-} for (UIExtension j = 0; (int)j < kUIExtCount; j++) { |
  629. {7:3} ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
  630. {7:3} } |
  631. {7:2} } |
  632. {7:│}} |
  633. {1:~ }|*4
  634. {5:-- INSERT --} |
  635. ]],
  636. })
  637. end)
  638. it("doesn't open folds that are not touched", function()
  639. -- test is known to be flaky
  640. -- https://github.com/neovim/neovim/issues/33910
  641. if t.skip_fragile(pending) then
  642. return
  643. end
  644. local screen = Screen.new(40, 8)
  645. screen:set_default_attr_ids({
  646. [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray },
  647. [2] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGray },
  648. [3] = { foreground = Screen.colors.Blue1, bold = true },
  649. [4] = { bold = true },
  650. })
  651. insert([[
  652. # h1
  653. t1
  654. # h2
  655. t2]])
  656. exec_lua([[vim.treesitter.query.set('markdown', 'folds', '(section) @fold')]])
  657. parse('markdown')
  658. command(
  659. [[set foldmethod=expr foldexpr=v:lua.vim.treesitter.foldexpr() foldcolumn=1 foldlevel=0]]
  660. )
  661. feed('ggzojo')
  662. poke_eventloop()
  663. screen:expect {
  664. grid = [[
  665. {1:-}# h1 |
  666. {1:│}t1 |
  667. {1:-}^ |
  668. {1:+}{2:+-- 2 lines: # h2·····················}|
  669. {3:~ }|*3
  670. {4:-- INSERT --} |
  671. ]],
  672. }
  673. feed('<Esc>u')
  674. -- TODO(tomtomjhj): `u` spuriously opens the fold (#26499).
  675. feed('zMggzo')
  676. feed('dd')
  677. poke_eventloop()
  678. screen:expect {
  679. grid = [[
  680. {1:-}^t1 |
  681. {1:-}# h2 |
  682. {1:│}t2 |
  683. {3:~ }|*4
  684. 1 line less; before #2 {MATCH:.*}|
  685. ]],
  686. }
  687. end)
  688. it("doesn't call get_parser too often when parser is not available", function()
  689. -- spy on vim.treesitter.get_parser() to keep track of how many times it is called
  690. exec_lua(function()
  691. _G.count = 0
  692. vim.treesitter.get_parser = (function(wrapped)
  693. return function(...)
  694. _G.count = _G.count + 1
  695. return wrapped(...)
  696. end
  697. end)(vim.treesitter.get_parser)
  698. end)
  699. insert(test_text)
  700. command [[
  701. set filetype=some_filetype_without_treesitter_parser
  702. set foldmethod=expr foldexpr=v:lua.vim.treesitter.foldexpr() foldcolumn=1 foldlevel=0
  703. ]]
  704. -- foldexpr will return '0' for all lines
  705. local levels = get_fold_levels() ---@type integer[]
  706. eq(19, #levels)
  707. for lnum, level in ipairs(levels) do
  708. eq('0', level, string.format("foldlevel[%d] == %s; expected '0'", lnum, level))
  709. end
  710. eq(
  711. 1,
  712. exec_lua [[ return _G.count ]],
  713. 'count should not be as high as the # of lines; actually only once for the buffer.'
  714. )
  715. end)
  716. it('can detect a new parser and refresh folds accordingly', function()
  717. local name = t.tmpname()
  718. write_file(name, test_text)
  719. command('edit ' .. name)
  720. command [[
  721. set filetype=some_filetype_without_treesitter_parser
  722. set foldmethod=expr foldexpr=v:lua.vim.treesitter.foldexpr() foldcolumn=1 foldlevel=0
  723. ]]
  724. -- foldexpr will return '0' for all lines
  725. local function expect_no_folds()
  726. local levels = get_fold_levels() ---@type integer[]
  727. eq(19, #levels)
  728. for lnum, level in ipairs(levels) do
  729. eq('0', level, string.format("foldlevel[%d] == %s; expected '0'", lnum, level))
  730. end
  731. end
  732. expect_no_folds()
  733. -- reload buffer as c filetype to simulate new parser being found
  734. feed('GA// vim: ft=c<Esc>')
  735. command([[write | edit]])
  736. local foldlevels = {
  737. [1] = '>1',
  738. [2] = '1',
  739. [3] = '1',
  740. [4] = '1',
  741. [5] = '>2',
  742. [6] = '2',
  743. [7] = '2',
  744. [8] = '1',
  745. [9] = '1',
  746. [10] = '>2',
  747. [11] = '2',
  748. [12] = '2',
  749. [13] = '2',
  750. [14] = '2',
  751. [15] = '>3',
  752. [16] = '3',
  753. [17] = '3',
  754. [18] = '2',
  755. [19] = '1',
  756. }
  757. eq(foldlevels, get_fold_levels())
  758. -- only changing filetype should change the parser again
  759. command('set ft=some_filetype_without_treesitter_parser')
  760. expect_no_folds()
  761. command('set ft=c')
  762. eq(foldlevels, get_fold_levels())
  763. end)
  764. end)