vim_spec.lua 89 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809
  1. -- Test suite for testing interactions with API bindings
  2. local helpers = require('test.functional.helpers')(after_each)
  3. local Screen = require('test.functional.ui.screen')
  4. local funcs = helpers.funcs
  5. local meths = helpers.meths
  6. local command = helpers.command
  7. local insert = helpers.insert
  8. local clear = helpers.clear
  9. local eq = helpers.eq
  10. local ok = helpers.ok
  11. local eval = helpers.eval
  12. local feed = helpers.feed
  13. local pcall_err = helpers.pcall_err
  14. local exec_lua = helpers.exec_lua
  15. local matches = helpers.matches
  16. local exec = helpers.exec
  17. local NIL = helpers.NIL
  18. local retry = helpers.retry
  19. local next_msg = helpers.next_msg
  20. local remove_trace = helpers.remove_trace
  21. local mkdir_p = helpers.mkdir_p
  22. local rmdir = helpers.rmdir
  23. local write_file = helpers.write_file
  24. describe('lua stdlib', function()
  25. before_each(clear)
  26. -- İ: `tolower("İ")` is `i` which has length 1 while `İ` itself has
  27. -- length 2 (in bytes).
  28. -- Ⱥ: `tolower("Ⱥ")` is `ⱥ` which has length 2 while `Ⱥ` itself has
  29. -- length 3 (in bytes).
  30. --
  31. -- Note: 'i' !=? 'İ' and 'ⱥ' !=? 'Ⱥ' on some systems.
  32. -- Note: Built-in Nvim comparison (on systems lacking `strcasecmp`) works
  33. -- only on ASCII characters.
  34. it('vim.stricmp', function()
  35. eq(0, funcs.luaeval('vim.stricmp("a", "A")'))
  36. eq(0, funcs.luaeval('vim.stricmp("A", "a")'))
  37. eq(0, funcs.luaeval('vim.stricmp("a", "a")'))
  38. eq(0, funcs.luaeval('vim.stricmp("A", "A")'))
  39. eq(0, funcs.luaeval('vim.stricmp("", "")'))
  40. eq(0, funcs.luaeval('vim.stricmp("\\0", "\\0")'))
  41. eq(0, funcs.luaeval('vim.stricmp("\\0\\0", "\\0\\0")'))
  42. eq(0, funcs.luaeval('vim.stricmp("\\0\\0\\0", "\\0\\0\\0")'))
  43. eq(0, funcs.luaeval('vim.stricmp("\\0\\0\\0A", "\\0\\0\\0a")'))
  44. eq(0, funcs.luaeval('vim.stricmp("\\0\\0\\0a", "\\0\\0\\0A")'))
  45. eq(0, funcs.luaeval('vim.stricmp("\\0\\0\\0a", "\\0\\0\\0a")'))
  46. eq(0, funcs.luaeval('vim.stricmp("a\\0", "A\\0")'))
  47. eq(0, funcs.luaeval('vim.stricmp("A\\0", "a\\0")'))
  48. eq(0, funcs.luaeval('vim.stricmp("a\\0", "a\\0")'))
  49. eq(0, funcs.luaeval('vim.stricmp("A\\0", "A\\0")'))
  50. eq(0, funcs.luaeval('vim.stricmp("\\0a", "\\0A")'))
  51. eq(0, funcs.luaeval('vim.stricmp("\\0A", "\\0a")'))
  52. eq(0, funcs.luaeval('vim.stricmp("\\0a", "\\0a")'))
  53. eq(0, funcs.luaeval('vim.stricmp("\\0A", "\\0A")'))
  54. eq(0, funcs.luaeval('vim.stricmp("\\0a\\0", "\\0A\\0")'))
  55. eq(0, funcs.luaeval('vim.stricmp("\\0A\\0", "\\0a\\0")'))
  56. eq(0, funcs.luaeval('vim.stricmp("\\0a\\0", "\\0a\\0")'))
  57. eq(0, funcs.luaeval('vim.stricmp("\\0A\\0", "\\0A\\0")'))
  58. eq(-1, funcs.luaeval('vim.stricmp("a", "B")'))
  59. eq(-1, funcs.luaeval('vim.stricmp("A", "b")'))
  60. eq(-1, funcs.luaeval('vim.stricmp("a", "b")'))
  61. eq(-1, funcs.luaeval('vim.stricmp("A", "B")'))
  62. eq(-1, funcs.luaeval('vim.stricmp("", "\\0")'))
  63. eq(-1, funcs.luaeval('vim.stricmp("\\0", "\\0\\0")'))
  64. eq(-1, funcs.luaeval('vim.stricmp("\\0\\0", "\\0\\0\\0")'))
  65. eq(-1, funcs.luaeval('vim.stricmp("\\0\\0\\0A", "\\0\\0\\0b")'))
  66. eq(-1, funcs.luaeval('vim.stricmp("\\0\\0\\0a", "\\0\\0\\0B")'))
  67. eq(-1, funcs.luaeval('vim.stricmp("\\0\\0\\0a", "\\0\\0\\0b")'))
  68. eq(-1, funcs.luaeval('vim.stricmp("a\\0", "B\\0")'))
  69. eq(-1, funcs.luaeval('vim.stricmp("A\\0", "b\\0")'))
  70. eq(-1, funcs.luaeval('vim.stricmp("a\\0", "b\\0")'))
  71. eq(-1, funcs.luaeval('vim.stricmp("A\\0", "B\\0")'))
  72. eq(-1, funcs.luaeval('vim.stricmp("\\0a", "\\0B")'))
  73. eq(-1, funcs.luaeval('vim.stricmp("\\0A", "\\0b")'))
  74. eq(-1, funcs.luaeval('vim.stricmp("\\0a", "\\0b")'))
  75. eq(-1, funcs.luaeval('vim.stricmp("\\0A", "\\0B")'))
  76. eq(-1, funcs.luaeval('vim.stricmp("\\0a\\0", "\\0B\\0")'))
  77. eq(-1, funcs.luaeval('vim.stricmp("\\0A\\0", "\\0b\\0")'))
  78. eq(-1, funcs.luaeval('vim.stricmp("\\0a\\0", "\\0b\\0")'))
  79. eq(-1, funcs.luaeval('vim.stricmp("\\0A\\0", "\\0B\\0")'))
  80. eq(1, funcs.luaeval('vim.stricmp("c", "B")'))
  81. eq(1, funcs.luaeval('vim.stricmp("C", "b")'))
  82. eq(1, funcs.luaeval('vim.stricmp("c", "b")'))
  83. eq(1, funcs.luaeval('vim.stricmp("C", "B")'))
  84. eq(1, funcs.luaeval('vim.stricmp("\\0", "")'))
  85. eq(1, funcs.luaeval('vim.stricmp("\\0\\0", "\\0")'))
  86. eq(1, funcs.luaeval('vim.stricmp("\\0\\0\\0", "\\0\\0")'))
  87. eq(1, funcs.luaeval('vim.stricmp("\\0\\0\\0\\0", "\\0\\0\\0")'))
  88. eq(1, funcs.luaeval('vim.stricmp("\\0\\0\\0C", "\\0\\0\\0b")'))
  89. eq(1, funcs.luaeval('vim.stricmp("\\0\\0\\0c", "\\0\\0\\0B")'))
  90. eq(1, funcs.luaeval('vim.stricmp("\\0\\0\\0c", "\\0\\0\\0b")'))
  91. eq(1, funcs.luaeval('vim.stricmp("c\\0", "B\\0")'))
  92. eq(1, funcs.luaeval('vim.stricmp("C\\0", "b\\0")'))
  93. eq(1, funcs.luaeval('vim.stricmp("c\\0", "b\\0")'))
  94. eq(1, funcs.luaeval('vim.stricmp("C\\0", "B\\0")'))
  95. eq(1, funcs.luaeval('vim.stricmp("c\\0", "B")'))
  96. eq(1, funcs.luaeval('vim.stricmp("C\\0", "b")'))
  97. eq(1, funcs.luaeval('vim.stricmp("c\\0", "b")'))
  98. eq(1, funcs.luaeval('vim.stricmp("C\\0", "B")'))
  99. eq(1, funcs.luaeval('vim.stricmp("\\0c", "\\0B")'))
  100. eq(1, funcs.luaeval('vim.stricmp("\\0C", "\\0b")'))
  101. eq(1, funcs.luaeval('vim.stricmp("\\0c", "\\0b")'))
  102. eq(1, funcs.luaeval('vim.stricmp("\\0C", "\\0B")'))
  103. eq(1, funcs.luaeval('vim.stricmp("\\0c\\0", "\\0B\\0")'))
  104. eq(1, funcs.luaeval('vim.stricmp("\\0C\\0", "\\0b\\0")'))
  105. eq(1, funcs.luaeval('vim.stricmp("\\0c\\0", "\\0b\\0")'))
  106. eq(1, funcs.luaeval('vim.stricmp("\\0C\\0", "\\0B\\0")'))
  107. end)
  108. it('vim.startswith', function()
  109. eq(true, funcs.luaeval('vim.startswith("123", "1")'))
  110. eq(true, funcs.luaeval('vim.startswith("123", "")'))
  111. eq(true, funcs.luaeval('vim.startswith("123", "123")'))
  112. eq(true, funcs.luaeval('vim.startswith("", "")'))
  113. eq(false, funcs.luaeval('vim.startswith("123", " ")'))
  114. eq(false, funcs.luaeval('vim.startswith("123", "2")'))
  115. eq(false, funcs.luaeval('vim.startswith("123", "1234")'))
  116. matches("prefix: expected string, got nil",
  117. pcall_err(exec_lua, 'return vim.startswith("123", nil)'))
  118. matches("s: expected string, got nil",
  119. pcall_err(exec_lua, 'return vim.startswith(nil, "123")'))
  120. end)
  121. it('vim.endswith', function()
  122. eq(true, funcs.luaeval('vim.endswith("123", "3")'))
  123. eq(true, funcs.luaeval('vim.endswith("123", "")'))
  124. eq(true, funcs.luaeval('vim.endswith("123", "123")'))
  125. eq(true, funcs.luaeval('vim.endswith("", "")'))
  126. eq(false, funcs.luaeval('vim.endswith("123", " ")'))
  127. eq(false, funcs.luaeval('vim.endswith("123", "2")'))
  128. eq(false, funcs.luaeval('vim.endswith("123", "1234")'))
  129. matches("suffix: expected string, got nil",
  130. pcall_err(exec_lua, 'return vim.endswith("123", nil)'))
  131. matches("s: expected string, got nil",
  132. pcall_err(exec_lua, 'return vim.endswith(nil, "123")'))
  133. end)
  134. it("vim.str_utfindex/str_byteindex", function()
  135. exec_lua([[_G.test_text = "xy åäö ɧ 汉语 ↥ 🤦x🦄 å بِيَّ"]])
  136. local indicies32 = {[0]=0,1,2,3,5,7,9,10,12,13,16,19,20,23,24,28,29,33,34,35,37,38,40,42,44,46,48}
  137. local indicies16 = {[0]=0,1,2,3,5,7,9,10,12,13,16,19,20,23,24,28,28,29,33,33,34,35,37,38,40,42,44,46,48}
  138. for i,k in pairs(indicies32) do
  139. eq(k, exec_lua("return vim.str_byteindex(_G.test_text, ...)", i), i)
  140. end
  141. for i,k in pairs(indicies16) do
  142. eq(k, exec_lua("return vim.str_byteindex(_G.test_text, ..., true)", i), i)
  143. end
  144. local i32, i16 = 0, 0
  145. for k = 0,48 do
  146. if indicies32[i32] < k then
  147. i32 = i32 + 1
  148. end
  149. if indicies16[i16] < k then
  150. i16 = i16 + 1
  151. if indicies16[i16+1] == indicies16[i16] then
  152. i16 = i16 + 1
  153. end
  154. end
  155. eq({i32, i16}, exec_lua("return {vim.str_utfindex(_G.test_text, ...)}", k), k)
  156. end
  157. end)
  158. it("vim.str_utf_start", function()
  159. exec_lua([[_G.test_text = "xy åäö ɧ 汉语 ↥ 🤦x🦄 å بِيَّ"]])
  160. local expected_positions = {0,0,0,0,-1,0,-1,0,-1,0,0,-1,0,0,-1,-2,0,-1,-2,0,0,-1,-2,0,0,-1,-2,-3,0,0,-1,-2,-3,0,0,0,-1,0,0,-1,0,-1,0,-1,0,-1,0,-1}
  161. eq(expected_positions, exec_lua([[
  162. local start_codepoint_positions = {}
  163. for idx = 1, #_G.test_text do
  164. table.insert(start_codepoint_positions, vim.str_utf_start(_G.test_text, idx))
  165. end
  166. return start_codepoint_positions
  167. ]]))
  168. end)
  169. it("vim.str_utf_end", function()
  170. exec_lua([[_G.test_text = "xy åäö ɧ 汉语 ↥ 🤦x🦄 å بِيَّ"]])
  171. local expected_positions = {0,0,0,1,0,1,0,1,0,0,1,0,0,2,1,0,2,1,0,0,2,1,0,0,3,2,1,0,0,3,2,1,0,0,0,1,0,0,1,0,1,0,1,0,1,0,1,0 }
  172. eq(expected_positions, exec_lua([[
  173. local end_codepoint_positions = {}
  174. for idx = 1, #_G.test_text do
  175. table.insert(end_codepoint_positions, vim.str_utf_end(_G.test_text, idx))
  176. end
  177. return end_codepoint_positions
  178. ]]))
  179. end)
  180. it("vim.str_utf_pos", function()
  181. exec_lua([[_G.test_text = "xy åäö ɧ 汉语 ↥ 🤦x🦄 å بِيَّ"]])
  182. local expected_positions = { 1,2,3,4,6,8,10,11,13,14,17,20,21,24,25,29,30,34,35,36,38,39,41,43,45,47 }
  183. eq(expected_positions, exec_lua("return vim.str_utf_pos(_G.test_text)"))
  184. end)
  185. it("vim.schedule", function()
  186. exec_lua([[
  187. test_table = {}
  188. vim.schedule(function()
  189. table.insert(test_table, "xx")
  190. end)
  191. table.insert(test_table, "yy")
  192. ]])
  193. eq({"yy","xx"}, exec_lua("return test_table"))
  194. -- Validates args.
  195. matches('vim.schedule: expected function',
  196. pcall_err(exec_lua, "vim.schedule('stringly')"))
  197. matches('vim.schedule: expected function',
  198. pcall_err(exec_lua, "vim.schedule()"))
  199. exec_lua([[
  200. vim.schedule(function()
  201. error("big failure\nvery async")
  202. end)
  203. ]])
  204. feed("<cr>")
  205. matches('big failure\nvery async', remove_trace(eval("v:errmsg")))
  206. local screen = Screen.new(60,5)
  207. screen:set_default_attr_ids({
  208. [1] = {bold = true, foreground = Screen.colors.Blue1},
  209. [2] = {bold = true, reverse = true},
  210. [3] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
  211. [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
  212. })
  213. screen:attach()
  214. screen:expect{grid=[[
  215. ^ |
  216. {1:~ }|
  217. {1:~ }|
  218. {1:~ }|
  219. |
  220. ]]}
  221. -- nvim_command causes a vimL exception, check that it is properly caught
  222. -- and propagated as an error message in async contexts.. #10809
  223. exec_lua([[
  224. vim.schedule(function()
  225. vim.api.nvim_command(":echo 'err")
  226. end)
  227. ]])
  228. screen:expect{grid=[[
  229. {3:stack traceback:} |
  230. {3: [C]: in function 'nvim_command'} |
  231. {3: [string "<nvim>"]:2: in function <[string "<nvim>"]:}|
  232. {3:1>} |
  233. {4:Press ENTER or type command to continue}^ |
  234. ]]}
  235. end)
  236. it("vim.split", function()
  237. local split = function(str, sep, kwargs)
  238. return exec_lua('return vim.split(...)', str, sep, kwargs)
  239. end
  240. local tests = {
  241. { "a,b", ",", false, false, { 'a', 'b' } },
  242. { ":aa::bb:", ":", false, false, { '', 'aa', '', 'bb', '' } },
  243. { ":aa::bb:", ":", false, true, { 'aa', '', 'bb' } },
  244. { "::ee::ff:", ":", false, false, { '', '', 'ee', '', 'ff', '' } },
  245. { "::ee::ff:", ":", false, true, { 'ee', '', 'ff' } },
  246. { "ab", ".", false, false, { '', '', '' } },
  247. { "a1b2c", "[0-9]", false, false, { 'a', 'b', 'c' } },
  248. { "xy", "", false, false, { 'x', 'y' } },
  249. { "here be dragons", " ", false, false, { "here", "be", "dragons"} },
  250. { "axaby", "ab?", false, false, { '', 'x', 'y' } },
  251. { "f v2v v3v w2w ", "([vw])2%1", false, false, { 'f ', ' v3v ', ' ' } },
  252. { "", "", false, false, {} },
  253. { "", "a", false, false, { '' } },
  254. { "x*yz*oo*l", "*", true, false, { 'x', 'yz', 'oo', 'l' } },
  255. }
  256. for _, t in ipairs(tests) do
  257. eq(t[5], split(t[1], t[2], {plain=t[3], trimempty=t[4]}))
  258. end
  259. -- Test old signature
  260. eq({'x', 'yz', 'oo', 'l'}, split("x*yz*oo*l", "*", true))
  261. local loops = {
  262. { "abc", ".-" },
  263. }
  264. for _, t in ipairs(loops) do
  265. matches("Infinite loop detected", pcall_err(split, t[1], t[2]))
  266. end
  267. -- Validates args.
  268. eq(true, pcall(split, 'string', 'string'))
  269. matches('s: expected string, got number',
  270. pcall_err(split, 1, 'string'))
  271. matches('sep: expected string, got number',
  272. pcall_err(split, 'string', 1))
  273. matches('kwargs: expected table, got number',
  274. pcall_err(split, 'string', 'string', 1))
  275. end)
  276. it('vim.trim', function()
  277. local trim = function(s)
  278. return exec_lua('return vim.trim(...)', s)
  279. end
  280. local trims = {
  281. { " a", "a" },
  282. { " b ", "b" },
  283. { "\tc" , "c" },
  284. { "r\n", "r" },
  285. }
  286. for _, t in ipairs(trims) do
  287. assert(t[2], trim(t[1]))
  288. end
  289. -- Validates args.
  290. matches('s: expected string, got number',
  291. pcall_err(trim, 2))
  292. end)
  293. it('vim.inspect', function()
  294. -- just make sure it basically works, it has its own test suite
  295. local inspect = function(t, opts)
  296. return exec_lua('return vim.inspect(...)', t, opts)
  297. end
  298. eq('2', inspect(2))
  299. eq('{+a = {+b = 1+}+}',
  300. inspect({ a = { b = 1 } }, { newline = '+', indent = '' }))
  301. -- special value vim.inspect.KEY works
  302. eq('{ KEY_a = "x", KEY_b = "y"}', exec_lua([[
  303. return vim.inspect({a="x", b="y"}, {newline = '', process = function(item, path)
  304. if path[#path] == vim.inspect.KEY then
  305. return 'KEY_'..item
  306. end
  307. return item
  308. end})
  309. ]]))
  310. end)
  311. it("vim.deepcopy", function()
  312. ok(exec_lua([[
  313. local a = { x = { 1, 2 }, y = 5}
  314. local b = vim.deepcopy(a)
  315. return b.x[1] == 1 and b.x[2] == 2 and b.y == 5 and vim.tbl_count(b) == 2
  316. and tostring(a) ~= tostring(b)
  317. ]]))
  318. ok(exec_lua([[
  319. local a = {}
  320. local b = vim.deepcopy(a)
  321. return vim.tbl_islist(b) and vim.tbl_count(b) == 0 and tostring(a) ~= tostring(b)
  322. ]]))
  323. ok(exec_lua([[
  324. local a = vim.empty_dict()
  325. local b = vim.deepcopy(a)
  326. return not vim.tbl_islist(b) and vim.tbl_count(b) == 0
  327. ]]))
  328. ok(exec_lua([[
  329. local a = {x = vim.empty_dict(), y = {}}
  330. local b = vim.deepcopy(a)
  331. return not vim.tbl_islist(b.x) and vim.tbl_islist(b.y)
  332. and vim.tbl_count(b) == 2
  333. and tostring(a) ~= tostring(b)
  334. ]]))
  335. ok(exec_lua([[
  336. local f1 = function() return 1 end
  337. local f2 = function() return 2 end
  338. local t1 = {f = f1}
  339. local t2 = vim.deepcopy(t1)
  340. t1.f = f2
  341. return t1.f() ~= t2.f()
  342. ]]))
  343. ok(exec_lua([[
  344. local t1 = {a = 5}
  345. t1.self = t1
  346. local t2 = vim.deepcopy(t1)
  347. return t2.self == t2 and t2.self ~= t1
  348. ]]))
  349. ok(exec_lua([[
  350. local mt = {mt=true}
  351. local t1 = setmetatable({a = 5}, mt)
  352. local t2 = vim.deepcopy(t1)
  353. return getmetatable(t2) == mt
  354. ]]))
  355. matches('Cannot deepcopy object of type thread',
  356. pcall_err(exec_lua, [[
  357. local thread = coroutine.create(function () return 0 end)
  358. local t = {thr = thread}
  359. vim.deepcopy(t)
  360. ]]))
  361. end)
  362. it('vim.pesc', function()
  363. eq('foo%-bar', exec_lua([[return vim.pesc('foo-bar')]]))
  364. eq('foo%%%-bar', exec_lua([[return vim.pesc(vim.pesc('foo-bar'))]]))
  365. -- Validates args.
  366. matches('s: expected string, got number',
  367. pcall_err(exec_lua, [[return vim.pesc(2)]]))
  368. end)
  369. it('vim.tbl_keys', function()
  370. eq({}, exec_lua("return vim.tbl_keys({})"))
  371. for _, v in pairs(exec_lua("return vim.tbl_keys({'a', 'b', 'c'})")) do
  372. eq(true, exec_lua("return vim.tbl_contains({ 1, 2, 3 }, ...)", v))
  373. end
  374. for _, v in pairs(exec_lua("return vim.tbl_keys({a=1, b=2, c=3})")) do
  375. eq(true, exec_lua("return vim.tbl_contains({ 'a', 'b', 'c' }, ...)", v))
  376. end
  377. end)
  378. it('vim.tbl_values', function()
  379. eq({}, exec_lua("return vim.tbl_values({})"))
  380. for _, v in pairs(exec_lua("return vim.tbl_values({'a', 'b', 'c'})")) do
  381. eq(true, exec_lua("return vim.tbl_contains({ 'a', 'b', 'c' }, ...)", v))
  382. end
  383. for _, v in pairs(exec_lua("return vim.tbl_values({a=1, b=2, c=3})")) do
  384. eq(true, exec_lua("return vim.tbl_contains({ 1, 2, 3 }, ...)", v))
  385. end
  386. end)
  387. it('vim.tbl_map', function()
  388. eq({}, exec_lua([[
  389. return vim.tbl_map(function(v) return v * 2 end, {})
  390. ]]))
  391. eq({2, 4, 6}, exec_lua([[
  392. return vim.tbl_map(function(v) return v * 2 end, {1, 2, 3})
  393. ]]))
  394. eq({{i=2}, {i=4}, {i=6}}, exec_lua([[
  395. return vim.tbl_map(function(v) return { i = v.i * 2 } end, {{i=1}, {i=2}, {i=3}})
  396. ]]))
  397. end)
  398. it('vim.tbl_filter', function()
  399. eq({}, exec_lua([[
  400. return vim.tbl_filter(function(v) return (v % 2) == 0 end, {})
  401. ]]))
  402. eq({2}, exec_lua([[
  403. return vim.tbl_filter(function(v) return (v % 2) == 0 end, {1, 2, 3})
  404. ]]))
  405. eq({{i=2}}, exec_lua([[
  406. return vim.tbl_filter(function(v) return (v.i % 2) == 0 end, {{i=1}, {i=2}, {i=3}})
  407. ]]))
  408. end)
  409. it('vim.tbl_islist', function()
  410. eq(true, exec_lua("return vim.tbl_islist({})"))
  411. eq(false, exec_lua("return vim.tbl_islist(vim.empty_dict())"))
  412. eq(true, exec_lua("return vim.tbl_islist({'a', 'b', 'c'})"))
  413. eq(false, exec_lua("return vim.tbl_islist({'a', '32', a='hello', b='baz'})"))
  414. eq(false, exec_lua("return vim.tbl_islist({1, a='hello', b='baz'})"))
  415. eq(false, exec_lua("return vim.tbl_islist({a='hello', b='baz', 1})"))
  416. eq(false, exec_lua("return vim.tbl_islist({1, 2, nil, a='hello'})"))
  417. end)
  418. it('vim.tbl_isempty', function()
  419. eq(true, exec_lua("return vim.tbl_isempty({})"))
  420. eq(false, exec_lua("return vim.tbl_isempty({ 1, 2, 3 })"))
  421. eq(false, exec_lua("return vim.tbl_isempty({a=1, b=2, c=3})"))
  422. end)
  423. it('vim.tbl_get', function()
  424. eq(true, exec_lua("return vim.tbl_get({ test = { nested_test = true }}, 'test', 'nested_test')"))
  425. eq(NIL, exec_lua("return vim.tbl_get({ unindexable = true }, 'unindexable', 'missing_key')"))
  426. eq(NIL, exec_lua("return vim.tbl_get({ unindexable = 1 }, 'unindexable', 'missing_key')"))
  427. eq(NIL, exec_lua("return vim.tbl_get({ unindexable = coroutine.create(function () end) }, 'unindexable', 'missing_key')"))
  428. eq(NIL, exec_lua("return vim.tbl_get({ unindexable = function () end }, 'unindexable', 'missing_key')"))
  429. eq(NIL, exec_lua("return vim.tbl_get({}, 'missing_key')"))
  430. eq(NIL, exec_lua("return vim.tbl_get({})"))
  431. end)
  432. it('vim.tbl_extend', function()
  433. ok(exec_lua([[
  434. local a = {x = 1}
  435. local b = {y = 2}
  436. local c = vim.tbl_extend("keep", a, b)
  437. return c.x == 1 and b.y == 2 and vim.tbl_count(c) == 2
  438. ]]))
  439. ok(exec_lua([[
  440. local a = {x = 1}
  441. local b = {y = 2}
  442. local c = {z = 3}
  443. local d = vim.tbl_extend("keep", a, b, c)
  444. return d.x == 1 and d.y == 2 and d.z == 3 and vim.tbl_count(d) == 3
  445. ]]))
  446. ok(exec_lua([[
  447. local a = {x = 1}
  448. local b = {x = 3}
  449. local c = vim.tbl_extend("keep", a, b)
  450. return c.x == 1 and vim.tbl_count(c) == 1
  451. ]]))
  452. ok(exec_lua([[
  453. local a = {x = 1}
  454. local b = {x = 3}
  455. local c = vim.tbl_extend("force", a, b)
  456. return c.x == 3 and vim.tbl_count(c) == 1
  457. ]]))
  458. ok(exec_lua([[
  459. local a = vim.empty_dict()
  460. local b = {}
  461. local c = vim.tbl_extend("keep", a, b)
  462. return not vim.tbl_islist(c) and vim.tbl_count(c) == 0
  463. ]]))
  464. ok(exec_lua([[
  465. local a = {}
  466. local b = vim.empty_dict()
  467. local c = vim.tbl_extend("keep", a, b)
  468. return vim.tbl_islist(c) and vim.tbl_count(c) == 0
  469. ]]))
  470. ok(exec_lua([[
  471. local a = {x = {a = 1, b = 2}}
  472. local b = {x = {a = 2, c = {y = 3}}}
  473. local c = vim.tbl_extend("keep", a, b)
  474. local count = 0
  475. for _ in pairs(c) do count = count + 1 end
  476. return c.x.a == 1 and c.x.b == 2 and c.x.c == nil and count == 1
  477. ]]))
  478. matches('invalid "behavior": nil',
  479. pcall_err(exec_lua, [[
  480. return vim.tbl_extend()
  481. ]])
  482. )
  483. matches('wrong number of arguments %(given 1, expected at least 3%)',
  484. pcall_err(exec_lua, [[
  485. return vim.tbl_extend("keep")
  486. ]])
  487. )
  488. matches('wrong number of arguments %(given 2, expected at least 3%)',
  489. pcall_err(exec_lua, [[
  490. return vim.tbl_extend("keep", {})
  491. ]])
  492. )
  493. end)
  494. it('vim.tbl_deep_extend', function()
  495. ok(exec_lua([[
  496. local a = {x = {a = 1, b = 2}}
  497. local b = {x = {a = 2, c = {y = 3}}}
  498. local c = vim.tbl_deep_extend("keep", a, b)
  499. local count = 0
  500. for _ in pairs(c) do count = count + 1 end
  501. return c.x.a == 1 and c.x.b == 2 and c.x.c.y == 3 and count == 1
  502. ]]))
  503. ok(exec_lua([[
  504. local a = {x = {a = 1, b = 2}}
  505. local b = {x = {a = 2, c = {y = 3}}}
  506. local c = vim.tbl_deep_extend("force", a, b)
  507. local count = 0
  508. for _ in pairs(c) do count = count + 1 end
  509. return c.x.a == 2 and c.x.b == 2 and c.x.c.y == 3 and count == 1
  510. ]]))
  511. ok(exec_lua([[
  512. local a = {x = {a = 1, b = 2}}
  513. local b = {x = {a = 2, c = {y = 3}}}
  514. local c = {x = {c = 4, d = {y = 4}}}
  515. local d = vim.tbl_deep_extend("keep", a, b, c)
  516. local count = 0
  517. for _ in pairs(c) do count = count + 1 end
  518. return d.x.a == 1 and d.x.b == 2 and d.x.c.y == 3 and d.x.d.y == 4 and count == 1
  519. ]]))
  520. ok(exec_lua([[
  521. local a = {x = {a = 1, b = 2}}
  522. local b = {x = {a = 2, c = {y = 3}}}
  523. local c = {x = {c = 4, d = {y = 4}}}
  524. local d = vim.tbl_deep_extend("force", a, b, c)
  525. local count = 0
  526. for _ in pairs(c) do count = count + 1 end
  527. return d.x.a == 2 and d.x.b == 2 and d.x.c == 4 and d.x.d.y == 4 and count == 1
  528. ]]))
  529. ok(exec_lua([[
  530. local a = vim.empty_dict()
  531. local b = {}
  532. local c = vim.tbl_deep_extend("keep", a, b)
  533. local count = 0
  534. for _ in pairs(c) do count = count + 1 end
  535. return not vim.tbl_islist(c) and count == 0
  536. ]]))
  537. ok(exec_lua([[
  538. local a = {}
  539. local b = vim.empty_dict()
  540. local c = vim.tbl_deep_extend("keep", a, b)
  541. local count = 0
  542. for _ in pairs(c) do count = count + 1 end
  543. return vim.tbl_islist(c) and count == 0
  544. ]]))
  545. eq(exec_lua([[
  546. local a = { a = { b = 1 } }
  547. local b = { a = {} }
  548. return vim.tbl_deep_extend("force", a, b)
  549. ]]), {a = {b = 1}})
  550. eq(exec_lua([[
  551. local a = { a = 123 }
  552. local b = { a = { b = 1} }
  553. return vim.tbl_deep_extend("force", a, b)
  554. ]]), {a = {b = 1}})
  555. ok(exec_lua([[
  556. local a = { a = {[2] = 3} }
  557. local b = { a = {[3] = 3} }
  558. local c = vim.tbl_deep_extend("force", a, b)
  559. return vim.deep_equal(c, {a = {[3] = 3}})
  560. ]]))
  561. eq(exec_lua([[
  562. local a = { a = { b = 1} }
  563. local b = { a = 123 }
  564. return vim.tbl_deep_extend("force", a, b)
  565. ]]), {a = 123 })
  566. matches('invalid "behavior": nil',
  567. pcall_err(exec_lua, [[
  568. return vim.tbl_deep_extend()
  569. ]])
  570. )
  571. matches('wrong number of arguments %(given 1, expected at least 3%)',
  572. pcall_err(exec_lua, [[
  573. return vim.tbl_deep_extend("keep")
  574. ]])
  575. )
  576. matches('wrong number of arguments %(given 2, expected at least 3%)',
  577. pcall_err(exec_lua, [[
  578. return vim.tbl_deep_extend("keep", {})
  579. ]])
  580. )
  581. end)
  582. it('vim.tbl_count', function()
  583. eq(0, exec_lua [[ return vim.tbl_count({}) ]])
  584. eq(0, exec_lua [[ return vim.tbl_count(vim.empty_dict()) ]])
  585. eq(0, exec_lua [[ return vim.tbl_count({nil}) ]])
  586. eq(0, exec_lua [[ return vim.tbl_count({a=nil}) ]])
  587. eq(1, exec_lua [[ return vim.tbl_count({1}) ]])
  588. eq(2, exec_lua [[ return vim.tbl_count({1, 2}) ]])
  589. eq(2, exec_lua [[ return vim.tbl_count({1, nil, 3}) ]])
  590. eq(1, exec_lua [[ return vim.tbl_count({a=1}) ]])
  591. eq(2, exec_lua [[ return vim.tbl_count({a=1, b=2}) ]])
  592. eq(2, exec_lua [[ return vim.tbl_count({a=1, b=nil, c=3}) ]])
  593. end)
  594. it('vim.deep_equal', function()
  595. eq(true, exec_lua [[ return vim.deep_equal({a=1}, {a=1}) ]])
  596. eq(true, exec_lua [[ return vim.deep_equal({a={b=1}}, {a={b=1}}) ]])
  597. eq(true, exec_lua [[ return vim.deep_equal({a={b={nil}}}, {a={b={}}}) ]])
  598. eq(true, exec_lua [[ return vim.deep_equal({a=1, [5]=5}, {nil,nil,nil,nil,5,a=1}) ]])
  599. eq(false, exec_lua [[ return vim.deep_equal(1, {nil,nil,nil,nil,5,a=1}) ]])
  600. eq(false, exec_lua [[ return vim.deep_equal(1, 3) ]])
  601. eq(false, exec_lua [[ return vim.deep_equal(nil, 3) ]])
  602. eq(false, exec_lua [[ return vim.deep_equal({a=1}, {a=2}) ]])
  603. end)
  604. it('vim.list_extend', function()
  605. eq({1,2,3}, exec_lua [[ return vim.list_extend({1}, {2,3}) ]])
  606. matches('src: expected table, got nil',
  607. pcall_err(exec_lua, [[ return vim.list_extend({1}, nil) ]]))
  608. eq({1,2}, exec_lua [[ return vim.list_extend({1}, {2;a=1}) ]])
  609. eq(true, exec_lua [[ local a = {1} return vim.list_extend(a, {2;a=1}) == a ]])
  610. eq({2}, exec_lua [[ return vim.list_extend({}, {2;a=1}, 1) ]])
  611. eq({}, exec_lua [[ return vim.list_extend({}, {2;a=1}, 2) ]])
  612. eq({}, exec_lua [[ return vim.list_extend({}, {2;a=1}, 1, -1) ]])
  613. eq({2}, exec_lua [[ return vim.list_extend({}, {2;a=1}, -1, 2) ]])
  614. end)
  615. it('vim.tbl_add_reverse_lookup', function()
  616. eq(true, exec_lua [[
  617. local a = { A = 1 }
  618. vim.tbl_add_reverse_lookup(a)
  619. return vim.deep_equal(a, { A = 1; [1] = 'A'; })
  620. ]])
  621. -- Throw an error for trying to do it twice (run into an existing key)
  622. local code = [[
  623. local res = {}
  624. local a = { A = 1 }
  625. vim.tbl_add_reverse_lookup(a)
  626. assert(vim.deep_equal(a, { A = 1; [1] = 'A'; }))
  627. vim.tbl_add_reverse_lookup(a)
  628. ]]
  629. matches('The reverse lookup found an existing value for "[1A]" while processing key "[1A]"$',
  630. pcall_err(exec_lua, code))
  631. end)
  632. it('vim.call, vim.fn', function()
  633. eq(true, exec_lua([[return vim.call('sin', 0.0) == 0.0 ]]))
  634. eq(true, exec_lua([[return vim.fn.sin(0.0) == 0.0 ]]))
  635. -- compat: nvim_call_function uses "special" value for vimL float
  636. eq(false, exec_lua([[return vim.api.nvim_call_function('sin', {0.0}) == 0.0 ]]))
  637. exec([[
  638. func! FooFunc(test)
  639. let g:test = a:test
  640. return {}
  641. endfunc
  642. func! VarArg(...)
  643. return a:000
  644. endfunc
  645. func! Nilly()
  646. return [v:null, v:null]
  647. endfunc
  648. ]])
  649. eq(true, exec_lua([[return next(vim.fn.FooFunc(3)) == nil ]]))
  650. eq(3, eval("g:test"))
  651. -- compat: nvim_call_function uses "special" value for empty dict
  652. eq(true, exec_lua([[return next(vim.api.nvim_call_function("FooFunc", {5})) == true ]]))
  653. eq(5, eval("g:test"))
  654. eq({2, "foo", true}, exec_lua([[return vim.fn.VarArg(2, "foo", true)]]))
  655. eq(true, exec_lua([[
  656. local x = vim.fn.Nilly()
  657. return #x == 2 and x[1] == vim.NIL and x[2] == vim.NIL
  658. ]]))
  659. eq({NIL, NIL}, exec_lua([[return vim.fn.Nilly()]]))
  660. -- error handling
  661. eq({false, 'Vim:E897: List or Blob required'}, exec_lua([[return {pcall(vim.fn.add, "aa", "bb")}]]))
  662. -- conversion between LuaRef and Vim Funcref
  663. eq(true, exec_lua([[
  664. local x = vim.fn.VarArg(function() return 'foo' end, function() return 'bar' end)
  665. return #x == 2 and x[1]() == 'foo' and x[2]() == 'bar'
  666. ]]))
  667. end)
  668. it('vim.fn should error when calling API function', function()
  669. matches('Tried to call API function with vim.fn: use vim.api.nvim_get_current_line instead',
  670. pcall_err(exec_lua, "vim.fn.nvim_get_current_line()"))
  671. end)
  672. it('vim.rpcrequest and vim.rpcnotify', function()
  673. exec_lua([[
  674. chan = vim.fn.jobstart({'cat'}, {rpc=true})
  675. vim.rpcrequest(chan, 'nvim_set_current_line', 'meow')
  676. ]])
  677. eq('meow', meths.get_current_line())
  678. command("let x = [3, 'aa', v:true, v:null]")
  679. eq(true, exec_lua([[
  680. ret = vim.rpcrequest(chan, 'nvim_get_var', 'x')
  681. return #ret == 4 and ret[1] == 3 and ret[2] == 'aa' and ret[3] == true and ret[4] == vim.NIL
  682. ]]))
  683. eq({3, 'aa', true, NIL}, exec_lua([[return ret]]))
  684. eq({{}, {}, false, true}, exec_lua([[
  685. vim.rpcrequest(chan, 'nvim_exec', 'let xx = {}\nlet yy = []', false)
  686. local dict = vim.rpcrequest(chan, 'nvim_eval', 'xx')
  687. local list = vim.rpcrequest(chan, 'nvim_eval', 'yy')
  688. return {dict, list, vim.tbl_islist(dict), vim.tbl_islist(list)}
  689. ]]))
  690. exec_lua([[
  691. vim.rpcrequest(chan, 'nvim_set_var', 'aa', {})
  692. vim.rpcrequest(chan, 'nvim_set_var', 'bb', vim.empty_dict())
  693. ]])
  694. eq({1, 1}, eval('[type(g:aa) == type([]), type(g:bb) == type({})]'))
  695. -- error handling
  696. eq({false, 'Invalid channel: 23'},
  697. exec_lua([[return {pcall(vim.rpcrequest, 23, 'foo')}]]))
  698. eq({false, 'Invalid channel: 23'},
  699. exec_lua([[return {pcall(vim.rpcnotify, 23, 'foo')}]]))
  700. eq({false, 'Vim:E121: Undefined variable: foobar'},
  701. exec_lua([[return {pcall(vim.rpcrequest, chan, 'nvim_eval', "foobar")}]]))
  702. -- rpcnotify doesn't wait on request
  703. eq('meow', exec_lua([[
  704. vim.rpcnotify(chan, 'nvim_set_current_line', 'foo')
  705. return vim.api.nvim_get_current_line()
  706. ]]))
  707. retry(10, nil, function()
  708. eq('foo', meths.get_current_line())
  709. end)
  710. local screen = Screen.new(50,7)
  711. screen:set_default_attr_ids({
  712. [1] = {bold = true, foreground = Screen.colors.Blue1},
  713. [2] = {bold = true, reverse = true},
  714. [3] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
  715. [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
  716. })
  717. screen:attach()
  718. exec_lua([[
  719. timer = vim.loop.new_timer()
  720. timer:start(20, 0, function ()
  721. -- notify ok (executed later when safe)
  722. vim.rpcnotify(chan, 'nvim_set_var', 'yy', {3, vim.NIL})
  723. -- rpcrequest an error
  724. vim.rpcrequest(chan, 'nvim_set_current_line', 'bork')
  725. end)
  726. ]])
  727. screen:expect{grid=[[
  728. {3:[string "<nvim>"]:6: E5560: rpcrequest must not be}|
  729. {3: called in a lua loop callback} |
  730. {3:stack traceback:} |
  731. {3: [C]: in function 'rpcrequest'} |
  732. {3: [string "<nvim>"]:6: in function <[string }|
  733. {3:"<nvim>"]:2>} |
  734. {4:Press ENTER or type command to continue}^ |
  735. ]]}
  736. feed('<cr>')
  737. eq({3, NIL}, meths.get_var('yy'))
  738. exec_lua([[timer:close()]])
  739. end)
  740. it('vim.empty_dict()', function()
  741. eq({true, false, true, true}, exec_lua([[
  742. vim.api.nvim_set_var('listy', {})
  743. vim.api.nvim_set_var('dicty', vim.empty_dict())
  744. local listy = vim.fn.eval("listy")
  745. local dicty = vim.fn.eval("dicty")
  746. return {vim.tbl_islist(listy), vim.tbl_islist(dicty), next(listy) == nil, next(dicty) == nil}
  747. ]]))
  748. -- vim.empty_dict() gives new value each time
  749. -- equality is not overriden (still by ref)
  750. -- non-empty table uses the usual heuristics (ignores the tag)
  751. eq({false, {"foo"}, {namey="bar"}}, exec_lua([[
  752. local aa = vim.empty_dict()
  753. local bb = vim.empty_dict()
  754. local equally = (aa == bb)
  755. aa[1] = "foo"
  756. bb["namey"] = "bar"
  757. return {equally, aa, bb}
  758. ]]))
  759. eq("{ {}, vim.empty_dict() }", exec_lua("return vim.inspect({{}, vim.empty_dict()})"))
  760. eq('{}', exec_lua([[ return vim.fn.json_encode(vim.empty_dict()) ]]))
  761. eq('{"a": {}, "b": []}', exec_lua([[ return vim.fn.json_encode({a=vim.empty_dict(), b={}}) ]]))
  762. end)
  763. it('vim.validate', function()
  764. exec_lua("vim.validate{arg1={{}, 'table' }}")
  765. exec_lua("vim.validate{arg1={{}, 't' }}")
  766. exec_lua("vim.validate{arg1={nil, 't', true }}")
  767. exec_lua("vim.validate{arg1={{ foo='foo' }, 't' }}")
  768. exec_lua("vim.validate{arg1={{ 'foo' }, 't' }}")
  769. exec_lua("vim.validate{arg1={'foo', 'string' }}")
  770. exec_lua("vim.validate{arg1={'foo', 's' }}")
  771. exec_lua("vim.validate{arg1={'', 's' }}")
  772. exec_lua("vim.validate{arg1={nil, 's', true }}")
  773. exec_lua("vim.validate{arg1={1, 'number' }}")
  774. exec_lua("vim.validate{arg1={1, 'n' }}")
  775. exec_lua("vim.validate{arg1={0, 'n' }}")
  776. exec_lua("vim.validate{arg1={0.1, 'n' }}")
  777. exec_lua("vim.validate{arg1={nil, 'n', true }}")
  778. exec_lua("vim.validate{arg1={true, 'boolean' }}")
  779. exec_lua("vim.validate{arg1={true, 'b' }}")
  780. exec_lua("vim.validate{arg1={false, 'b' }}")
  781. exec_lua("vim.validate{arg1={nil, 'b', true }}")
  782. exec_lua("vim.validate{arg1={function()end, 'function' }}")
  783. exec_lua("vim.validate{arg1={function()end, 'f' }}")
  784. exec_lua("vim.validate{arg1={nil, 'f', true }}")
  785. exec_lua("vim.validate{arg1={nil, 'nil' }}")
  786. exec_lua("vim.validate{arg1={nil, 'nil', true }}")
  787. exec_lua("vim.validate{arg1={coroutine.create(function()end), 'thread' }}")
  788. exec_lua("vim.validate{arg1={nil, 'thread', true }}")
  789. exec_lua("vim.validate{arg1={{}, 't' }, arg2={ 'foo', 's' }}")
  790. exec_lua("vim.validate{arg1={2, function(a) return (a % 2) == 0 end, 'even number' }}")
  791. exec_lua("vim.validate{arg1={5, {'n', 's'} }, arg2={ 'foo', {'n', 's'} }}")
  792. matches('expected table, got number',
  793. pcall_err(exec_lua, "vim.validate{ 1, 'x' }"))
  794. matches('invalid type name: x',
  795. pcall_err(exec_lua, "vim.validate{ arg1={ 1, 'x' }}"))
  796. matches('invalid type name: 1',
  797. pcall_err(exec_lua, "vim.validate{ arg1={ 1, 1 }}"))
  798. matches('invalid type name: nil',
  799. pcall_err(exec_lua, "vim.validate{ arg1={ 1 }}"))
  800. -- Validated parameters are required by default.
  801. matches('arg1: expected string, got nil',
  802. pcall_err(exec_lua, "vim.validate{ arg1={ nil, 's' }}"))
  803. -- Explicitly required.
  804. matches('arg1: expected string, got nil',
  805. pcall_err(exec_lua, "vim.validate{ arg1={ nil, 's', false }}"))
  806. matches('arg1: expected table, got number',
  807. pcall_err(exec_lua, "vim.validate{arg1={1, 't'}}"))
  808. matches('arg2: expected string, got number',
  809. pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={1, 's'}}"))
  810. matches('arg2: expected string, got nil',
  811. pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}"))
  812. matches('arg2: expected string, got nil',
  813. pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}"))
  814. matches('arg1: expected even number, got 3',
  815. pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end, 'even number'}}"))
  816. matches('arg1: expected %?, got 3',
  817. pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end}}"))
  818. matches('arg1: expected number|string, got nil',
  819. pcall_err(exec_lua, "vim.validate{ arg1={ nil, {'n', 's'} }}"))
  820. -- Pass an additional message back.
  821. matches('arg1: expected %?, got 3. Info: TEST_MSG',
  822. pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1, 'TEST_MSG' end}}"))
  823. end)
  824. it('vim.is_callable', function()
  825. eq(true, exec_lua("return vim.is_callable(function()end)"))
  826. eq(true, exec_lua([[
  827. local meta = { __call = function()end }
  828. local function new_callable()
  829. return setmetatable({}, meta)
  830. end
  831. local callable = new_callable()
  832. return vim.is_callable(callable)
  833. ]]))
  834. eq(false, exec_lua("return vim.is_callable(1)"))
  835. eq(false, exec_lua("return vim.is_callable('foo')"))
  836. eq(false, exec_lua("return vim.is_callable({})"))
  837. end)
  838. it('vim.g', function()
  839. exec_lua [[
  840. vim.api.nvim_set_var("testing", "hi")
  841. vim.api.nvim_set_var("other", 123)
  842. vim.api.nvim_set_var("floaty", 5120.1)
  843. vim.api.nvim_set_var("nullvar", vim.NIL)
  844. vim.api.nvim_set_var("to_delete", {hello="world"})
  845. ]]
  846. eq('hi', funcs.luaeval "vim.g.testing")
  847. eq(123, funcs.luaeval "vim.g.other")
  848. eq(5120.1, funcs.luaeval "vim.g.floaty")
  849. eq(NIL, funcs.luaeval "vim.g.nonexistant")
  850. eq(NIL, funcs.luaeval "vim.g.nullvar")
  851. -- lost over RPC, so test locally:
  852. eq({false, true}, exec_lua [[
  853. return {vim.g.nonexistant == vim.NIL, vim.g.nullvar == vim.NIL}
  854. ]])
  855. eq({hello="world"}, funcs.luaeval "vim.g.to_delete")
  856. exec_lua [[
  857. vim.g.to_delete = nil
  858. ]]
  859. eq(NIL, funcs.luaeval "vim.g.to_delete")
  860. matches([[attempt to index .* nil value]],
  861. pcall_err(exec_lua, 'return vim.g[0].testing'))
  862. exec_lua [[
  863. local counter = 0
  864. local function add_counter() counter = counter + 1 end
  865. local function get_counter() return counter end
  866. vim.g.AddCounter = add_counter
  867. vim.g.GetCounter = get_counter
  868. vim.g.funcs = {add = add_counter, get = get_counter}
  869. ]]
  870. eq(0, eval('g:GetCounter()'))
  871. eval('g:AddCounter()')
  872. eq(1, eval('g:GetCounter()'))
  873. eval('g:AddCounter()')
  874. eq(2, eval('g:GetCounter()'))
  875. exec_lua([[vim.g.AddCounter()]])
  876. eq(3, exec_lua([[return vim.g.GetCounter()]]))
  877. exec_lua([[vim.api.nvim_get_var('AddCounter')()]])
  878. eq(4, exec_lua([[return vim.api.nvim_get_var('GetCounter')()]]))
  879. exec_lua([[vim.g.funcs.add()]])
  880. eq(5, exec_lua([[return vim.g.funcs.get()]]))
  881. exec_lua([[vim.api.nvim_get_var('funcs').add()]])
  882. eq(6, exec_lua([[return vim.api.nvim_get_var('funcs').get()]]))
  883. exec_lua [[
  884. local counter = 0
  885. local function add_counter() counter = counter + 1 end
  886. local function get_counter() return counter end
  887. vim.api.nvim_set_var('AddCounter', add_counter)
  888. vim.api.nvim_set_var('GetCounter', get_counter)
  889. vim.api.nvim_set_var('funcs', {add = add_counter, get = get_counter})
  890. ]]
  891. eq(0, eval('g:GetCounter()'))
  892. eval('g:AddCounter()')
  893. eq(1, eval('g:GetCounter()'))
  894. eval('g:AddCounter()')
  895. eq(2, eval('g:GetCounter()'))
  896. exec_lua([[vim.g.AddCounter()]])
  897. eq(3, exec_lua([[return vim.g.GetCounter()]]))
  898. exec_lua([[vim.api.nvim_get_var('AddCounter')()]])
  899. eq(4, exec_lua([[return vim.api.nvim_get_var('GetCounter')()]]))
  900. exec_lua([[vim.g.funcs.add()]])
  901. eq(5, exec_lua([[return vim.g.funcs.get()]]))
  902. exec_lua([[vim.api.nvim_get_var('funcs').add()]])
  903. eq(6, exec_lua([[return vim.api.nvim_get_var('funcs').get()]]))
  904. exec([[
  905. function Test()
  906. endfunction
  907. function s:Test()
  908. endfunction
  909. let g:Unknown_func = function('Test')
  910. let g:Unknown_script_func = function('s:Test')
  911. ]])
  912. eq(NIL, exec_lua([[return vim.g.Unknown_func]]))
  913. eq(NIL, exec_lua([[return vim.g.Unknown_script_func]]))
  914. -- Check if autoload works properly
  915. local pathsep = helpers.get_pathsep()
  916. local xconfig = 'Xhome' .. pathsep .. 'Xconfig'
  917. local xdata = 'Xhome' .. pathsep .. 'Xdata'
  918. local autoload_folder = table.concat({xconfig, 'nvim', 'autoload'}, pathsep)
  919. local autoload_file = table.concat({autoload_folder , 'testload.vim'}, pathsep)
  920. mkdir_p(autoload_folder)
  921. write_file(autoload_file , [[let testload#value = 2]])
  922. clear{ args_rm={'-u'}, env={ XDG_CONFIG_HOME=xconfig, XDG_DATA_HOME=xdata } }
  923. eq(2, exec_lua("return vim.g['testload#value']"))
  924. rmdir('Xhome')
  925. end)
  926. it('vim.b', function()
  927. exec_lua [[
  928. vim.api.nvim_buf_set_var(0, "testing", "hi")
  929. vim.api.nvim_buf_set_var(0, "other", 123)
  930. vim.api.nvim_buf_set_var(0, "floaty", 5120.1)
  931. vim.api.nvim_buf_set_var(0, "nullvar", vim.NIL)
  932. vim.api.nvim_buf_set_var(0, "to_delete", {hello="world"})
  933. BUF = vim.api.nvim_create_buf(false, true)
  934. vim.api.nvim_buf_set_var(BUF, "testing", "bye")
  935. ]]
  936. eq('hi', funcs.luaeval "vim.b.testing")
  937. eq('bye', funcs.luaeval "vim.b[BUF].testing")
  938. eq(123, funcs.luaeval "vim.b.other")
  939. eq(5120.1, funcs.luaeval "vim.b.floaty")
  940. eq(NIL, funcs.luaeval "vim.b.nonexistant")
  941. eq(NIL, funcs.luaeval "vim.b[BUF].nonexistant")
  942. eq(NIL, funcs.luaeval "vim.b.nullvar")
  943. -- lost over RPC, so test locally:
  944. eq({false, true}, exec_lua [[
  945. return {vim.b.nonexistant == vim.NIL, vim.b.nullvar == vim.NIL}
  946. ]])
  947. matches([[attempt to index .* nil value]],
  948. pcall_err(exec_lua, 'return vim.b[BUF][0].testing'))
  949. eq({hello="world"}, funcs.luaeval "vim.b.to_delete")
  950. exec_lua [[
  951. vim.b.to_delete = nil
  952. ]]
  953. eq(NIL, funcs.luaeval "vim.b.to_delete")
  954. exec_lua [[
  955. local counter = 0
  956. local function add_counter() counter = counter + 1 end
  957. local function get_counter() return counter end
  958. vim.b.AddCounter = add_counter
  959. vim.b.GetCounter = get_counter
  960. vim.b.funcs = {add = add_counter, get = get_counter}
  961. ]]
  962. eq(0, eval('b:GetCounter()'))
  963. eval('b:AddCounter()')
  964. eq(1, eval('b:GetCounter()'))
  965. eval('b:AddCounter()')
  966. eq(2, eval('b:GetCounter()'))
  967. exec_lua([[vim.b.AddCounter()]])
  968. eq(3, exec_lua([[return vim.b.GetCounter()]]))
  969. exec_lua([[vim.api.nvim_buf_get_var(0, 'AddCounter')()]])
  970. eq(4, exec_lua([[return vim.api.nvim_buf_get_var(0, 'GetCounter')()]]))
  971. exec_lua([[vim.b.funcs.add()]])
  972. eq(5, exec_lua([[return vim.b.funcs.get()]]))
  973. exec_lua([[vim.api.nvim_buf_get_var(0, 'funcs').add()]])
  974. eq(6, exec_lua([[return vim.api.nvim_buf_get_var(0, 'funcs').get()]]))
  975. exec_lua [[
  976. local counter = 0
  977. local function add_counter() counter = counter + 1 end
  978. local function get_counter() return counter end
  979. vim.api.nvim_buf_set_var(0, 'AddCounter', add_counter)
  980. vim.api.nvim_buf_set_var(0, 'GetCounter', get_counter)
  981. vim.api.nvim_buf_set_var(0, 'funcs', {add = add_counter, get = get_counter})
  982. ]]
  983. eq(0, eval('b:GetCounter()'))
  984. eval('b:AddCounter()')
  985. eq(1, eval('b:GetCounter()'))
  986. eval('b:AddCounter()')
  987. eq(2, eval('b:GetCounter()'))
  988. exec_lua([[vim.b.AddCounter()]])
  989. eq(3, exec_lua([[return vim.b.GetCounter()]]))
  990. exec_lua([[vim.api.nvim_buf_get_var(0, 'AddCounter')()]])
  991. eq(4, exec_lua([[return vim.api.nvim_buf_get_var(0, 'GetCounter')()]]))
  992. exec_lua([[vim.b.funcs.add()]])
  993. eq(5, exec_lua([[return vim.b.funcs.get()]]))
  994. exec_lua([[vim.api.nvim_buf_get_var(0, 'funcs').add()]])
  995. eq(6, exec_lua([[return vim.api.nvim_buf_get_var(0, 'funcs').get()]]))
  996. exec([[
  997. function Test()
  998. endfunction
  999. function s:Test()
  1000. endfunction
  1001. let b:Unknown_func = function('Test')
  1002. let b:Unknown_script_func = function('s:Test')
  1003. ]])
  1004. eq(NIL, exec_lua([[return vim.b.Unknown_func]]))
  1005. eq(NIL, exec_lua([[return vim.b.Unknown_script_func]]))
  1006. exec_lua [[
  1007. vim.cmd "vnew"
  1008. ]]
  1009. eq(NIL, funcs.luaeval "vim.b.testing")
  1010. eq(NIL, funcs.luaeval "vim.b.other")
  1011. eq(NIL, funcs.luaeval "vim.b.nonexistant")
  1012. end)
  1013. it('vim.w', function()
  1014. exec_lua [[
  1015. vim.api.nvim_win_set_var(0, "testing", "hi")
  1016. vim.api.nvim_win_set_var(0, "other", 123)
  1017. vim.api.nvim_win_set_var(0, "to_delete", {hello="world"})
  1018. BUF = vim.api.nvim_create_buf(false, true)
  1019. WIN = vim.api.nvim_open_win(BUF, false, {
  1020. width=10, height=10,
  1021. relative='win', row=0, col=0
  1022. })
  1023. vim.api.nvim_win_set_var(WIN, "testing", "bye")
  1024. ]]
  1025. eq('hi', funcs.luaeval "vim.w.testing")
  1026. eq('bye', funcs.luaeval "vim.w[WIN].testing")
  1027. eq(123, funcs.luaeval "vim.w.other")
  1028. eq(NIL, funcs.luaeval "vim.w.nonexistant")
  1029. eq(NIL, funcs.luaeval "vim.w[WIN].nonexistant")
  1030. matches([[attempt to index .* nil value]],
  1031. pcall_err(exec_lua, 'return vim.w[WIN][0].testing'))
  1032. eq({hello="world"}, funcs.luaeval "vim.w.to_delete")
  1033. exec_lua [[
  1034. vim.w.to_delete = nil
  1035. ]]
  1036. eq(NIL, funcs.luaeval "vim.w.to_delete")
  1037. exec_lua [[
  1038. local counter = 0
  1039. local function add_counter() counter = counter + 1 end
  1040. local function get_counter() return counter end
  1041. vim.w.AddCounter = add_counter
  1042. vim.w.GetCounter = get_counter
  1043. vim.w.funcs = {add = add_counter, get = get_counter}
  1044. ]]
  1045. eq(0, eval('w:GetCounter()'))
  1046. eval('w:AddCounter()')
  1047. eq(1, eval('w:GetCounter()'))
  1048. eval('w:AddCounter()')
  1049. eq(2, eval('w:GetCounter()'))
  1050. exec_lua([[vim.w.AddCounter()]])
  1051. eq(3, exec_lua([[return vim.w.GetCounter()]]))
  1052. exec_lua([[vim.api.nvim_win_get_var(0, 'AddCounter')()]])
  1053. eq(4, exec_lua([[return vim.api.nvim_win_get_var(0, 'GetCounter')()]]))
  1054. exec_lua([[vim.w.funcs.add()]])
  1055. eq(5, exec_lua([[return vim.w.funcs.get()]]))
  1056. exec_lua([[vim.api.nvim_win_get_var(0, 'funcs').add()]])
  1057. eq(6, exec_lua([[return vim.api.nvim_win_get_var(0, 'funcs').get()]]))
  1058. exec_lua [[
  1059. local counter = 0
  1060. local function add_counter() counter = counter + 1 end
  1061. local function get_counter() return counter end
  1062. vim.api.nvim_win_set_var(0, 'AddCounter', add_counter)
  1063. vim.api.nvim_win_set_var(0, 'GetCounter', get_counter)
  1064. vim.api.nvim_win_set_var(0, 'funcs', {add = add_counter, get = get_counter})
  1065. ]]
  1066. eq(0, eval('w:GetCounter()'))
  1067. eval('w:AddCounter()')
  1068. eq(1, eval('w:GetCounter()'))
  1069. eval('w:AddCounter()')
  1070. eq(2, eval('w:GetCounter()'))
  1071. exec_lua([[vim.w.AddCounter()]])
  1072. eq(3, exec_lua([[return vim.w.GetCounter()]]))
  1073. exec_lua([[vim.api.nvim_win_get_var(0, 'AddCounter')()]])
  1074. eq(4, exec_lua([[return vim.api.nvim_win_get_var(0, 'GetCounter')()]]))
  1075. exec_lua([[vim.w.funcs.add()]])
  1076. eq(5, exec_lua([[return vim.w.funcs.get()]]))
  1077. exec_lua([[vim.api.nvim_win_get_var(0, 'funcs').add()]])
  1078. eq(6, exec_lua([[return vim.api.nvim_win_get_var(0, 'funcs').get()]]))
  1079. exec([[
  1080. function Test()
  1081. endfunction
  1082. function s:Test()
  1083. endfunction
  1084. let w:Unknown_func = function('Test')
  1085. let w:Unknown_script_func = function('s:Test')
  1086. ]])
  1087. eq(NIL, exec_lua([[return vim.w.Unknown_func]]))
  1088. eq(NIL, exec_lua([[return vim.w.Unknown_script_func]]))
  1089. exec_lua [[
  1090. vim.cmd "vnew"
  1091. ]]
  1092. eq(NIL, funcs.luaeval "vim.w.testing")
  1093. eq(NIL, funcs.luaeval "vim.w.other")
  1094. eq(NIL, funcs.luaeval "vim.w.nonexistant")
  1095. end)
  1096. it('vim.t', function()
  1097. exec_lua [[
  1098. vim.api.nvim_tabpage_set_var(0, "testing", "hi")
  1099. vim.api.nvim_tabpage_set_var(0, "other", 123)
  1100. vim.api.nvim_tabpage_set_var(0, "to_delete", {hello="world"})
  1101. ]]
  1102. eq('hi', funcs.luaeval "vim.t.testing")
  1103. eq(123, funcs.luaeval "vim.t.other")
  1104. eq(NIL, funcs.luaeval "vim.t.nonexistant")
  1105. eq('hi', funcs.luaeval "vim.t[0].testing")
  1106. eq(123, funcs.luaeval "vim.t[0].other")
  1107. eq(NIL, funcs.luaeval "vim.t[0].nonexistant")
  1108. matches([[attempt to index .* nil value]],
  1109. pcall_err(exec_lua, 'return vim.t[0][0].testing'))
  1110. eq({hello="world"}, funcs.luaeval "vim.t.to_delete")
  1111. exec_lua [[
  1112. vim.t.to_delete = nil
  1113. ]]
  1114. eq(NIL, funcs.luaeval "vim.t.to_delete")
  1115. exec_lua [[
  1116. local counter = 0
  1117. local function add_counter() counter = counter + 1 end
  1118. local function get_counter() return counter end
  1119. vim.t.AddCounter = add_counter
  1120. vim.t.GetCounter = get_counter
  1121. vim.t.funcs = {add = add_counter, get = get_counter}
  1122. ]]
  1123. eq(0, eval('t:GetCounter()'))
  1124. eval('t:AddCounter()')
  1125. eq(1, eval('t:GetCounter()'))
  1126. eval('t:AddCounter()')
  1127. eq(2, eval('t:GetCounter()'))
  1128. exec_lua([[vim.t.AddCounter()]])
  1129. eq(3, exec_lua([[return vim.t.GetCounter()]]))
  1130. exec_lua([[vim.api.nvim_tabpage_get_var(0, 'AddCounter')()]])
  1131. eq(4, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'GetCounter')()]]))
  1132. exec_lua([[vim.t.funcs.add()]])
  1133. eq(5, exec_lua([[return vim.t.funcs.get()]]))
  1134. exec_lua([[vim.api.nvim_tabpage_get_var(0, 'funcs').add()]])
  1135. eq(6, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'funcs').get()]]))
  1136. exec_lua [[
  1137. local counter = 0
  1138. local function add_counter() counter = counter + 1 end
  1139. local function get_counter() return counter end
  1140. vim.api.nvim_tabpage_set_var(0, 'AddCounter', add_counter)
  1141. vim.api.nvim_tabpage_set_var(0, 'GetCounter', get_counter)
  1142. vim.api.nvim_tabpage_set_var(0, 'funcs', {add = add_counter, get = get_counter})
  1143. ]]
  1144. eq(0, eval('t:GetCounter()'))
  1145. eval('t:AddCounter()')
  1146. eq(1, eval('t:GetCounter()'))
  1147. eval('t:AddCounter()')
  1148. eq(2, eval('t:GetCounter()'))
  1149. exec_lua([[vim.t.AddCounter()]])
  1150. eq(3, exec_lua([[return vim.t.GetCounter()]]))
  1151. exec_lua([[vim.api.nvim_tabpage_get_var(0, 'AddCounter')()]])
  1152. eq(4, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'GetCounter')()]]))
  1153. exec_lua([[vim.t.funcs.add()]])
  1154. eq(5, exec_lua([[return vim.t.funcs.get()]]))
  1155. exec_lua([[vim.api.nvim_tabpage_get_var(0, 'funcs').add()]])
  1156. eq(6, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'funcs').get()]]))
  1157. exec_lua [[
  1158. vim.cmd "tabnew"
  1159. ]]
  1160. eq(NIL, funcs.luaeval "vim.t.testing")
  1161. eq(NIL, funcs.luaeval "vim.t.other")
  1162. eq(NIL, funcs.luaeval "vim.t.nonexistant")
  1163. end)
  1164. it('vim.env', function()
  1165. exec_lua [[
  1166. vim.fn.setenv("A", 123)
  1167. ]]
  1168. eq('123', funcs.luaeval "vim.env.A")
  1169. eq(true, funcs.luaeval "vim.env.B == nil")
  1170. end)
  1171. it('vim.v', function()
  1172. eq(funcs.luaeval "vim.api.nvim_get_vvar('progpath')", funcs.luaeval "vim.v.progpath")
  1173. eq(false, funcs.luaeval "vim.v['false']")
  1174. eq(NIL, funcs.luaeval "vim.v.null")
  1175. matches([[attempt to index .* nil value]],
  1176. pcall_err(exec_lua, 'return vim.v[0].progpath'))
  1177. end)
  1178. it('vim.bo', function()
  1179. eq('', funcs.luaeval "vim.bo.filetype")
  1180. exec_lua [[
  1181. vim.api.nvim_buf_set_option(0, "filetype", "markdown")
  1182. BUF = vim.api.nvim_create_buf(false, true)
  1183. vim.api.nvim_buf_set_option(BUF, "modifiable", false)
  1184. ]]
  1185. eq(false, funcs.luaeval "vim.bo.modified")
  1186. eq('markdown', funcs.luaeval "vim.bo.filetype")
  1187. eq(false, funcs.luaeval "vim.bo[BUF].modifiable")
  1188. exec_lua [[
  1189. vim.bo.filetype = ''
  1190. vim.bo[BUF].modifiable = true
  1191. ]]
  1192. eq('', funcs.luaeval "vim.bo.filetype")
  1193. eq(true, funcs.luaeval "vim.bo[BUF].modifiable")
  1194. matches("Invalid option name: 'nosuchopt'$",
  1195. pcall_err(exec_lua, 'return vim.bo.nosuchopt'))
  1196. matches("Expected lua string$",
  1197. pcall_err(exec_lua, 'return vim.bo[0][0].autoread'))
  1198. end)
  1199. it('vim.wo', function()
  1200. exec_lua [[
  1201. vim.api.nvim_win_set_option(0, "cole", 2)
  1202. vim.cmd "split"
  1203. vim.api.nvim_win_set_option(0, "cole", 2)
  1204. ]]
  1205. eq(2, funcs.luaeval "vim.wo.cole")
  1206. exec_lua [[
  1207. vim.wo.conceallevel = 0
  1208. ]]
  1209. eq(0, funcs.luaeval "vim.wo.cole")
  1210. eq(0, funcs.luaeval "vim.wo[0].cole")
  1211. eq(0, funcs.luaeval "vim.wo[1001].cole")
  1212. matches("Invalid option name: 'notanopt'$",
  1213. pcall_err(exec_lua, 'return vim.wo.notanopt'))
  1214. matches("Expected lua string$",
  1215. pcall_err(exec_lua, 'return vim.wo[0][0].list'))
  1216. eq(2, funcs.luaeval "vim.wo[1000].cole")
  1217. exec_lua [[
  1218. vim.wo[1000].cole = 0
  1219. ]]
  1220. eq(0, funcs.luaeval "vim.wo[1000].cole")
  1221. end)
  1222. describe('vim.opt', function()
  1223. -- TODO: We still need to write some tests for optlocal, opt and then getting the options
  1224. -- Probably could also do some stuff with getting things from viml side as well to confirm behavior is the same.
  1225. it('should allow setting number values', function()
  1226. local scrolloff = exec_lua [[
  1227. vim.opt.scrolloff = 10
  1228. return vim.o.scrolloff
  1229. ]]
  1230. eq(scrolloff, 10)
  1231. end)
  1232. pending('should handle STUPID window things', function()
  1233. local result = exec_lua [[
  1234. local result = {}
  1235. table.insert(result, vim.api.nvim_get_option('scrolloff'))
  1236. table.insert(result, vim.api.nvim_win_get_option(0, 'scrolloff'))
  1237. return result
  1238. ]]
  1239. eq({}, result)
  1240. end)
  1241. it('should allow setting tables', function()
  1242. local wildignore = exec_lua [[
  1243. vim.opt.wildignore = { 'hello', 'world' }
  1244. return vim.o.wildignore
  1245. ]]
  1246. eq(wildignore, "hello,world")
  1247. end)
  1248. it('should allow setting tables with shortnames', function()
  1249. local wildignore = exec_lua [[
  1250. vim.opt.wig = { 'hello', 'world' }
  1251. return vim.o.wildignore
  1252. ]]
  1253. eq(wildignore, "hello,world")
  1254. end)
  1255. it('should error when you attempt to set string values to numeric options', function()
  1256. local result = exec_lua [[
  1257. return {
  1258. pcall(function() vim.opt.textwidth = 'hello world' end)
  1259. }
  1260. ]]
  1261. eq(false, result[1])
  1262. end)
  1263. it('should error when you attempt to setlocal a global value', function()
  1264. local result = exec_lua [[
  1265. return pcall(function() vim.opt_local.clipboard = "hello" end)
  1266. ]]
  1267. eq(false, result)
  1268. end)
  1269. it('should allow you to set boolean values', function()
  1270. eq({true, false, true}, exec_lua [[
  1271. local results = {}
  1272. vim.opt.autoindent = true
  1273. table.insert(results, vim.bo.autoindent)
  1274. vim.opt.autoindent = false
  1275. table.insert(results, vim.bo.autoindent)
  1276. vim.opt.autoindent = not vim.opt.autoindent:get()
  1277. table.insert(results, vim.bo.autoindent)
  1278. return results
  1279. ]])
  1280. end)
  1281. it('should change current buffer values and defaults for global local values', function()
  1282. local result = exec_lua [[
  1283. local result = {}
  1284. vim.opt.makeprg = "global-local"
  1285. table.insert(result, vim.api.nvim_get_option('makeprg'))
  1286. table.insert(result, vim.api.nvim_buf_get_option(0, 'makeprg'))
  1287. vim.opt_local.mp = "only-local"
  1288. table.insert(result, vim.api.nvim_get_option('makeprg'))
  1289. table.insert(result, vim.api.nvim_buf_get_option(0, 'makeprg'))
  1290. vim.opt_global.makeprg = "only-global"
  1291. table.insert(result, vim.api.nvim_get_option('makeprg'))
  1292. table.insert(result, vim.api.nvim_buf_get_option(0, 'makeprg'))
  1293. vim.opt.makeprg = "global-local"
  1294. table.insert(result, vim.api.nvim_get_option('makeprg'))
  1295. table.insert(result, vim.api.nvim_buf_get_option(0, 'makeprg'))
  1296. return result
  1297. ]]
  1298. -- Set -> global & local
  1299. eq("global-local", result[1])
  1300. eq("", result[2])
  1301. -- Setlocal -> only local
  1302. eq("global-local", result[3])
  1303. eq("only-local", result[4])
  1304. -- Setglobal -> only global
  1305. eq("only-global", result[5])
  1306. eq("only-local", result[6])
  1307. -- Set -> sets global value and resets local value
  1308. eq("global-local", result[7])
  1309. eq("", result[8])
  1310. end)
  1311. it('should allow you to retrieve window opts even if they have not been set', function()
  1312. local result = exec_lua [[
  1313. local result = {}
  1314. table.insert(result, vim.opt.number:get())
  1315. table.insert(result, vim.opt_local.number:get())
  1316. vim.opt_local.number = true
  1317. table.insert(result, vim.opt.number:get())
  1318. table.insert(result, vim.opt_local.number:get())
  1319. return result
  1320. ]]
  1321. eq({false, false, true, true}, result)
  1322. end)
  1323. it('should allow all sorts of string manipulation', function()
  1324. eq({'hello', 'hello world', 'start hello world'}, exec_lua [[
  1325. local results = {}
  1326. vim.opt.makeprg = "hello"
  1327. table.insert(results, vim.o.makeprg)
  1328. vim.opt.makeprg = vim.opt.makeprg + " world"
  1329. table.insert(results, vim.o.makeprg)
  1330. vim.opt.makeprg = vim.opt.makeprg ^ "start "
  1331. table.insert(results, vim.o.makeprg)
  1332. return results
  1333. ]])
  1334. end)
  1335. describe('option:get()', function()
  1336. it('should work for boolean values', function()
  1337. eq(false, exec_lua [[
  1338. vim.opt.number = false
  1339. return vim.opt.number:get()
  1340. ]])
  1341. end)
  1342. it('should work for number values', function()
  1343. local tabstop = exec_lua[[
  1344. vim.opt.tabstop = 10
  1345. return vim.opt.tabstop:get()
  1346. ]]
  1347. eq(10, tabstop)
  1348. end)
  1349. it('should work for string values', function()
  1350. eq("hello world", exec_lua [[
  1351. vim.opt.makeprg = "hello world"
  1352. return vim.opt.makeprg:get()
  1353. ]])
  1354. end)
  1355. it('should work for set type flaglists', function()
  1356. local formatoptions = exec_lua [[
  1357. vim.opt.formatoptions = 'tcro'
  1358. return vim.opt.formatoptions:get()
  1359. ]]
  1360. eq(true, formatoptions.t)
  1361. eq(true, not formatoptions.q)
  1362. end)
  1363. it('should work for set type flaglists', function()
  1364. local formatoptions = exec_lua [[
  1365. vim.opt.formatoptions = { t = true, c = true, r = true, o = true }
  1366. return vim.opt.formatoptions:get()
  1367. ]]
  1368. eq(true, formatoptions.t)
  1369. eq(true, not formatoptions.q)
  1370. end)
  1371. it('should work for array list type options', function()
  1372. local wildignore = exec_lua [[
  1373. vim.opt.wildignore = "*.c,*.o,__pycache__"
  1374. return vim.opt.wildignore:get()
  1375. ]]
  1376. eq(3, #wildignore)
  1377. eq("*.c", wildignore[1])
  1378. end)
  1379. it('should work for options that are both commalist and flaglist', function()
  1380. local result = exec_lua [[
  1381. vim.opt.whichwrap = "b,s"
  1382. return vim.opt.whichwrap:get()
  1383. ]]
  1384. eq({b = true, s = true}, result)
  1385. result = exec_lua [[
  1386. vim.opt.whichwrap = { b = true, s = false, h = true }
  1387. return vim.opt.whichwrap:get()
  1388. ]]
  1389. eq({b = true, h = true}, result)
  1390. end)
  1391. it('should work for key-value pair options', function()
  1392. local listchars = exec_lua [[
  1393. vim.opt.listchars = "tab:> ,space:_"
  1394. return vim.opt.listchars:get()
  1395. ]]
  1396. eq({
  1397. tab = "> ",
  1398. space = "_",
  1399. }, listchars)
  1400. end)
  1401. it('should allow you to add numeric options', function()
  1402. eq(16, exec_lua [[
  1403. vim.opt.tabstop = 12
  1404. vim.opt.tabstop = vim.opt.tabstop + 4
  1405. return vim.bo.tabstop
  1406. ]])
  1407. end)
  1408. it('should allow you to subtract numeric options', function()
  1409. eq(2, exec_lua [[
  1410. vim.opt.tabstop = 4
  1411. vim.opt.tabstop = vim.opt.tabstop - 2
  1412. return vim.bo.tabstop
  1413. ]])
  1414. end)
  1415. end)
  1416. describe('key:value style options', function()
  1417. it('should handle dictionary style', function()
  1418. local listchars = exec_lua [[
  1419. vim.opt.listchars = {
  1420. eol = "~",
  1421. space = ".",
  1422. }
  1423. return vim.o.listchars
  1424. ]]
  1425. eq("eol:~,space:.", listchars)
  1426. end)
  1427. it('should allow adding dictionary style', function()
  1428. local listchars = exec_lua [[
  1429. vim.opt.listchars = {
  1430. eol = "~",
  1431. space = ".",
  1432. }
  1433. vim.opt.listchars = vim.opt.listchars + { space = "-" }
  1434. return vim.o.listchars
  1435. ]]
  1436. eq("eol:~,space:-", listchars)
  1437. end)
  1438. it('should allow adding dictionary style', function()
  1439. local listchars = exec_lua [[
  1440. vim.opt.listchars = {
  1441. eol = "~",
  1442. space = ".",
  1443. }
  1444. vim.opt.listchars = vim.opt.listchars + { space = "-" } + { space = "_" }
  1445. return vim.o.listchars
  1446. ]]
  1447. eq("eol:~,space:_", listchars)
  1448. end)
  1449. it('should allow completely new keys', function()
  1450. local listchars = exec_lua [[
  1451. vim.opt.listchars = {
  1452. eol = "~",
  1453. space = ".",
  1454. }
  1455. vim.opt.listchars = vim.opt.listchars + { tab = ">>>" }
  1456. return vim.o.listchars
  1457. ]]
  1458. eq("eol:~,space:.,tab:>>>", listchars)
  1459. end)
  1460. it('should allow subtracting dictionary style', function()
  1461. local listchars = exec_lua [[
  1462. vim.opt.listchars = {
  1463. eol = "~",
  1464. space = ".",
  1465. }
  1466. vim.opt.listchars = vim.opt.listchars - "space"
  1467. return vim.o.listchars
  1468. ]]
  1469. eq("eol:~", listchars)
  1470. end)
  1471. it('should allow subtracting dictionary style', function()
  1472. local listchars = exec_lua [[
  1473. vim.opt.listchars = {
  1474. eol = "~",
  1475. space = ".",
  1476. }
  1477. vim.opt.listchars = vim.opt.listchars - "space" - "eol"
  1478. return vim.o.listchars
  1479. ]]
  1480. eq("", listchars)
  1481. end)
  1482. it('should allow subtracting dictionary style multiple times', function()
  1483. local listchars = exec_lua [[
  1484. vim.opt.listchars = {
  1485. eol = "~",
  1486. space = ".",
  1487. }
  1488. vim.opt.listchars = vim.opt.listchars - "space" - "space"
  1489. return vim.o.listchars
  1490. ]]
  1491. eq("eol:~", listchars)
  1492. end)
  1493. it('should allow adding a key:value string to a listchars', function()
  1494. local listchars = exec_lua [[
  1495. vim.opt.listchars = {
  1496. eol = "~",
  1497. space = ".",
  1498. }
  1499. vim.opt.listchars = vim.opt.listchars + "tab:>~"
  1500. return vim.o.listchars
  1501. ]]
  1502. eq("eol:~,space:.,tab:>~", listchars)
  1503. end)
  1504. it('should allow prepending a key:value string to a listchars', function()
  1505. local listchars = exec_lua [[
  1506. vim.opt.listchars = {
  1507. eol = "~",
  1508. space = ".",
  1509. }
  1510. vim.opt.listchars = vim.opt.listchars ^ "tab:>~"
  1511. return vim.o.listchars
  1512. ]]
  1513. eq("eol:~,space:.,tab:>~", listchars)
  1514. end)
  1515. end)
  1516. it('should automatically set when calling remove', function()
  1517. eq("foo,baz", exec_lua [[
  1518. vim.opt.wildignore = "foo,bar,baz"
  1519. vim.opt.wildignore:remove("bar")
  1520. return vim.o.wildignore
  1521. ]])
  1522. end)
  1523. it('should automatically set when calling remove with a table', function()
  1524. eq("foo", exec_lua [[
  1525. vim.opt.wildignore = "foo,bar,baz"
  1526. vim.opt.wildignore:remove { "bar", "baz" }
  1527. return vim.o.wildignore
  1528. ]])
  1529. end)
  1530. it('should automatically set when calling append', function()
  1531. eq("foo,bar,baz,bing", exec_lua [[
  1532. vim.opt.wildignore = "foo,bar,baz"
  1533. vim.opt.wildignore:append("bing")
  1534. return vim.o.wildignore
  1535. ]])
  1536. end)
  1537. it('should automatically set when calling append with a table', function()
  1538. eq("foo,bar,baz,bing,zap", exec_lua [[
  1539. vim.opt.wildignore = "foo,bar,baz"
  1540. vim.opt.wildignore:append { "bing", "zap" }
  1541. return vim.o.wildignore
  1542. ]])
  1543. end)
  1544. it('should allow adding tables', function()
  1545. local wildignore = exec_lua [[
  1546. vim.opt.wildignore = 'foo'
  1547. return vim.o.wildignore
  1548. ]]
  1549. eq(wildignore, 'foo')
  1550. wildignore = exec_lua [[
  1551. vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' }
  1552. return vim.o.wildignore
  1553. ]]
  1554. eq(wildignore, 'foo,bar,baz')
  1555. end)
  1556. it('should handle adding duplicates', function()
  1557. local wildignore = exec_lua [[
  1558. vim.opt.wildignore = 'foo'
  1559. return vim.o.wildignore
  1560. ]]
  1561. eq(wildignore, 'foo')
  1562. wildignore = exec_lua [[
  1563. vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' }
  1564. return vim.o.wildignore
  1565. ]]
  1566. eq(wildignore, 'foo,bar,baz')
  1567. wildignore = exec_lua [[
  1568. vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' }
  1569. return vim.o.wildignore
  1570. ]]
  1571. eq(wildignore, 'foo,bar,baz')
  1572. end)
  1573. it('should allow adding multiple times', function()
  1574. local wildignore = exec_lua [[
  1575. vim.opt.wildignore = 'foo'
  1576. vim.opt.wildignore = vim.opt.wildignore + 'bar' + 'baz'
  1577. return vim.o.wildignore
  1578. ]]
  1579. eq(wildignore, 'foo,bar,baz')
  1580. end)
  1581. it('should remove values when you use minus', function()
  1582. local wildignore = exec_lua [[
  1583. vim.opt.wildignore = 'foo'
  1584. return vim.o.wildignore
  1585. ]]
  1586. eq(wildignore, 'foo')
  1587. wildignore = exec_lua [[
  1588. vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' }
  1589. return vim.o.wildignore
  1590. ]]
  1591. eq(wildignore, 'foo,bar,baz')
  1592. wildignore = exec_lua [[
  1593. vim.opt.wildignore = vim.opt.wildignore - 'bar'
  1594. return vim.o.wildignore
  1595. ]]
  1596. eq(wildignore, 'foo,baz')
  1597. end)
  1598. it('should prepend values when using ^', function()
  1599. local wildignore = exec_lua [[
  1600. vim.opt.wildignore = 'foo'
  1601. vim.opt.wildignore = vim.opt.wildignore ^ 'first'
  1602. return vim.o.wildignore
  1603. ]]
  1604. eq('first,foo', wildignore)
  1605. wildignore = exec_lua [[
  1606. vim.opt.wildignore = vim.opt.wildignore ^ 'super_first'
  1607. return vim.o.wildignore
  1608. ]]
  1609. eq(wildignore, 'super_first,first,foo')
  1610. end)
  1611. it('should not remove duplicates from wildmode: #14708', function()
  1612. local wildmode = exec_lua [[
  1613. vim.opt.wildmode = {"full", "list", "full"}
  1614. return vim.o.wildmode
  1615. ]]
  1616. eq(wildmode, 'full,list,full')
  1617. end)
  1618. describe('option types', function()
  1619. it('should allow to set option with numeric value', function()
  1620. eq(4, exec_lua [[
  1621. vim.opt.tabstop = 4
  1622. return vim.bo.tabstop
  1623. ]])
  1624. matches("Invalid option type 'string' for 'tabstop'", pcall_err(exec_lua, [[
  1625. vim.opt.tabstop = '4'
  1626. ]]))
  1627. matches("Invalid option type 'boolean' for 'tabstop'", pcall_err(exec_lua, [[
  1628. vim.opt.tabstop = true
  1629. ]]))
  1630. matches("Invalid option type 'table' for 'tabstop'", pcall_err(exec_lua, [[
  1631. vim.opt.tabstop = {4, 2}
  1632. ]]))
  1633. matches("Invalid option type 'function' for 'tabstop'", pcall_err(exec_lua, [[
  1634. vim.opt.tabstop = function()
  1635. return 4
  1636. end
  1637. ]]))
  1638. end)
  1639. it('should allow to set option with boolean value', function()
  1640. eq(true, exec_lua [[
  1641. vim.opt.undofile = true
  1642. return vim.bo.undofile
  1643. ]])
  1644. matches("Invalid option type 'number' for 'undofile'", pcall_err(exec_lua, [[
  1645. vim.opt.undofile = 0
  1646. ]]))
  1647. matches("Invalid option type 'table' for 'undofile'", pcall_err(exec_lua, [[
  1648. vim.opt.undofile = {true}
  1649. ]]))
  1650. matches("Invalid option type 'string' for 'undofile'", pcall_err(exec_lua, [[
  1651. vim.opt.undofile = 'true'
  1652. ]]))
  1653. matches("Invalid option type 'function' for 'undofile'", pcall_err(exec_lua, [[
  1654. vim.opt.undofile = function()
  1655. return true
  1656. end
  1657. ]]))
  1658. end)
  1659. it('should allow to set option with array or string value', function()
  1660. eq('indent,eol,start', exec_lua [[
  1661. vim.opt.backspace = {'indent','eol','start'}
  1662. return vim.go.backspace
  1663. ]])
  1664. eq('indent,eol,start', exec_lua [[
  1665. vim.opt.backspace = 'indent,eol,start'
  1666. return vim.go.backspace
  1667. ]])
  1668. matches("Invalid option type 'boolean' for 'backspace'", pcall_err(exec_lua, [[
  1669. vim.opt.backspace = true
  1670. ]]))
  1671. matches("Invalid option type 'number' for 'backspace'", pcall_err(exec_lua, [[
  1672. vim.opt.backspace = 2
  1673. ]]))
  1674. matches("Invalid option type 'function' for 'backspace'", pcall_err(exec_lua, [[
  1675. vim.opt.backspace = function()
  1676. return 'indent,eol,start'
  1677. end
  1678. ]]))
  1679. end)
  1680. it('should allow set option with map or string value', function()
  1681. eq("eol:~,space:.", exec_lua [[
  1682. vim.opt.listchars = {
  1683. eol = "~",
  1684. space = ".",
  1685. }
  1686. return vim.o.listchars
  1687. ]])
  1688. eq("eol:~,space:.,tab:>~", exec_lua [[
  1689. vim.opt.listchars = "eol:~,space:.,tab:>~"
  1690. return vim.o.listchars
  1691. ]])
  1692. matches("Invalid option type 'boolean' for 'listchars'", pcall_err(exec_lua, [[
  1693. vim.opt.listchars = true
  1694. ]]))
  1695. matches("Invalid option type 'number' for 'listchars'", pcall_err(exec_lua, [[
  1696. vim.opt.listchars = 2
  1697. ]]))
  1698. matches("Invalid option type 'function' for 'listchars'", pcall_err(exec_lua, [[
  1699. vim.opt.listchars = function()
  1700. return "eol:~,space:.,tab:>~"
  1701. end
  1702. ]]))
  1703. end)
  1704. it('should allow set option with set or string value', function()
  1705. local ww = exec_lua [[
  1706. vim.opt.whichwrap = {
  1707. b = true,
  1708. s = 1,
  1709. }
  1710. return vim.go.whichwrap
  1711. ]]
  1712. eq(ww, "b,s")
  1713. eq("b,s,<,>,[,]", exec_lua [[
  1714. vim.opt.whichwrap = "b,s,<,>,[,]"
  1715. return vim.go.whichwrap
  1716. ]])
  1717. matches("Invalid option type 'boolean' for 'whichwrap'", pcall_err(exec_lua, [[
  1718. vim.opt.whichwrap = true
  1719. ]]))
  1720. matches("Invalid option type 'number' for 'whichwrap'", pcall_err(exec_lua, [[
  1721. vim.opt.whichwrap = 2
  1722. ]]))
  1723. matches("Invalid option type 'function' for 'whichwrap'", pcall_err(exec_lua, [[
  1724. vim.opt.whichwrap = function()
  1725. return "b,s,<,>,[,]"
  1726. end
  1727. ]]))
  1728. end)
  1729. end)
  1730. -- isfname=a,b,c,,,d,e,f
  1731. it('can handle isfname ,,,', function()
  1732. local result = exec_lua [[
  1733. vim.opt.isfname = "a,b,,,c"
  1734. return { vim.opt.isfname:get(), vim.api.nvim_get_option('isfname') }
  1735. ]]
  1736. eq({{",", "a", "b", "c"}, "a,b,,,c"}, result)
  1737. end)
  1738. -- isfname=a,b,c,^,,def
  1739. it('can handle isfname ,^,,', function()
  1740. local result = exec_lua [[
  1741. vim.opt.isfname = "a,b,^,,c"
  1742. return { vim.opt.isfname:get(), vim.api.nvim_get_option('isfname') }
  1743. ]]
  1744. eq({{"^,", "a", "b", "c"}, "a,b,^,,c"}, result)
  1745. end)
  1746. describe('https://github.com/neovim/neovim/issues/14828', function()
  1747. it('gives empty list when item is empty:array', function()
  1748. eq({}, exec_lua [[
  1749. vim.cmd("set wildignore=")
  1750. return vim.opt.wildignore:get()
  1751. ]])
  1752. eq({}, exec_lua [[
  1753. vim.opt.wildignore = {}
  1754. return vim.opt.wildignore:get()
  1755. ]])
  1756. end)
  1757. it('gives empty list when item is empty:set', function()
  1758. eq({}, exec_lua [[
  1759. vim.cmd("set formatoptions=")
  1760. return vim.opt.formatoptions:get()
  1761. ]])
  1762. eq({}, exec_lua [[
  1763. vim.opt.formatoptions = {}
  1764. return vim.opt.formatoptions:get()
  1765. ]])
  1766. end)
  1767. it('does not append to empty item', function()
  1768. eq({"*.foo", "*.bar"}, exec_lua [[
  1769. vim.opt.wildignore = {}
  1770. vim.opt.wildignore:append { "*.foo", "*.bar" }
  1771. return vim.opt.wildignore:get()
  1772. ]])
  1773. end)
  1774. it('does not prepend to empty item', function()
  1775. eq({"*.foo", "*.bar"}, exec_lua [[
  1776. vim.opt.wildignore = {}
  1777. vim.opt.wildignore:prepend { "*.foo", "*.bar" }
  1778. return vim.opt.wildignore:get()
  1779. ]])
  1780. end)
  1781. it('append to empty set', function()
  1782. eq({ t = true }, exec_lua [[
  1783. vim.opt.formatoptions = {}
  1784. vim.opt.formatoptions:append("t")
  1785. return vim.opt.formatoptions:get()
  1786. ]])
  1787. end)
  1788. it('prepend to empty set', function()
  1789. eq({ t = true }, exec_lua [[
  1790. vim.opt.formatoptions = {}
  1791. vim.opt.formatoptions:prepend("t")
  1792. return vim.opt.formatoptions:get()
  1793. ]])
  1794. end)
  1795. end)
  1796. end) -- vim.opt
  1797. it('vim.cmd', function()
  1798. exec_lua [[
  1799. vim.cmd "autocmd BufNew * ++once lua BUF = vim.fn.expand('<abuf>')"
  1800. vim.cmd "new"
  1801. ]]
  1802. eq('2', funcs.luaeval "BUF")
  1803. eq(2, funcs.luaeval "#vim.api.nvim_list_bufs()")
  1804. end)
  1805. it('vim.regex', function()
  1806. exec_lua [[
  1807. re1 = vim.regex"ab\\+c"
  1808. vim.cmd "set nomagic ignorecase"
  1809. re2 = vim.regex"xYz"
  1810. ]]
  1811. eq({}, exec_lua[[return {re1:match_str("x ac")}]])
  1812. eq({3,7}, exec_lua[[return {re1:match_str("ac abbc")}]])
  1813. meths.buf_set_lines(0, 0, -1, true, {"yy", "abc abbc"})
  1814. eq({}, exec_lua[[return {re1:match_line(0, 0)}]])
  1815. eq({0,3}, exec_lua[[return {re1:match_line(0, 1)}]])
  1816. eq({3,7}, exec_lua[[return {re1:match_line(0, 1, 1)}]])
  1817. eq({3,7}, exec_lua[[return {re1:match_line(0, 1, 1, 8)}]])
  1818. eq({}, exec_lua[[return {re1:match_line(0, 1, 1, 7)}]])
  1819. eq({0,3}, exec_lua[[return {re1:match_line(0, 1, 0, 7)}]])
  1820. end)
  1821. it('vim.defer_fn', function()
  1822. eq(false, exec_lua [[
  1823. vim.g.test = false
  1824. vim.defer_fn(function() vim.g.test = true end, 150)
  1825. return vim.g.test
  1826. ]])
  1827. exec_lua [[vim.wait(1000, function() return vim.g.test end)]]
  1828. eq(true, exec_lua[[return vim.g.test]])
  1829. end)
  1830. it('vim.region', function()
  1831. insert(helpers.dedent( [[
  1832. text tααt tααt text
  1833. text tαxt txtα tex
  1834. text tαxt tαxt
  1835. ]]))
  1836. eq({5,15}, exec_lua[[ return vim.region(0,{1,5},{1,14},'v',true)[1] ]])
  1837. end)
  1838. describe('vim.on_key', function()
  1839. it('tracks keystrokes', function()
  1840. insert([[hello world ]])
  1841. exec_lua [[
  1842. keys = {}
  1843. vim.on_key(function(buf)
  1844. if buf:byte() == 27 then
  1845. buf = "<ESC>"
  1846. end
  1847. table.insert(keys, buf)
  1848. end)
  1849. ]]
  1850. insert([[next 🤦 lines å ]])
  1851. -- It has escape in the keys pressed
  1852. eq('inext 🤦 lines å <ESC>', exec_lua [[return table.concat(keys, '')]])
  1853. end)
  1854. it('allows removing on_key listeners', function()
  1855. insert([[hello world]])
  1856. exec_lua [[
  1857. keys = {}
  1858. return vim.on_key(function(buf)
  1859. if buf:byte() == 27 then
  1860. buf = "<ESC>"
  1861. end
  1862. table.insert(keys, buf)
  1863. end, vim.api.nvim_create_namespace("logger"))
  1864. ]]
  1865. insert([[next lines]])
  1866. eq(1, exec_lua('return vim.on_key()'))
  1867. exec_lua("vim.on_key(nil, vim.api.nvim_create_namespace('logger'))")
  1868. eq(0, exec_lua('return vim.on_key()'))
  1869. insert([[more lines]])
  1870. -- It has escape in the keys pressed
  1871. eq('inext lines<ESC>', exec_lua [[return table.concat(keys, '')]])
  1872. end)
  1873. it('skips any function that caused an error', function()
  1874. insert([[hello world]])
  1875. exec_lua [[
  1876. keys = {}
  1877. return vim.on_key(function(buf)
  1878. if buf:byte() == 27 then
  1879. buf = "<ESC>"
  1880. end
  1881. table.insert(keys, buf)
  1882. if buf == 'l' then
  1883. error("Dumb Error")
  1884. end
  1885. end)
  1886. ]]
  1887. insert([[next lines]])
  1888. insert([[more lines]])
  1889. -- Only the first letter gets added. After that we remove the callback
  1890. eq('inext l', exec_lua [[ return table.concat(keys, '') ]])
  1891. end)
  1892. it('processes mapped keys, not unmapped keys', function()
  1893. exec_lua [[
  1894. keys = {}
  1895. vim.cmd("inoremap hello world")
  1896. vim.on_key(function(buf)
  1897. if buf:byte() == 27 then
  1898. buf = "<ESC>"
  1899. end
  1900. table.insert(keys, buf)
  1901. end)
  1902. ]]
  1903. insert("hello")
  1904. eq('iworld<ESC>', exec_lua[[return table.concat(keys, '')]])
  1905. end)
  1906. end)
  1907. describe('vim.wait', function()
  1908. before_each(function()
  1909. exec_lua[[
  1910. -- high precision timer
  1911. get_time = function()
  1912. return vim.fn.reltimefloat(vim.fn.reltime())
  1913. end
  1914. ]]
  1915. end)
  1916. it('should run from lua', function()
  1917. exec_lua[[vim.wait(100, function() return true end)]]
  1918. end)
  1919. it('should wait the expected time if false', function()
  1920. eq({time = true, wait_result = {false, -1}}, exec_lua[[
  1921. start_time = get_time()
  1922. wait_succeed, wait_fail_val = vim.wait(200, function() return false end)
  1923. return {
  1924. -- 150ms waiting or more results in true. Flaky tests are bad.
  1925. time = (start_time + 0.15) < get_time(),
  1926. wait_result = {wait_succeed, wait_fail_val}
  1927. }
  1928. ]])
  1929. end)
  1930. it('should not block other events', function()
  1931. eq({time = true, wait_result = true}, exec_lua[[
  1932. start_time = get_time()
  1933. vim.g.timer_result = false
  1934. timer = vim.loop.new_timer()
  1935. timer:start(100, 0, vim.schedule_wrap(function()
  1936. vim.g.timer_result = true
  1937. end))
  1938. -- Would wait ten seconds if results blocked.
  1939. wait_result = vim.wait(10000, function() return vim.g.timer_result end)
  1940. timer:close()
  1941. return {
  1942. time = (start_time + 5) > get_time(),
  1943. wait_result = wait_result,
  1944. }
  1945. ]])
  1946. end)
  1947. it('should not process non-fast events when commanded', function()
  1948. eq({wait_result = false}, exec_lua[[
  1949. start_time = get_time()
  1950. vim.g.timer_result = false
  1951. timer = vim.loop.new_timer()
  1952. timer:start(100, 0, vim.schedule_wrap(function()
  1953. vim.g.timer_result = true
  1954. end))
  1955. wait_result = vim.wait(300, function() return vim.g.timer_result end, nil, true)
  1956. timer:close()
  1957. return {
  1958. wait_result = wait_result,
  1959. }
  1960. ]])
  1961. end)
  1962. it('should work with vim.defer_fn', function()
  1963. eq({time = true, wait_result = true}, exec_lua[[
  1964. start_time = get_time()
  1965. vim.defer_fn(function() vim.g.timer_result = true end, 100)
  1966. wait_result = vim.wait(10000, function() return vim.g.timer_result end)
  1967. return {
  1968. time = (start_time + 5) > get_time(),
  1969. wait_result = wait_result,
  1970. }
  1971. ]])
  1972. end)
  1973. it('should not crash when callback errors', function()
  1974. local result = exec_lua [[
  1975. return {pcall(function() vim.wait(1000, function() error("As Expected") end) end)}
  1976. ]]
  1977. eq({false, '[string "<nvim>"]:1: As Expected'}, {result[1], remove_trace(result[2])})
  1978. end)
  1979. it('if callback is passed, it must be a function', function()
  1980. eq({false, 'vim.wait: if passed, condition must be a function'}, exec_lua [[
  1981. return {pcall(function() vim.wait(1000, 13) end)}
  1982. ]])
  1983. end)
  1984. it('should allow waiting with no callback, explicit', function()
  1985. eq(true, exec_lua [[
  1986. local start_time = vim.loop.hrtime()
  1987. vim.wait(50, nil)
  1988. return vim.loop.hrtime() - start_time > 25000
  1989. ]])
  1990. end)
  1991. it('should allow waiting with no callback, implicit', function()
  1992. eq(true, exec_lua [[
  1993. local start_time = vim.loop.hrtime()
  1994. vim.wait(50)
  1995. return vim.loop.hrtime() - start_time > 25000
  1996. ]])
  1997. end)
  1998. it('should call callbacks exactly once if they return true immediately', function()
  1999. eq(true, exec_lua [[
  2000. vim.g.wait_count = 0
  2001. vim.wait(1000, function()
  2002. vim.g.wait_count = vim.g.wait_count + 1
  2003. return true
  2004. end, 20)
  2005. return vim.g.wait_count == 1
  2006. ]])
  2007. end)
  2008. it('should call callbacks few times with large `interval`', function()
  2009. eq(true, exec_lua [[
  2010. vim.g.wait_count = 0
  2011. vim.wait(50, function() vim.g.wait_count = vim.g.wait_count + 1 end, 200)
  2012. return vim.g.wait_count < 5
  2013. ]])
  2014. end)
  2015. it('should play nice with `not` when fails', function()
  2016. eq(true, exec_lua [[
  2017. if not vim.wait(50, function() end) then
  2018. return true
  2019. end
  2020. return false
  2021. ]])
  2022. end)
  2023. it('should play nice with `if` when success', function()
  2024. eq(true, exec_lua [[
  2025. if vim.wait(50, function() return true end) then
  2026. return true
  2027. end
  2028. return false
  2029. ]])
  2030. end)
  2031. it('should return immediately with false if timeout is 0', function()
  2032. eq({false, -1}, exec_lua [[
  2033. return {
  2034. vim.wait(0, function() return false end)
  2035. }
  2036. ]])
  2037. end)
  2038. it('should work with tables with __call', function()
  2039. eq(true, exec_lua [[
  2040. local t = setmetatable({}, {__call = function(...) return true end})
  2041. return vim.wait(100, t, 10)
  2042. ]])
  2043. end)
  2044. it('should work with tables with __call that change', function()
  2045. eq(true, exec_lua [[
  2046. local t = {count = 0}
  2047. setmetatable(t, {
  2048. __call = function()
  2049. t.count = t.count + 1
  2050. return t.count > 3
  2051. end
  2052. })
  2053. return vim.wait(1000, t, 10)
  2054. ]])
  2055. end)
  2056. it('should not work with negative intervals', function()
  2057. local pcall_result = exec_lua [[
  2058. return pcall(function() vim.wait(1000, function() return false end, -1) end)
  2059. ]]
  2060. eq(false, pcall_result)
  2061. end)
  2062. it('should not work with weird intervals', function()
  2063. local pcall_result = exec_lua [[
  2064. return pcall(function() vim.wait(1000, function() return false end, 'a string value') end)
  2065. ]]
  2066. eq(false, pcall_result)
  2067. end)
  2068. end)
  2069. it('vim.notify_once', function()
  2070. local screen = Screen.new(60,5)
  2071. screen:set_default_attr_ids({
  2072. [0] = {bold=true, foreground=Screen.colors.Blue},
  2073. [1] = {foreground=Screen.colors.Red},
  2074. })
  2075. screen:attach()
  2076. screen:expect{grid=[[
  2077. ^ |
  2078. {0:~ }|
  2079. {0:~ }|
  2080. {0:~ }|
  2081. |
  2082. ]]}
  2083. exec_lua [[vim.notify_once("I'll only tell you this once...", vim.log.levels.WARN)]]
  2084. screen:expect{grid=[[
  2085. ^ |
  2086. {0:~ }|
  2087. {0:~ }|
  2088. {0:~ }|
  2089. {1:I'll only tell you this once...} |
  2090. ]]}
  2091. feed('<C-l>')
  2092. screen:expect{grid=[[
  2093. ^ |
  2094. {0:~ }|
  2095. {0:~ }|
  2096. {0:~ }|
  2097. |
  2098. ]]}
  2099. exec_lua [[vim.notify_once("I'll only tell you this once...")]]
  2100. screen:expect_unchanged()
  2101. end)
  2102. describe('vim.schedule_wrap', function()
  2103. it('preserves argument lists', function()
  2104. exec_lua [[
  2105. local fun = vim.schedule_wrap(function(kling, klang, klonk)
  2106. vim.rpcnotify(1, 'mayday_mayday', {a=kling, b=klang, c=klonk})
  2107. end)
  2108. fun("BOB", nil, "MIKE")
  2109. ]]
  2110. eq({'notification', 'mayday_mayday', {{a='BOB', c='MIKE'}}}, next_msg())
  2111. -- let's gooooo
  2112. exec_lua [[
  2113. vim.schedule_wrap(function(...) vim.rpcnotify(1, 'boogalo', select('#', ...)) end)(nil,nil,nil,nil)
  2114. ]]
  2115. eq({'notification', 'boogalo', {4}}, next_msg())
  2116. end)
  2117. end)
  2118. describe('vim.api.nvim_buf_call', function()
  2119. it('can access buf options', function()
  2120. local buf1 = meths.get_current_buf()
  2121. local buf2 = exec_lua [[
  2122. buf2 = vim.api.nvim_create_buf(false, true)
  2123. return buf2
  2124. ]]
  2125. eq(false, meths.buf_get_option(buf1, 'autoindent'))
  2126. eq(false, meths.buf_get_option(buf2, 'autoindent'))
  2127. local val = exec_lua [[
  2128. return vim.api.nvim_buf_call(buf2, function()
  2129. vim.cmd "set autoindent"
  2130. return vim.api.nvim_get_current_buf()
  2131. end)
  2132. ]]
  2133. eq(false, meths.buf_get_option(buf1, 'autoindent'))
  2134. eq(true, meths.buf_get_option(buf2, 'autoindent'))
  2135. eq(buf1, meths.get_current_buf())
  2136. eq(buf2, val)
  2137. end)
  2138. it('does not cause ml_get errors with invalid visual selection', function()
  2139. -- Should be fixed by vim-patch:8.2.4028.
  2140. exec_lua [[
  2141. local a = vim.api
  2142. local t = function(s) return a.nvim_replace_termcodes(s, true, true, true) end
  2143. a.nvim_buf_set_lines(0, 0, -1, true, {"a", "b", "c"})
  2144. a.nvim_feedkeys(t "G<C-V>", "txn", false)
  2145. a.nvim_buf_call(a.nvim_create_buf(false, true), function() vim.cmd "redraw" end)
  2146. ]]
  2147. end)
  2148. end)
  2149. describe('vim.api.nvim_win_call', function()
  2150. it('can access window options', function()
  2151. command('vsplit')
  2152. local win1 = meths.get_current_win()
  2153. command('wincmd w')
  2154. local win2 = exec_lua [[
  2155. win2 = vim.api.nvim_get_current_win()
  2156. return win2
  2157. ]]
  2158. command('wincmd p')
  2159. eq('', meths.win_get_option(win1, 'winhighlight'))
  2160. eq('', meths.win_get_option(win2, 'winhighlight'))
  2161. local val = exec_lua [[
  2162. return vim.api.nvim_win_call(win2, function()
  2163. vim.cmd "setlocal winhighlight=Normal:Normal"
  2164. return vim.api.nvim_get_current_win()
  2165. end)
  2166. ]]
  2167. eq('', meths.win_get_option(win1, 'winhighlight'))
  2168. eq('Normal:Normal', meths.win_get_option(win2, 'winhighlight'))
  2169. eq(win1, meths.get_current_win())
  2170. eq(win2, val)
  2171. end)
  2172. it('does not cause ml_get errors with invalid visual selection', function()
  2173. -- Add lines to the current buffer and make another window looking into an empty buffer.
  2174. exec_lua [[
  2175. _G.a = vim.api
  2176. _G.t = function(s) return a.nvim_replace_termcodes(s, true, true, true) end
  2177. _G.win_lines = a.nvim_get_current_win()
  2178. vim.cmd "new"
  2179. _G.win_empty = a.nvim_get_current_win()
  2180. a.nvim_set_current_win(win_lines)
  2181. a.nvim_buf_set_lines(0, 0, -1, true, {"a", "b", "c"})
  2182. ]]
  2183. -- Start Visual in current window, redraw in other window with fewer lines.
  2184. -- Should be fixed by vim-patch:8.2.4018.
  2185. exec_lua [[
  2186. a.nvim_feedkeys(t "G<C-V>", "txn", false)
  2187. a.nvim_win_call(win_empty, function() vim.cmd "redraw" end)
  2188. ]]
  2189. -- Start Visual in current window, extend it in other window with more lines.
  2190. -- Fixed for win_execute by vim-patch:8.2.4026, but nvim_win_call should also not be affected.
  2191. exec_lua [[
  2192. a.nvim_feedkeys(t "<Esc>gg", "txn", false)
  2193. a.nvim_set_current_win(win_empty)
  2194. a.nvim_feedkeys(t "gg<C-V>", "txn", false)
  2195. a.nvim_win_call(win_lines, function() a.nvim_feedkeys(t "G<C-V>", "txn", false) end)
  2196. vim.cmd "redraw"
  2197. ]]
  2198. end)
  2199. it('updates ruler if cursor moved', function()
  2200. -- Fixed for win_execute in vim-patch:8.1.2124, but should've applied to nvim_win_call too!
  2201. local screen = Screen.new(30, 5)
  2202. screen:set_default_attr_ids {
  2203. [1] = {reverse = true},
  2204. [2] = {bold = true, reverse = true},
  2205. }
  2206. screen:attach()
  2207. exec_lua [[
  2208. _G.a = vim.api
  2209. vim.opt.ruler = true
  2210. local lines = {}
  2211. for i = 0, 499 do lines[#lines + 1] = tostring(i) end
  2212. a.nvim_buf_set_lines(0, 0, -1, true, lines)
  2213. a.nvim_win_set_cursor(0, {20, 0})
  2214. vim.cmd "split"
  2215. _G.win = a.nvim_get_current_win()
  2216. vim.cmd "wincmd w | redraw"
  2217. ]]
  2218. screen:expect [[
  2219. 19 |
  2220. {1:[No Name] [+] 20,1 3%}|
  2221. ^19 |
  2222. {2:[No Name] [+] 20,1 3%}|
  2223. |
  2224. ]]
  2225. exec_lua [[
  2226. a.nvim_win_call(win, function() a.nvim_win_set_cursor(0, {100, 0}) end)
  2227. vim.cmd "redraw"
  2228. ]]
  2229. screen:expect [[
  2230. 99 |
  2231. {1:[No Name] [+] 100,1 19%}|
  2232. ^19 |
  2233. {2:[No Name] [+] 20,1 3%}|
  2234. |
  2235. ]]
  2236. end)
  2237. end)
  2238. end)
  2239. describe('lua: builtin modules', function()
  2240. local function do_tests()
  2241. eq(2, exec_lua[[return vim.tbl_count {x=1,y=2}]])
  2242. eq('{ 10, "spam" }', exec_lua[[return vim.inspect {10, 'spam'}]])
  2243. end
  2244. it('works', function()
  2245. clear()
  2246. do_tests()
  2247. end)
  2248. it('works when disabled', function()
  2249. clear('--luamod-dev')
  2250. do_tests()
  2251. end)
  2252. it('works without runtime', function()
  2253. clear{env={VIMRUNTIME='fixtures/a'}}
  2254. do_tests()
  2255. end)
  2256. it('does not work when disabled without runtime', function()
  2257. clear{args={'--luamod-dev'}, env={VIMRUNTIME='fixtures/a'}}
  2258. -- error checking could be better here. just check that --luamod-dev
  2259. -- does anything at all by breaking with missing runtime..
  2260. eq(nil, exec_lua[[return vim.tbl_count {x=1,y=2}]])
  2261. end)
  2262. end)
  2263. describe('lua: require("mod") from packages', function()
  2264. before_each(function()
  2265. clear('--cmd', 'set rtp+=test/functional/fixtures pp+=test/functional/fixtures')
  2266. end)
  2267. it('propagates syntax error', function()
  2268. local syntax_error_msg = exec_lua [[
  2269. local _, err = pcall(require, "syntax_error")
  2270. return err
  2271. ]]
  2272. matches("unexpected symbol", syntax_error_msg)
  2273. end)
  2274. it('uses the right order of mod.lua vs mod/init.lua', function()
  2275. -- lua/fancy_x.lua takes precedence over lua/fancy_x/init.lua
  2276. eq('I am fancy_x.lua', exec_lua [[ return require'fancy_x' ]])
  2277. -- but lua/fancy_y/init.lua takes precedence over after/lua/fancy_y.lua
  2278. eq('I am init.lua of fancy_y!', exec_lua [[ return require'fancy_y' ]])
  2279. -- safety check: after/lua/fancy_z.lua is still loaded
  2280. eq('I am fancy_z.lua', exec_lua [[ return require'fancy_z' ]])
  2281. end)
  2282. end)
  2283. describe('vim.keymap', function()
  2284. before_each(clear)
  2285. it('can make a mapping', function()
  2286. eq(0, exec_lua [[
  2287. GlobalCount = 0
  2288. vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount + 1 end)
  2289. return GlobalCount
  2290. ]])
  2291. feed('asdf\n')
  2292. eq(1, exec_lua[[return GlobalCount]])
  2293. end)
  2294. it('can make an expr mapping', function()
  2295. exec_lua [[
  2296. vim.keymap.set('n', 'aa', function() return ':lua SomeValue = 99<cr>' end, {expr = true})
  2297. ]]
  2298. feed('aa')
  2299. eq(99, exec_lua[[return SomeValue]])
  2300. end)
  2301. it('can overwrite a mapping', function()
  2302. eq(0, exec_lua [[
  2303. GlobalCount = 0
  2304. vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount + 1 end)
  2305. return GlobalCount
  2306. ]])
  2307. feed('asdf\n')
  2308. eq(1, exec_lua[[return GlobalCount]])
  2309. exec_lua [[
  2310. vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount - 1 end)
  2311. ]]
  2312. feed('asdf\n')
  2313. eq(0, exec_lua[[return GlobalCount]])
  2314. end)
  2315. it('can unmap a mapping', function()
  2316. eq(0, exec_lua [[
  2317. GlobalCount = 0
  2318. vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount + 1 end)
  2319. return GlobalCount
  2320. ]])
  2321. feed('asdf\n')
  2322. eq(1, exec_lua[[return GlobalCount]])
  2323. exec_lua [[
  2324. vim.keymap.del('n', 'asdf')
  2325. ]]
  2326. feed('asdf\n')
  2327. eq(1, exec_lua[[return GlobalCount]])
  2328. eq('\nNo mapping found', helpers.exec_capture('nmap asdf'))
  2329. end)
  2330. it('works with buffer-local mappings', function()
  2331. eq(0, exec_lua [[
  2332. GlobalCount = 0
  2333. vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount + 1 end, {buffer=true})
  2334. return GlobalCount
  2335. ]])
  2336. feed('asdf\n')
  2337. eq(1, exec_lua[[return GlobalCount]])
  2338. exec_lua [[
  2339. vim.keymap.del('n', 'asdf', {buffer=true})
  2340. ]]
  2341. feed('asdf\n')
  2342. eq(1, exec_lua[[return GlobalCount]])
  2343. eq('\nNo mapping found', helpers.exec_capture('nmap asdf'))
  2344. end)
  2345. it('does not mutate the opts parameter', function()
  2346. eq(true, exec_lua [[
  2347. opts = {buffer=true}
  2348. vim.keymap.set('n', 'asdf', function() end, opts)
  2349. return opts.buffer
  2350. ]])
  2351. eq(true, exec_lua [[
  2352. vim.keymap.del('n', 'asdf', opts)
  2353. return opts.buffer
  2354. ]])
  2355. end)
  2356. it('can do <Plug> mappings', function()
  2357. eq(0, exec_lua [[
  2358. GlobalCount = 0
  2359. vim.keymap.set('n', '<plug>(asdf)', function() GlobalCount = GlobalCount + 1 end)
  2360. vim.keymap.set('n', 'ww', '<plug>(asdf)')
  2361. return GlobalCount
  2362. ]])
  2363. feed('ww\n')
  2364. eq(1, exec_lua[[return GlobalCount]])
  2365. end)
  2366. end)