bufhl_spec.lua 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935
  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 change3; 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. set_extmark(id, 0, 0, {
  518. end_line = 0,
  519. end_col = 6,
  520. hl_group = "String",
  521. priority = 1
  522. })
  523. set_extmark(id, 0, 0, {
  524. end_line = 0,
  525. end_col = 5,
  526. hl_group = "Statement",
  527. priority = 100
  528. })
  529. screen:expect [[
  530. {3:fooba}{2:^r} |
  531. {1:~ }|
  532. {1:~ }|
  533. {1:~ }|
  534. {1:~ }|
  535. {1:~ }|
  536. {1:~ }|
  537. |
  538. ]]
  539. end)
  540. it('works with multibyte text', function()
  541. insert([[
  542. Ta båten över sjön!]])
  543. add_highlight(-1, "Identifier", 0, 3, 9)
  544. add_highlight(-1, "String", 0, 16, 21)
  545. screen:expect([[
  546. Ta {6:båten} över {2:sjön}^! |
  547. {1:~ }|
  548. {1:~ }|
  549. {1:~ }|
  550. {1:~ }|
  551. {1:~ }|
  552. {1:~ }|
  553. |
  554. ]])
  555. end)
  556. it('works with new syntax groups', function()
  557. insert([[
  558. fancy code in a new fancy language]])
  559. add_highlight(-1, "FancyLangItem", 0, 0, 5)
  560. screen:expect([[
  561. fancy code in a new fancy languag^e |
  562. {1:~ }|
  563. {1:~ }|
  564. {1:~ }|
  565. {1:~ }|
  566. {1:~ }|
  567. {1:~ }|
  568. |
  569. ]])
  570. command('hi FancyLangItem guifg=red')
  571. screen:expect([[
  572. {10:fancy} code in a new fancy languag^e |
  573. {1:~ }|
  574. {1:~ }|
  575. {1:~ }|
  576. {1:~ }|
  577. {1:~ }|
  578. {1:~ }|
  579. |
  580. ]])
  581. end)
  582. describe('virtual text decorations', function()
  583. local set_virtual_text = curbufmeths.set_virtual_text
  584. local id1, id2
  585. before_each(function()
  586. insert([[
  587. 1 + 2
  588. 3 +
  589. x = 4]])
  590. feed('O<esc>20A5, <esc>gg')
  591. screen:expect([[
  592. ^1 + 2 |
  593. 3 + |
  594. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  595. , 5, 5, 5, 5, 5, 5, |
  596. x = 4 |
  597. {1:~ }|
  598. {1:~ }|
  599. |
  600. ]])
  601. id1 = set_virtual_text(0, 0, {{"=", "Statement"}, {" 3", "Number"}}, {})
  602. set_virtual_text(id1, 1, {{"ERROR:", "ErrorMsg"}, {" invalid syntax"}}, {})
  603. 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."}}, {})
  604. neq(id2, id1)
  605. end)
  606. it('works', function()
  607. screen:expect([[
  608. ^1 + 2 {3:=}{2: 3} |
  609. 3 + {11:ERROR:} invalid syntax |
  610. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  611. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  612. x = 4 |
  613. {1:~ }|
  614. {1:~ }|
  615. |
  616. ]])
  617. clear_namespace(id1, 0, -1)
  618. screen:expect([[
  619. ^1 + 2 |
  620. 3 + |
  621. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  622. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  623. x = 4 |
  624. {1:~ }|
  625. {1:~ }|
  626. |
  627. ]])
  628. -- Handles doublewidth chars, leaving a space if truncating
  629. -- in the middle of a char
  630. eq(-1, set_virtual_text(-1, 1, {{"暗x事zz速野谷質結育副住新覚丸活解終事", "Comment"}}, {}))
  631. screen:expect([[
  632. ^1 + 2 |
  633. 3 + {12:暗x事zz速野谷質結育副住新覚丸活解終 }|
  634. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  635. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  636. x = 4 |
  637. {1:~ }|
  638. {1:~ }|
  639. |
  640. ]])
  641. feed("2Gx")
  642. screen:expect([[
  643. 1 + 2 |
  644. ^ + {12:暗x事zz速野谷質結育副住新覚丸活解終事}|
  645. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  646. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  647. x = 4 |
  648. {1:~ }|
  649. {1:~ }|
  650. |
  651. ]])
  652. feed("2Gdd")
  653. -- TODO(bfredl): currently decorations get moved from a deleted line
  654. -- to the next one. We might want to add "invalidation" when deleting
  655. -- over a decoration.
  656. screen:expect{grid=[[
  657. 1 + 2 |
  658. ^5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  659. , 5, 5, 5, 5, 5, 5, {12:暗x事zz速野谷質結育}|
  660. x = 4 |
  661. {1:~ }|
  662. {1:~ }|
  663. {1:~ }|
  664. |
  665. ]]}
  666. --screen:expect([[
  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, Lorem ipsum dolor s|
  670. -- x = 4 |
  671. -- {1:~ }|
  672. -- {1:~ }|
  673. -- {1:~ }|
  674. -- |
  675. --]])
  676. end)
  677. it('validates contents', function()
  678. -- this used to leak memory
  679. eq('Chunk is not an array', pcall_err(set_virtual_text, id1, 0, {"texty"}, {}))
  680. eq('Chunk is not an array', pcall_err(set_virtual_text, id1, 0, {{"very"}, "texty"}, {}))
  681. end)
  682. it('can be retrieved', function()
  683. local get_extmarks = curbufmeths.get_extmarks
  684. local line_count = curbufmeths.line_count
  685. local s1 = {{'Köttbullar', 'Comment'}, {'Kräuterbutter'}}
  686. local s2 = {{'こんにちは', 'Comment'}}
  687. -- TODO: only a virtual text from the same ns curretly overrides
  688. -- an existing virtual text. We might add a prioritation system.
  689. set_virtual_text(id1, 0, s1, {})
  690. eq({{1, 0, 0, { priority = 0, virt_text = s1}}}, get_extmarks(id1, {0,0}, {0, -1}, {details=true}))
  691. -- TODO: is this really valid? shouldn't the max be line_count()-1?
  692. local lastline = line_count()
  693. set_virtual_text(id1, line_count(), s2, {})
  694. eq({{3, lastline, 0, { priority = 0, virt_text = s2}}}, get_extmarks(id1, {lastline,0}, {lastline, -1}, {details=true}))
  695. eq({}, get_extmarks(id1, {lastline+9000,0}, {lastline+9000, -1}, {}))
  696. end)
  697. it('is not highlighted by visual selection', function()
  698. feed("ggVG")
  699. screen:expect([[
  700. {13:1 + 2} {3:=}{2: 3} |
  701. {13:3 +} {11:ERROR:} invalid syntax |
  702. {13:5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}|
  703. {13:, 5, 5, 5, 5, 5, 5, } Lorem ipsum dolor s|
  704. ^x{13: = 4} |
  705. {1:~ }|
  706. {1:~ }|
  707. {7:-- VISUAL LINE --} |
  708. ]])
  709. feed("<esc>")
  710. screen:expect([[
  711. 1 + 2 {3:=}{2: 3} |
  712. 3 + {11:ERROR:} invalid syntax |
  713. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  714. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  715. ^x = 4 |
  716. {1:~ }|
  717. {1:~ }|
  718. |
  719. ]])
  720. -- special case: empty line has extra eol highlight
  721. feed("ggd$")
  722. screen:expect([[
  723. ^ {3:=}{2: 3} |
  724. 3 + {11:ERROR:} invalid syntax |
  725. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  726. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  727. x = 4 |
  728. {1:~ }|
  729. {1:~ }|
  730. |
  731. ]])
  732. feed("jvk")
  733. screen:expect([[
  734. ^ {3:=}{2: 3} |
  735. {13:3} + {11:ERROR:} invalid syntax |
  736. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  737. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  738. x = 4 |
  739. {1:~ }|
  740. {1:~ }|
  741. {7:-- VISUAL --} |
  742. ]])
  743. feed("o")
  744. screen:expect([[
  745. {13: }{3:=}{2: 3} |
  746. ^3 + {11:ERROR:} invalid syntax |
  747. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  748. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  749. x = 4 |
  750. {1:~ }|
  751. {1:~ }|
  752. {7:-- VISUAL --} |
  753. ]])
  754. end)
  755. it('works with listchars', function()
  756. command("set list listchars+=eol:$")
  757. screen:expect([[
  758. ^1 + 2{1:$}{3:=}{2: 3} |
  759. 3 +{1:$}{11:ERROR:} invalid syntax |
  760. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  761. , 5, 5, 5, 5, 5, 5,{1:-$}Lorem ipsum dolor s|
  762. x = 4{1:$} |
  763. {1:~ }|
  764. {1:~ }|
  765. |
  766. ]])
  767. clear_namespace(-1, 0, -1)
  768. screen:expect([[
  769. ^1 + 2{1:$} |
  770. 3 +{1:$} |
  771. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  772. , 5, 5, 5, 5, 5, 5,{1:-$} |
  773. x = 4{1:$} |
  774. {1:~ }|
  775. {1:~ }|
  776. |
  777. ]])
  778. end)
  779. it('works with cursorline', function()
  780. command("set cursorline")
  781. screen:expect([[
  782. {14:^1 + 2 }{15:=}{16: 3}{14: }|
  783. 3 + {11:ERROR:} invalid syntax |
  784. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  785. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  786. x = 4 |
  787. {1:~ }|
  788. {1:~ }|
  789. |
  790. ]])
  791. feed('j')
  792. screen:expect([[
  793. 1 + 2 {3:=}{2: 3} |
  794. {14:^3 + }{11:ERROR:}{14: invalid syntax }|
  795. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  796. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  797. x = 4 |
  798. {1:~ }|
  799. {1:~ }|
  800. |
  801. ]])
  802. feed('j')
  803. screen:expect([[
  804. 1 + 2 {3:=}{2: 3} |
  805. 3 + {11:ERROR:} invalid syntax |
  806. {14:^5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}|
  807. {14:, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s}|
  808. x = 4 |
  809. {1:~ }|
  810. {1:~ }|
  811. |
  812. ]])
  813. end)
  814. it('works with color column', function()
  815. eq(-1, set_virtual_text(-1, 3, {{"暗x事", "Comment"}}, {}))
  816. screen:expect{grid=[[
  817. ^1 + 2 {3:=}{2: 3} |
  818. 3 + {11:ERROR:} invalid syntax |
  819. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  820. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  821. x = 4 {12:暗x事} |
  822. {1:~ }|
  823. {1:~ }|
  824. |
  825. ]]}
  826. command("set colorcolumn=9")
  827. screen:expect{grid=[[
  828. ^1 + 2 {3:=}{2: }{17:3} |
  829. 3 + {11:ERROR:} invalid syntax |
  830. 5, 5, 5,{18: }5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
  831. , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
  832. x = 4 {12:暗}{19:x}{12:事} |
  833. {1:~ }|
  834. {1:~ }|
  835. |
  836. ]]}
  837. end)
  838. end)
  839. it('and virtual text use the same namespace counter', function()
  840. local set_virtual_text = curbufmeths.set_virtual_text
  841. eq(1, add_highlight(0, "String", 0 , 0, -1))
  842. eq(2, set_virtual_text(0, 0, {{"= text", "Comment"}}, {}))
  843. eq(3, meths.create_namespace("my-ns"))
  844. eq(4, add_highlight(0, "String", 0 , 0, -1))
  845. eq(5, set_virtual_text(0, 0, {{"= text", "Comment"}}, {}))
  846. eq(6, meths.create_namespace("other-ns"))
  847. end)
  848. end)