bufhl_spec.lua 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  1. local helpers = require('test.functional.helpers')(after_each)
  2. local Screen = require('test.functional.ui.screen')
  3. local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
  4. local command, neq = helpers.command, helpers.neq
  5. local meths = helpers.meths
  6. local curbufmeths, eq = helpers.curbufmeths, helpers.eq
  7. local pcall_err = helpers.pcall_err
  8. describe('Buffer highlighting', function()
  9. local screen
  10. before_each(function()
  11. clear()
  12. command('syntax on')
  13. screen = Screen.new(40, 8)
  14. screen:attach()
  15. screen:set_default_attr_ids({
  16. [1] = {bold=true, foreground=Screen.colors.Blue},
  17. [2] = {foreground = Screen.colors.Fuchsia}, -- String
  18. [3] = {foreground = Screen.colors.Brown, bold = true}, -- Statement
  19. [4] = {foreground = Screen.colors.SlateBlue}, -- Special
  20. [5] = {bold = true, foreground = Screen.colors.SlateBlue},
  21. [6] = {foreground = Screen.colors.DarkCyan}, -- Identifier
  22. [7] = {bold = true},
  23. [8] = {underline = true, bold = true, foreground = Screen.colors.SlateBlue},
  24. [9] = {foreground = Screen.colors.SlateBlue, underline = true},
  25. [10] = {foreground = Screen.colors.Red},
  26. [11] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
  27. [12] = {foreground = Screen.colors.Blue1},
  28. [13] = {background = Screen.colors.LightGrey},
  29. [14] = {background = Screen.colors.Gray90},
  30. [15] = {background = Screen.colors.Gray90, bold = true, foreground = Screen.colors.Brown},
  31. [16] = {foreground = Screen.colors.Magenta, background = Screen.colors.Gray90},
  32. [17] = {foreground = Screen.colors.Magenta, background = Screen.colors.LightRed},
  33. [18] = {background = Screen.colors.LightRed},
  34. [19] = {foreground = Screen.colors.Blue1, background = Screen.colors.LightRed},
  35. [20] = {underline = true, bold = true, foreground = Screen.colors.Cyan4},
  36. })
  37. end)
  38. local add_highlight = curbufmeths.add_highlight
  39. local clear_namespace = curbufmeths.clear_namespace
  40. it('works', function()
  41. insert([[
  42. these are some lines
  43. with colorful text]])
  44. feed('+')
  45. screen:expect([[
  46. these are some lines |
  47. with colorful tex^t |
  48. {1:~ }|
  49. {1:~ }|
  50. {1:~ }|
  51. {1:~ }|
  52. {1:~ }|
  53. |
  54. ]])
  55. add_highlight(-1, "String", 0 , 10, 14)
  56. add_highlight(-1, "Statement", 1 , 5, -1)
  57. screen:expect([[
  58. these are {2:some} lines |
  59. with {3:colorful tex^t} |
  60. {1:~ }|
  61. {1:~ }|
  62. {1:~ }|
  63. {1:~ }|
  64. {1:~ }|
  65. |
  66. ]])
  67. feed("ggo<esc>")
  68. screen:expect([[
  69. these are {2:some} lines |
  70. ^ |
  71. with {3:colorful text} |
  72. {1:~ }|
  73. {1:~ }|
  74. {1:~ }|
  75. {1:~ }|
  76. |
  77. ]])
  78. clear_namespace(-1, 0, -1)
  79. screen:expect([[
  80. these are some lines |
  81. ^ |
  82. with colorful text |
  83. {1:~ }|
  84. {1:~ }|
  85. {1:~ }|
  86. {1:~ }|
  87. |
  88. ]])
  89. end)
  90. describe('support using multiple namespaces', function()
  91. local id1, id2
  92. before_each(function()
  93. insert([[
  94. a longer example
  95. in order to demonstrate
  96. combining highlights
  97. from different sources]])
  98. command("hi ImportantWord gui=bold cterm=bold")
  99. id1 = add_highlight(0, "ImportantWord", 0, 2, 8)
  100. add_highlight(id1, "ImportantWord", 1, 12, -1)
  101. add_highlight(id1, "ImportantWord", 2, 0, 9)
  102. add_highlight(id1, "ImportantWord", 3, 5, 14)
  103. -- add_highlight can be called like this to get a new source
  104. -- without adding any highlight
  105. id2 = add_highlight(0, "", 0, 0, 0)
  106. neq(id1, id2)
  107. add_highlight(id2, "Special", 0, 2, 8)
  108. add_highlight(id2, "Identifier", 1, 3, 8)
  109. add_highlight(id2, "Special", 1, 14, 20)
  110. add_highlight(id2, "Underlined", 2, 6, 12)
  111. add_highlight(id2, "Underlined", 3, 0, 9)
  112. screen:expect([[
  113. a {5:longer} example |
  114. in {6:order} to {7:de}{5:monstr}{7:ate} |
  115. {7:combin}{8:ing}{9: hi}ghlights |
  116. {9:from }{8:diff}{7:erent} source^s |
  117. {1:~ }|
  118. {1:~ }|
  119. {1:~ }|
  120. |
  121. ]])
  122. end)
  123. it('and clearing the first added', function()
  124. clear_namespace(id1, 0, -1)
  125. screen:expect([[
  126. a {4:longer} example |
  127. in {6:order} to de{4:monstr}ate |
  128. combin{9:ing hi}ghlights |
  129. {9:from diff}erent source^s |
  130. {1:~ }|
  131. {1:~ }|
  132. {1:~ }|
  133. |
  134. ]])
  135. end)
  136. it('and clearing using deprecated name', function()
  137. curbufmeths.clear_highlight(id1, 0, -1)
  138. screen:expect([[
  139. a {4:longer} example |
  140. in {6:order} to de{4:monstr}ate |
  141. combin{9:ing hi}ghlights |
  142. {9:from diff}erent source^s |
  143. {1:~ }|
  144. {1:~ }|
  145. {1:~ }|
  146. |
  147. ]])
  148. end)
  149. it('and clearing the second added', function()
  150. clear_namespace(id2, 0, -1)
  151. screen:expect([[
  152. a {7:longer} example |
  153. in order to {7:demonstrate} |
  154. {7:combining} highlights |
  155. from {7:different} source^s |
  156. {1:~ }|
  157. {1:~ }|
  158. {1:~ }|
  159. |
  160. ]])
  161. end)
  162. it('and clearing line ranges', function()
  163. clear_namespace(-1, 0, 1)
  164. clear_namespace(id1, 1, 2)
  165. clear_namespace(id2, 2, -1)
  166. screen:expect([[
  167. a longer example |
  168. in {6:order} to de{4:monstr}ate |
  169. {7:combining} highlights |
  170. from {7:different} source^s |
  171. {1:~ }|
  172. {1:~ }|
  173. {1:~ }|
  174. |
  175. ]])
  176. end)
  177. it('and renumbering lines', function()
  178. feed('3Gddggo<esc>')
  179. screen:expect([[
  180. a {5:longer} example |
  181. ^ |
  182. in {6:order} to {7:de}{5:monstr}{7:ate} |
  183. {9:from }{8:diff}{7:erent} sources |
  184. {1:~ }|
  185. {1:~ }|
  186. {1:~ }|
  187. |
  188. ]])
  189. -- TODO(bfedl): this behaves a bit weirdly due to the highlight on
  190. -- the deleted line wrapping around. we should invalidate
  191. -- highlights when they are completely inside deleted text
  192. command('3move 4')
  193. screen:expect{grid=[[
  194. a {5:longer} example |
  195. |
  196. {8:from different sources} |
  197. {8:^in }{20:order}{8: to demonstrate} |
  198. {1:~ }|
  199. {1:~ }|
  200. {1:~ }|
  201. |
  202. ]]}
  203. --screen:expect([[
  204. -- a {5:longer} example |
  205. -- |
  206. -- {9:from }{8:diff}{7:erent} sources |
  207. -- ^in {6:order} to {7:de}{5:monstr}{7:ate} |
  208. -- {1:~ }|
  209. -- {1:~ }|
  210. -- {1:~ }|
  211. -- |
  212. --]])
  213. command('undo')
  214. screen:expect{grid=[[
  215. a {5:longer} example |
  216. ^ |
  217. in {6:order} to {7:de}{5:monstr}{7:ate} |
  218. {9:from }{8:diff}{7:erent} sources |
  219. {1:~ }|
  220. {1:~ }|
  221. {1:~ }|
  222. 1 change; before #4 {MATCH:.*}|
  223. ]]}
  224. command('undo')
  225. screen:expect{grid=[[
  226. ^a {5:longer} example |
  227. in {6:order} to {7:de}{5:monstr}{7:ate} |
  228. {9:from }{8:diff}{7:erent} sources |
  229. {1:~ }|
  230. {1:~ }|
  231. {1:~ }|
  232. {1:~ }|
  233. 1 line less; before #3 {MATCH:.*}|
  234. ]]}
  235. command('undo')
  236. screen:expect{grid=[[
  237. a {5:longer} example |
  238. in {6:order} to {7:de}{5:monstr}{7:ate} |
  239. {7:^combin}{8:ing}{9: hi}ghlights |
  240. {9:from }{8:diff}{7:erent} sources |
  241. {1:~ }|
  242. {1:~ }|
  243. {1:~ }|
  244. 1 more line; before #2 {MATCH:.*}|
  245. ]]}
  246. end)
  247. it('and moving lines around', function()
  248. command('2move 3')
  249. screen:expect{grid=[[
  250. a {5:longer} example |
  251. {7:combin}{8:ing}{9: hi}ghlights |
  252. ^in {6:order} to {7:de}{5:monstr}{7:ate} |
  253. {9:from }{8:diff}{7:erent} sources |
  254. {1:~ }|
  255. {1:~ }|
  256. {1:~ }|
  257. |
  258. ]]}
  259. command('1,2move 4')
  260. screen:expect{grid=[[
  261. in {6:order} to {7:de}{5:monstr}{7:ate} |
  262. {9:from }{8:diff}{7:erent} sources |
  263. a {5:longer} example |
  264. {7:^combin}{8:ing}{9: hi}ghlights |
  265. {1:~ }|
  266. {1:~ }|
  267. {1:~ }|
  268. |
  269. ]]}
  270. command('undo')
  271. screen:expect{grid=[[
  272. a {5:longer} example |
  273. {7:combin}{8:ing}{9: hi}ghlights |
  274. ^in {6:order} to {7:de}{5:monstr}{7:ate} |
  275. {9:from }{8:diff}{7:erent} sources |
  276. {1:~ }|
  277. {1:~ }|
  278. {1:~ }|
  279. 2 changes; before #3 {MATCH:.*}|
  280. ]]}
  281. command('undo')
  282. screen:expect{grid=[[
  283. a {5:longer} example |
  284. ^in {6:order} to {7:de}{5:monstr}{7:ate} |
  285. {7:combin}{8:ing}{9: hi}ghlights |
  286. {9:from }{8:diff}{7:erent} sources |
  287. {1:~ }|
  288. {1:~ }|
  289. {1:~ }|
  290. 1 change; before #2 {MATCH:.*}|
  291. ]]}
  292. end)
  293. it('and adjusting columns', function()
  294. -- insert before
  295. feed('ggiquite <esc>')
  296. screen:expect{grid=[[
  297. quite^ a {5:longer} example |
  298. in {6:order} to {7:de}{5:monstr}{7:ate} |
  299. {7:combin}{8:ing}{9: hi}ghlights |
  300. {9:from }{8:diff}{7:erent} sources |
  301. {1:~ }|
  302. {1:~ }|
  303. {1:~ }|
  304. |
  305. ]]}
  306. feed('u')
  307. screen:expect{grid=[[
  308. ^a {5:longer} example |
  309. in {6:order} to {7:de}{5:monstr}{7:ate} |
  310. {7:combin}{8:ing}{9: hi}ghlights |
  311. {9:from }{8:diff}{7:erent} sources |
  312. {1:~ }|
  313. {1:~ }|
  314. {1:~ }|
  315. 1 change; before #2 {MATCH:.*}|
  316. ]]}
  317. -- change/insert in the middle
  318. feed('+fesAAAA')
  319. screen:expect{grid=[[
  320. a {5:longer} example |
  321. in {6:ordAAAA^r} to {7:de}{5:monstr}{7:ate} |
  322. {7:combin}{8:ing}{9: hi}ghlights |
  323. {9:from }{8:diff}{7:erent} sources |
  324. {1:~ }|
  325. {1:~ }|
  326. {1:~ }|
  327. {7:-- INSERT --} |
  328. ]]}
  329. feed('<esc>tdD')
  330. screen:expect{grid=[[
  331. a {5:longer} example |
  332. in {6:ordAAAAr} t^o |
  333. {7:combin}{8:ing}{9: hi}ghlights |
  334. {9:from }{8:diff}{7:erent} sources |
  335. {1:~ }|
  336. {1:~ }|
  337. {1:~ }|
  338. |
  339. ]]}
  340. feed('u')
  341. screen:expect{grid=[[
  342. a {5:longer} example |
  343. in {6:ordAAAAr} to^ {7:de}{5:monstr}{7:ate} |
  344. {7:combin}{8:ing}{9: hi}ghlights |
  345. {9:from }{8:diff}{7:erent} sources |
  346. {1:~ }|
  347. {1:~ }|
  348. {1:~ }|
  349. 1 change; before #4 {MATCH:.*}|
  350. ]]}
  351. feed('u')
  352. screen:expect{grid=[[
  353. a {5:longer} example |
  354. in {6:ord^er} to {7:de}{5:monstr}{7:ate} |
  355. {7:combin}{8:ing}{9: hi}ghlights |
  356. {9:from }{8:diff}{7:erent} sources |
  357. {1:~ }|
  358. {1:~ }|
  359. {1:~ }|
  360. 1 change; before #3 {MATCH:.*}|
  361. ]]}
  362. end)
  363. it('and joining lines', function()
  364. feed('ggJJJ')
  365. screen:expect{grid=[[
  366. a {5:longer} example in {6:order} to {7:de}{5:monstr}{7:ate}|
  367. {7:combin}{8:ing}{9: hi}ghlights^ {9:from }{8:diff}{7:erent} sou|
  368. rces |
  369. {1:~ }|
  370. {1:~ }|
  371. {1:~ }|
  372. {1:~ }|
  373. |
  374. ]]}
  375. feed('uuu')
  376. screen:expect{grid=[[
  377. ^a {5:longer} example |
  378. in {6:order} to {7:de}{5:monstr}{7:ate} |
  379. {7:combin}{8:ing}{9: hi}ghlights |
  380. {9:from }{8:diff}{7:erent} sources |
  381. {1:~ }|
  382. {1:~ }|
  383. {1:~ }|
  384. 1 more line; before #2 {MATCH:.*}|
  385. ]]}
  386. end)
  387. it('and splitting lines', function()
  388. feed('2Gtti<cr>')
  389. screen:expect{grid=[[
  390. a {5:longer} example |
  391. in {6:order} |
  392. ^ to {7:de}{5:monstr}{7:ate} |
  393. {7:combin}{8:ing}{9: hi}ghlights |
  394. {9:from }{8:diff}{7:erent} sources |
  395. {1:~ }|
  396. {1:~ }|
  397. {7:-- INSERT --} |
  398. ]]}
  399. feed('<esc>tsi<cr>')
  400. screen:expect{grid=[[
  401. a {5:longer} example |
  402. in {6:order} |
  403. to {7:de}{5:mo} |
  404. {5:^nstr}{7:ate} |
  405. {7:combin}{8:ing}{9: hi}ghlights |
  406. {9:from }{8:diff}{7:erent} sources |
  407. {1:~ }|
  408. {7:-- INSERT --} |
  409. ]]}
  410. feed('<esc>u')
  411. screen:expect{grid=[[
  412. a {5:longer} example |
  413. in {6:order} |
  414. to {7:de}{5:mo^nstr}{7:ate} |
  415. {7:combin}{8:ing}{9: hi}ghlights |
  416. {9:from }{8:diff}{7:erent} sources |
  417. {1:~ }|
  418. {1:~ }|
  419. 1 line less; before #3 {MATCH:.*}|
  420. ]]}
  421. feed('<esc>u')
  422. screen:expect{grid=[[
  423. a {5:longer} example |
  424. in {6:order}^ to {7:de}{5:monstr}{7:ate} |
  425. {7:combin}{8:ing}{9: hi}ghlights |
  426. {9:from }{8:diff}{7:erent} sources |
  427. {1:~ }|
  428. {1:~ }|
  429. {1:~ }|
  430. 1 line less; before #2 {MATCH:.*}|
  431. ]]}
  432. end)
  433. end)
  434. pending('prioritizes latest added highlight', function()
  435. insert([[
  436. three overlapping colors]])
  437. add_highlight(0, "Identifier", 0, 6, 17)
  438. add_highlight(0, "String", 0, 14, 23)
  439. local id = add_highlight(0, "Special", 0, 0, 9)
  440. screen:expect([[
  441. {4:three ove}{6:rlapp}{2:ing color}^s |
  442. {1:~ }|
  443. {1:~ }|
  444. {1:~ }|
  445. {1:~ }|
  446. {1:~ }|
  447. {1:~ }|
  448. |
  449. ]])
  450. clear_namespace(id, 0, 1)
  451. screen:expect([[
  452. three {6:overlapp}{2:ing color}^s |
  453. {1:~ }|
  454. {1:~ }|
  455. {1:~ }|
  456. {1:~ }|
  457. {1:~ }|
  458. {1:~ }|
  459. |
  460. ]])
  461. end)
  462. it('prioritizes earlier highlight groups (TEMP)', function()
  463. insert([[
  464. three overlapping colors]])
  465. add_highlight(0, "Identifier", 0, 6, 17)
  466. add_highlight(0, "String", 0, 14, 23)
  467. local id = add_highlight(0, "Special", 0, 0, 9)
  468. screen:expect{grid=[[
  469. {4:three }{6:overlapp}{2:ing color}^s |
  470. {1:~ }|
  471. {1:~ }|
  472. {1:~ }|
  473. {1:~ }|
  474. {1:~ }|
  475. {1:~ }|
  476. |
  477. ]]}
  478. clear_namespace(id, 0, 1)
  479. screen:expect{grid=[[
  480. three {6:overlapp}{2:ing color}^s |
  481. {1:~ }|
  482. {1:~ }|
  483. {1:~ }|
  484. {1:~ }|
  485. {1:~ }|
  486. {1:~ }|
  487. |
  488. ]]}
  489. end)
  490. it('respects priority', function()
  491. local set_extmark = curbufmeths.set_extmark
  492. local id = meths.create_namespace('')
  493. insert [[foobar]]
  494. set_extmark(id, 0, 0, {
  495. end_line = 0,
  496. end_col = 5,
  497. hl_group = "Statement",
  498. priority = 100
  499. })
  500. set_extmark(id, 0, 0, {
  501. end_line = 0,
  502. end_col = 6,
  503. hl_group = "String",
  504. priority = 1
  505. })
  506. screen:expect [[
  507. {3:fooba}{2:^r} |
  508. {1:~ }|
  509. {1:~ }|
  510. {1:~ }|
  511. {1:~ }|
  512. {1:~ }|
  513. {1:~ }|
  514. |
  515. ]]
  516. clear_namespace(id, 0, -1)
  517. screen:expect{grid=[[
  518. fooba^r |
  519. {1:~ }|
  520. {1:~ }|
  521. {1:~ }|
  522. {1:~ }|
  523. {1:~ }|
  524. {1:~ }|
  525. |
  526. ]]}
  527. set_extmark(id, 0, 0, {
  528. end_line = 0,
  529. end_col = 6,
  530. hl_group = "String",
  531. priority = 1
  532. })
  533. set_extmark(id, 0, 0, {
  534. end_line = 0,
  535. end_col = 5,
  536. hl_group = "Statement",
  537. priority = 100
  538. })
  539. screen:expect [[
  540. {3:fooba}{2:^r} |
  541. {1:~ }|
  542. {1:~ }|
  543. {1:~ }|
  544. {1:~ }|
  545. {1:~ }|
  546. {1:~ }|
  547. |
  548. ]]
  549. end)
  550. it('works with multibyte text', function()
  551. insert([[
  552. Ta båten över sjön!]])
  553. add_highlight(-1, "Identifier", 0, 3, 9)
  554. add_highlight(-1, "String", 0, 16, 21)
  555. screen:expect([[
  556. Ta {6:båten} över {2:sjön}^! |
  557. {1:~ }|
  558. {1:~ }|
  559. {1:~ }|
  560. {1:~ }|
  561. {1:~ }|
  562. {1:~ }|
  563. |
  564. ]])
  565. end)
  566. it('works with new syntax groups', function()
  567. insert([[
  568. fancy code in a new fancy language]])
  569. add_highlight(-1, "FancyLangItem", 0, 0, 5)
  570. screen:expect([[
  571. fancy code in a new fancy languag^e |
  572. {1:~ }|
  573. {1:~ }|
  574. {1:~ }|
  575. {1:~ }|
  576. {1:~ }|
  577. {1:~ }|
  578. |
  579. ]])
  580. command('hi FancyLangItem guifg=red')
  581. screen:expect([[
  582. {10:fancy} code in a new fancy languag^e |
  583. {1:~ }|
  584. {1:~ }|
  585. {1:~ }|
  586. {1:~ }|
  587. {1:~ }|
  588. {1:~ }|
  589. |
  590. ]])
  591. end)
  592. describe('virtual text decorations', function()
  593. local set_virtual_text = curbufmeths.set_virtual_text
  594. local id1, id2
  595. before_each(function()
  596. insert([[
  597. 1 + 2
  598. 3 +
  599. x = 4]])
  600. feed('O<esc>20A5, <esc>gg')
  601. screen:expect([[
  602. ^1 + 2 |
  603. 3 + |
  604. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  605. , 5, 5, 5, 5, 5, 5, |
  606. x = 4 |
  607. {1:~ }|
  608. {1:~ }|
  609. |
  610. ]])
  611. id1 = set_virtual_text(0, 0, {{"=", "Statement"}, {" 3", "Number"}}, {})
  612. set_virtual_text(id1, 1, {{"ERROR:", "ErrorMsg"}, {" invalid syntax"}}, {})
  613. id2 = set_virtual_text(0, 2, {{"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."}}, {})
  614. neq(id2, id1)
  615. end)
  616. it('works', function()
  617. screen:expect([[
  618. ^1 + 2 {3:=}{2: 3} |
  619. 3 + {11:ERROR:} invalid syntax |
  620. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  621. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  622. x = 4 |
  623. {1:~ }|
  624. {1:~ }|
  625. |
  626. ]])
  627. clear_namespace(id1, 0, -1)
  628. screen:expect([[
  629. ^1 + 2 |
  630. 3 + |
  631. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  632. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  633. x = 4 |
  634. {1:~ }|
  635. {1:~ }|
  636. |
  637. ]])
  638. -- Handles doublewidth chars, leaving a space if truncating
  639. -- in the middle of a char
  640. eq(-1, set_virtual_text(-1, 1, {{"暗x事zz速野谷質結育副住新覚丸活解終事", "Comment"}}, {}))
  641. screen:expect([[
  642. ^1 + 2 |
  643. 3 + {12:暗x事zz速野谷質結育副住新覚丸活解終 }|
  644. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  645. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  646. x = 4 |
  647. {1:~ }|
  648. {1:~ }|
  649. |
  650. ]])
  651. feed("2Gx")
  652. screen:expect([[
  653. 1 + 2 |
  654. ^ + {12:暗x事zz速野谷質結育副住新覚丸活解終事}|
  655. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  656. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  657. x = 4 |
  658. {1:~ }|
  659. {1:~ }|
  660. |
  661. ]])
  662. feed("2Gdd")
  663. -- TODO(bfredl): currently decorations get moved from a deleted line
  664. -- to the next one. We might want to add "invalidation" when deleting
  665. -- over a decoration.
  666. screen:expect{grid=[[
  667. 1 + 2 |
  668. ^5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  669. , 5, 5, 5, 5, 5, 5, {12:暗x事zz速野谷質結育}|
  670. x = 4 |
  671. {1:~ }|
  672. {1:~ }|
  673. {1:~ }|
  674. |
  675. ]]}
  676. --screen:expect([[
  677. -- 1 + 2 |
  678. -- ^5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  679. -- , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  680. -- x = 4 |
  681. -- {1:~ }|
  682. -- {1:~ }|
  683. -- {1:~ }|
  684. -- |
  685. --]])
  686. end)
  687. it('validates contents', function()
  688. -- this used to leak memory
  689. eq("Invalid 'chunk': expected Array, got String", pcall_err(set_virtual_text, id1, 0, {"texty"}, {}))
  690. eq("Invalid 'chunk': expected Array, got String", pcall_err(set_virtual_text, id1, 0, {{"very"}, "texty"}, {}))
  691. end)
  692. it('can be retrieved', function()
  693. local get_extmarks = curbufmeths.get_extmarks
  694. local line_count = curbufmeths.line_count
  695. local s1 = {{'Köttbullar', 'Comment'}, {'Kräuterbutter'}}
  696. local s2 = {{'こんにちは', 'Comment'}}
  697. -- TODO: only a virtual text from the same ns currently overrides
  698. -- an existing virtual text. We might add a prioritation system.
  699. set_virtual_text(id1, 0, s1, {})
  700. eq({{1, 0, 0, {
  701. ns_id = 1,
  702. priority = 0,
  703. virt_text = s1,
  704. -- other details
  705. right_gravity = true,
  706. virt_text_pos = 'eol',
  707. virt_text_hide = false,
  708. }}}, get_extmarks(id1, {0,0}, {0, -1}, {details=true}))
  709. -- TODO: is this really valid? shouldn't the max be line_count()-1?
  710. local lastline = line_count()
  711. set_virtual_text(id1, line_count(), s2, {})
  712. eq({{3, lastline, 0, {
  713. ns_id = 1,
  714. priority = 0,
  715. virt_text = s2,
  716. -- other details
  717. right_gravity = true,
  718. virt_text_pos = 'eol',
  719. virt_text_hide = false,
  720. }}}, get_extmarks(id1, {lastline,0}, {lastline, -1}, {details=true}))
  721. eq({}, get_extmarks(id1, {lastline+9000,0}, {lastline+9000, -1}, {}))
  722. end)
  723. it('is not highlighted by visual selection', function()
  724. feed("ggVG")
  725. screen:expect([[
  726. {13:1 + 2} {3:=}{2: 3} |
  727. {13:3 +} {11:ERROR:} invalid syntax |
  728. {13:5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}|
  729. {13:, 5, 5, 5, 5, 5, 5, } Lorem ipsum dolor s|
  730. ^x{13: = 4} |
  731. {1:~ }|
  732. {1:~ }|
  733. {7:-- VISUAL LINE --} |
  734. ]])
  735. feed("<esc>")
  736. screen:expect([[
  737. 1 + 2 {3:=}{2: 3} |
  738. 3 + {11:ERROR:} invalid syntax |
  739. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  740. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  741. ^x = 4 |
  742. {1:~ }|
  743. {1:~ }|
  744. |
  745. ]])
  746. -- special case: empty line has extra eol highlight
  747. feed("ggd$")
  748. screen:expect([[
  749. ^ {3:=}{2: 3} |
  750. 3 + {11:ERROR:} invalid syntax |
  751. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  752. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  753. x = 4 |
  754. {1:~ }|
  755. {1:~ }|
  756. |
  757. ]])
  758. feed("jvk")
  759. screen:expect([[
  760. ^ {3:=}{2: 3} |
  761. {13:3} + {11:ERROR:} invalid syntax |
  762. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  763. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  764. x = 4 |
  765. {1:~ }|
  766. {1:~ }|
  767. {7:-- VISUAL --} |
  768. ]])
  769. feed("o")
  770. screen:expect([[
  771. {13: }{3:=}{2: 3} |
  772. ^3 + {11:ERROR:} invalid syntax |
  773. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  774. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  775. x = 4 |
  776. {1:~ }|
  777. {1:~ }|
  778. {7:-- VISUAL --} |
  779. ]])
  780. end)
  781. it('works with listchars', function()
  782. command("set list listchars+=eol:$")
  783. screen:expect([[
  784. ^1 + 2{1:$}{3:=}{2: 3} |
  785. 3 +{1:$}{11:ERROR:} invalid syntax |
  786. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  787. , 5, 5, 5, 5, 5, 5,{1:-$}Lorem ipsum dolor s|
  788. x = 4{1:$} |
  789. {1:~ }|
  790. {1:~ }|
  791. |
  792. ]])
  793. clear_namespace(-1, 0, -1)
  794. screen:expect([[
  795. ^1 + 2{1:$} |
  796. 3 +{1:$} |
  797. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  798. , 5, 5, 5, 5, 5, 5,{1:-$} |
  799. x = 4{1:$} |
  800. {1:~ }|
  801. {1:~ }|
  802. |
  803. ]])
  804. end)
  805. it('works with cursorline', function()
  806. command("set cursorline")
  807. screen:expect{grid=[[
  808. {14:^1 + 2 }{3:=}{2: 3}{14: }|
  809. 3 + {11:ERROR:} invalid syntax |
  810. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  811. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  812. x = 4 |
  813. {1:~ }|
  814. {1:~ }|
  815. |
  816. ]]}
  817. feed('j')
  818. screen:expect{grid=[[
  819. 1 + 2 {3:=}{2: 3} |
  820. {14:^3 + }{11:ERROR:} invalid syntax{14: }|
  821. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  822. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  823. x = 4 |
  824. {1:~ }|
  825. {1:~ }|
  826. |
  827. ]]}
  828. feed('j')
  829. screen:expect{grid=[[
  830. 1 + 2 {3:=}{2: 3} |
  831. 3 + {11:ERROR:} invalid syntax |
  832. {14:^5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}|
  833. {14:, 5, 5, 5, 5, 5, 5, }Lorem ipsum dolor s|
  834. x = 4 |
  835. {1:~ }|
  836. {1:~ }|
  837. |
  838. ]]}
  839. end)
  840. it('works with color column', function()
  841. eq(-1, set_virtual_text(-1, 3, {{"暗x事", "Comment"}}, {}))
  842. screen:expect{grid=[[
  843. ^1 + 2 {3:=}{2: 3} |
  844. 3 + {11:ERROR:} invalid syntax |
  845. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  846. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  847. x = 4 {12:暗x事} |
  848. {1:~ }|
  849. {1:~ }|
  850. |
  851. ]]}
  852. command("set colorcolumn=9")
  853. screen:expect{grid=[[
  854. ^1 + 2 {3:=}{2: 3} |
  855. 3 + {11:ERROR:} invalid syntax |
  856. 5, 5, 5,{18: }5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  857. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  858. x = 4 {12:暗x事} |
  859. {1:~ }|
  860. {1:~ }|
  861. |
  862. ]]}
  863. end)
  864. end)
  865. it('and virtual text use the same namespace counter', function()
  866. local set_virtual_text = curbufmeths.set_virtual_text
  867. eq(1, add_highlight(0, "String", 0 , 0, -1))
  868. eq(2, set_virtual_text(0, 0, {{"= text", "Comment"}}, {}))
  869. eq(3, meths.create_namespace("my-ns"))
  870. eq(4, add_highlight(0, "String", 0 , 0, -1))
  871. eq(5, set_virtual_text(0, 0, {{"= text", "Comment"}}, {}))
  872. eq(6, meths.create_namespace("other-ns"))
  873. end)
  874. end)