option_and_var_spec.lua 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local Screen = require('test.functional.ui.screen')
  4. local NIL = vim.NIL
  5. local feed = n.feed
  6. local command = n.command
  7. local clear = n.clear
  8. local api = n.api
  9. local eq = t.eq
  10. local eval = n.eval
  11. local exec = n.exec
  12. local exec_lua = n.exec_lua
  13. local fn = n.fn
  14. local matches = t.matches
  15. local mkdir_p = n.mkdir_p
  16. local pcall_err = t.pcall_err
  17. local rmdir = n.rmdir
  18. local write_file = t.write_file
  19. local function eq_exec_lua(expected, f)
  20. eq(expected, exec_lua(f))
  21. end
  22. describe('lua stdlib', function()
  23. before_each(clear)
  24. describe('variables', function()
  25. it('vim.g', function()
  26. exec_lua(function()
  27. vim.api.nvim_set_var('testing', 'hi')
  28. vim.api.nvim_set_var('other', 123)
  29. vim.api.nvim_set_var('floaty', 5120.1)
  30. vim.api.nvim_set_var('nullvar', vim.NIL)
  31. vim.api.nvim_set_var('to_delete', { hello = 'world' })
  32. end)
  33. eq('hi', fn.luaeval 'vim.g.testing')
  34. eq(123, fn.luaeval 'vim.g.other')
  35. eq(5120.1, fn.luaeval 'vim.g.floaty')
  36. eq(NIL, fn.luaeval 'vim.g.nonexistent')
  37. eq(NIL, fn.luaeval 'vim.g.nullvar')
  38. -- lost over RPC, so test locally:
  39. eq_exec_lua({ false, true }, function()
  40. return { vim.g.nonexistent == vim.NIL, vim.g.nullvar == vim.NIL }
  41. end)
  42. eq({ hello = 'world' }, fn.luaeval 'vim.g.to_delete')
  43. exec_lua [[
  44. vim.g.to_delete = nil
  45. ]]
  46. eq(NIL, fn.luaeval 'vim.g.to_delete')
  47. matches([[attempt to index .* nil value]], pcall_err(exec_lua, 'return vim.g[0].testing'))
  48. exec_lua(function()
  49. local counter = 0
  50. local function add_counter()
  51. counter = counter + 1
  52. end
  53. local function get_counter()
  54. return counter
  55. end
  56. vim.g.AddCounter = add_counter
  57. vim.g.GetCounter = get_counter
  58. vim.g.fn = { add = add_counter, get = get_counter }
  59. vim.g.AddParens = function(s)
  60. return '(' .. s .. ')'
  61. end
  62. end)
  63. eq(0, eval('g:GetCounter()'))
  64. eval('g:AddCounter()')
  65. eq(1, eval('g:GetCounter()'))
  66. eval('g:AddCounter()')
  67. eq(2, eval('g:GetCounter()'))
  68. exec_lua([[vim.g.AddCounter()]])
  69. eq(3, exec_lua([[return vim.g.GetCounter()]]))
  70. exec_lua([[vim.api.nvim_get_var('AddCounter')()]])
  71. eq(4, exec_lua([[return vim.api.nvim_get_var('GetCounter')()]]))
  72. exec_lua([[vim.g.fn.add()]])
  73. eq(5, exec_lua([[return vim.g.fn.get()]]))
  74. exec_lua([[vim.api.nvim_get_var('fn').add()]])
  75. eq(6, exec_lua([[return vim.api.nvim_get_var('fn').get()]]))
  76. eq('((foo))', eval([['foo'->AddParens()->AddParens()]]))
  77. exec_lua(function()
  78. local counter = 0
  79. local function add_counter()
  80. counter = counter + 1
  81. end
  82. local function get_counter()
  83. return counter
  84. end
  85. vim.api.nvim_set_var('AddCounter', add_counter)
  86. vim.api.nvim_set_var('GetCounter', get_counter)
  87. vim.api.nvim_set_var('fn', { add = add_counter, get = get_counter })
  88. vim.api.nvim_set_var('AddParens', function(s)
  89. return '(' .. s .. ')'
  90. end)
  91. end)
  92. eq(0, eval('g:GetCounter()'))
  93. eval('g:AddCounter()')
  94. eq(1, eval('g:GetCounter()'))
  95. eval('g:AddCounter()')
  96. eq(2, eval('g:GetCounter()'))
  97. exec_lua([[vim.g.AddCounter()]])
  98. eq(3, exec_lua([[return vim.g.GetCounter()]]))
  99. exec_lua([[vim.api.nvim_get_var('AddCounter')()]])
  100. eq(4, exec_lua([[return vim.api.nvim_get_var('GetCounter')()]]))
  101. exec_lua([[vim.g.fn.add()]])
  102. eq(5, exec_lua([[return vim.g.fn.get()]]))
  103. exec_lua([[vim.api.nvim_get_var('fn').add()]])
  104. eq(6, exec_lua([[return vim.api.nvim_get_var('fn').get()]]))
  105. eq('((foo))', eval([['foo'->AddParens()->AddParens()]]))
  106. exec([[
  107. function Test()
  108. endfunction
  109. function s:Test()
  110. endfunction
  111. let g:Unknown_func = function('Test')
  112. let g:Unknown_script_func = function('s:Test')
  113. ]])
  114. eq(NIL, exec_lua([[return vim.g.Unknown_func]]))
  115. eq(NIL, exec_lua([[return vim.g.Unknown_script_func]]))
  116. -- Check if autoload works properly
  117. local pathsep = n.get_pathsep()
  118. local xconfig = 'Xhome' .. pathsep .. 'Xconfig'
  119. local xdata = 'Xhome' .. pathsep .. 'Xdata'
  120. local autoload_folder = table.concat({ xconfig, 'nvim', 'autoload' }, pathsep)
  121. local autoload_file = table.concat({ autoload_folder, 'testload.vim' }, pathsep)
  122. mkdir_p(autoload_folder)
  123. write_file(autoload_file, [[let testload#value = 2]])
  124. clear { args_rm = { '-u' }, env = { XDG_CONFIG_HOME = xconfig, XDG_DATA_HOME = xdata } }
  125. eq(2, exec_lua("return vim.g['testload#value']"))
  126. rmdir('Xhome')
  127. end)
  128. it('vim.b', function()
  129. exec_lua(function()
  130. vim.api.nvim_buf_set_var(0, 'testing', 'hi')
  131. vim.api.nvim_buf_set_var(0, 'other', 123)
  132. vim.api.nvim_buf_set_var(0, 'floaty', 5120.1)
  133. vim.api.nvim_buf_set_var(0, 'nullvar', vim.NIL)
  134. vim.api.nvim_buf_set_var(0, 'to_delete', { hello = 'world' })
  135. _G.BUF = vim.api.nvim_create_buf(false, true)
  136. vim.api.nvim_buf_set_var(_G.BUF, 'testing', 'bye')
  137. end)
  138. eq('hi', fn.luaeval 'vim.b.testing')
  139. eq('bye', fn.luaeval 'vim.b[BUF].testing')
  140. eq(123, fn.luaeval 'vim.b.other')
  141. eq(5120.1, fn.luaeval 'vim.b.floaty')
  142. eq(NIL, fn.luaeval 'vim.b.nonexistent')
  143. eq(NIL, fn.luaeval 'vim.b[BUF].nonexistent')
  144. eq(NIL, fn.luaeval 'vim.b.nullvar')
  145. -- lost over RPC, so test locally:
  146. eq_exec_lua({ false, true }, function()
  147. return { vim.b.nonexistent == vim.NIL, vim.b.nullvar == vim.NIL }
  148. end)
  149. matches(
  150. [[attempt to index .* nil value]],
  151. pcall_err(exec_lua, 'return vim.b[BUF][0].testing')
  152. )
  153. eq({ hello = 'world' }, fn.luaeval 'vim.b.to_delete')
  154. exec_lua [[
  155. vim.b.to_delete = nil
  156. ]]
  157. eq(NIL, fn.luaeval 'vim.b.to_delete')
  158. exec_lua(function()
  159. local counter = 0
  160. local function add_counter()
  161. counter = counter + 1
  162. end
  163. local function get_counter()
  164. return counter
  165. end
  166. vim.b.AddCounter = add_counter
  167. vim.b.GetCounter = get_counter
  168. vim.b.fn = { add = add_counter, get = get_counter }
  169. vim.b.AddParens = function(s)
  170. return '(' .. s .. ')'
  171. end
  172. end)
  173. eq(0, eval('b:GetCounter()'))
  174. eval('b:AddCounter()')
  175. eq(1, eval('b:GetCounter()'))
  176. eval('b:AddCounter()')
  177. eq(2, eval('b:GetCounter()'))
  178. exec_lua([[vim.b.AddCounter()]])
  179. eq(3, exec_lua([[return vim.b.GetCounter()]]))
  180. exec_lua([[vim.api.nvim_buf_get_var(0, 'AddCounter')()]])
  181. eq(4, exec_lua([[return vim.api.nvim_buf_get_var(0, 'GetCounter')()]]))
  182. exec_lua([[vim.b.fn.add()]])
  183. eq(5, exec_lua([[return vim.b.fn.get()]]))
  184. exec_lua([[vim.api.nvim_buf_get_var(0, 'fn').add()]])
  185. eq(6, exec_lua([[return vim.api.nvim_buf_get_var(0, 'fn').get()]]))
  186. eq('((foo))', eval([['foo'->b:AddParens()->b:AddParens()]]))
  187. exec_lua(function()
  188. local counter = 0
  189. local function add_counter()
  190. counter = counter + 1
  191. end
  192. local function get_counter()
  193. return counter
  194. end
  195. vim.api.nvim_buf_set_var(0, 'AddCounter', add_counter)
  196. vim.api.nvim_buf_set_var(0, 'GetCounter', get_counter)
  197. vim.api.nvim_buf_set_var(0, 'fn', { add = add_counter, get = get_counter })
  198. vim.api.nvim_buf_set_var(0, 'AddParens', function(s)
  199. return '(' .. s .. ')'
  200. end)
  201. end)
  202. eq(0, eval('b:GetCounter()'))
  203. eval('b:AddCounter()')
  204. eq(1, eval('b:GetCounter()'))
  205. eval('b:AddCounter()')
  206. eq(2, eval('b:GetCounter()'))
  207. exec_lua([[vim.b.AddCounter()]])
  208. eq(3, exec_lua([[return vim.b.GetCounter()]]))
  209. exec_lua([[vim.api.nvim_buf_get_var(0, 'AddCounter')()]])
  210. eq(4, exec_lua([[return vim.api.nvim_buf_get_var(0, 'GetCounter')()]]))
  211. exec_lua([[vim.b.fn.add()]])
  212. eq(5, exec_lua([[return vim.b.fn.get()]]))
  213. exec_lua([[vim.api.nvim_buf_get_var(0, 'fn').add()]])
  214. eq(6, exec_lua([[return vim.api.nvim_buf_get_var(0, 'fn').get()]]))
  215. eq('((foo))', eval([['foo'->b:AddParens()->b:AddParens()]]))
  216. exec([[
  217. function Test()
  218. endfunction
  219. function s:Test()
  220. endfunction
  221. let b:Unknown_func = function('Test')
  222. let b:Unknown_script_func = function('s:Test')
  223. ]])
  224. eq(NIL, exec_lua([[return vim.b.Unknown_func]]))
  225. eq(NIL, exec_lua([[return vim.b.Unknown_script_func]]))
  226. exec_lua [[
  227. vim.cmd "vnew"
  228. ]]
  229. eq(NIL, fn.luaeval 'vim.b.testing')
  230. eq(NIL, fn.luaeval 'vim.b.other')
  231. eq(NIL, fn.luaeval 'vim.b.nonexistent')
  232. end)
  233. it('vim.w', function()
  234. exec_lua [[
  235. vim.api.nvim_win_set_var(0, "testing", "hi")
  236. vim.api.nvim_win_set_var(0, "other", 123)
  237. vim.api.nvim_win_set_var(0, "to_delete", {hello="world"})
  238. BUF = vim.api.nvim_create_buf(false, true)
  239. WIN = vim.api.nvim_open_win(BUF, false, {
  240. width=10, height=10,
  241. relative='win', row=0, col=0
  242. })
  243. vim.api.nvim_win_set_var(WIN, "testing", "bye")
  244. ]]
  245. eq('hi', fn.luaeval 'vim.w.testing')
  246. eq('bye', fn.luaeval 'vim.w[WIN].testing')
  247. eq(123, fn.luaeval 'vim.w.other')
  248. eq(NIL, fn.luaeval 'vim.w.nonexistent')
  249. eq(NIL, fn.luaeval 'vim.w[WIN].nonexistent')
  250. matches(
  251. [[attempt to index .* nil value]],
  252. pcall_err(exec_lua, 'return vim.w[WIN][0].testing')
  253. )
  254. eq({ hello = 'world' }, fn.luaeval 'vim.w.to_delete')
  255. exec_lua [[
  256. vim.w.to_delete = nil
  257. ]]
  258. eq(NIL, fn.luaeval 'vim.w.to_delete')
  259. exec_lua [[
  260. local counter = 0
  261. local function add_counter() counter = counter + 1 end
  262. local function get_counter() return counter end
  263. vim.w.AddCounter = add_counter
  264. vim.w.GetCounter = get_counter
  265. vim.w.fn = {add = add_counter, get = get_counter}
  266. vim.w.AddParens = function(s) return '(' .. s .. ')' end
  267. ]]
  268. eq(0, eval('w:GetCounter()'))
  269. eval('w:AddCounter()')
  270. eq(1, eval('w:GetCounter()'))
  271. eval('w:AddCounter()')
  272. eq(2, eval('w:GetCounter()'))
  273. exec_lua([[vim.w.AddCounter()]])
  274. eq(3, exec_lua([[return vim.w.GetCounter()]]))
  275. exec_lua([[vim.api.nvim_win_get_var(0, 'AddCounter')()]])
  276. eq(4, exec_lua([[return vim.api.nvim_win_get_var(0, 'GetCounter')()]]))
  277. exec_lua([[vim.w.fn.add()]])
  278. eq(5, exec_lua([[return vim.w.fn.get()]]))
  279. exec_lua([[vim.api.nvim_win_get_var(0, 'fn').add()]])
  280. eq(6, exec_lua([[return vim.api.nvim_win_get_var(0, 'fn').get()]]))
  281. eq('((foo))', eval([['foo'->w:AddParens()->w:AddParens()]]))
  282. exec_lua [[
  283. local counter = 0
  284. local function add_counter() counter = counter + 1 end
  285. local function get_counter() return counter end
  286. vim.api.nvim_win_set_var(0, 'AddCounter', add_counter)
  287. vim.api.nvim_win_set_var(0, 'GetCounter', get_counter)
  288. vim.api.nvim_win_set_var(0, 'fn', {add = add_counter, get = get_counter})
  289. vim.api.nvim_win_set_var(0, 'AddParens', function(s) return '(' .. s .. ')' end)
  290. ]]
  291. eq(0, eval('w:GetCounter()'))
  292. eval('w:AddCounter()')
  293. eq(1, eval('w:GetCounter()'))
  294. eval('w:AddCounter()')
  295. eq(2, eval('w:GetCounter()'))
  296. exec_lua([[vim.w.AddCounter()]])
  297. eq(3, exec_lua([[return vim.w.GetCounter()]]))
  298. exec_lua([[vim.api.nvim_win_get_var(0, 'AddCounter')()]])
  299. eq(4, exec_lua([[return vim.api.nvim_win_get_var(0, 'GetCounter')()]]))
  300. exec_lua([[vim.w.fn.add()]])
  301. eq(5, exec_lua([[return vim.w.fn.get()]]))
  302. exec_lua([[vim.api.nvim_win_get_var(0, 'fn').add()]])
  303. eq(6, exec_lua([[return vim.api.nvim_win_get_var(0, 'fn').get()]]))
  304. eq('((foo))', eval([['foo'->w:AddParens()->w:AddParens()]]))
  305. exec([[
  306. function Test()
  307. endfunction
  308. function s:Test()
  309. endfunction
  310. let w:Unknown_func = function('Test')
  311. let w:Unknown_script_func = function('s:Test')
  312. ]])
  313. eq(NIL, exec_lua([[return vim.w.Unknown_func]]))
  314. eq(NIL, exec_lua([[return vim.w.Unknown_script_func]]))
  315. exec_lua [[
  316. vim.cmd "vnew"
  317. ]]
  318. eq(NIL, fn.luaeval 'vim.w.testing')
  319. eq(NIL, fn.luaeval 'vim.w.other')
  320. eq(NIL, fn.luaeval 'vim.w.nonexistent')
  321. end)
  322. it('vim.t', function()
  323. exec_lua [[
  324. vim.api.nvim_tabpage_set_var(0, "testing", "hi")
  325. vim.api.nvim_tabpage_set_var(0, "other", 123)
  326. vim.api.nvim_tabpage_set_var(0, "to_delete", {hello="world"})
  327. ]]
  328. eq('hi', fn.luaeval 'vim.t.testing')
  329. eq(123, fn.luaeval 'vim.t.other')
  330. eq(NIL, fn.luaeval 'vim.t.nonexistent')
  331. eq('hi', fn.luaeval 'vim.t[0].testing')
  332. eq(123, fn.luaeval 'vim.t[0].other')
  333. eq(NIL, fn.luaeval 'vim.t[0].nonexistent')
  334. matches([[attempt to index .* nil value]], pcall_err(exec_lua, 'return vim.t[0][0].testing'))
  335. eq({ hello = 'world' }, fn.luaeval 'vim.t.to_delete')
  336. exec_lua [[
  337. vim.t.to_delete = nil
  338. ]]
  339. eq(NIL, fn.luaeval 'vim.t.to_delete')
  340. exec_lua [[
  341. local counter = 0
  342. local function add_counter() counter = counter + 1 end
  343. local function get_counter() return counter end
  344. vim.t.AddCounter = add_counter
  345. vim.t.GetCounter = get_counter
  346. vim.t.fn = {add = add_counter, get = get_counter}
  347. vim.t.AddParens = function(s) return '(' .. s .. ')' end
  348. ]]
  349. eq(0, eval('t:GetCounter()'))
  350. eval('t:AddCounter()')
  351. eq(1, eval('t:GetCounter()'))
  352. eval('t:AddCounter()')
  353. eq(2, eval('t:GetCounter()'))
  354. exec_lua([[vim.t.AddCounter()]])
  355. eq(3, exec_lua([[return vim.t.GetCounter()]]))
  356. exec_lua([[vim.api.nvim_tabpage_get_var(0, 'AddCounter')()]])
  357. eq(4, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'GetCounter')()]]))
  358. exec_lua([[vim.t.fn.add()]])
  359. eq(5, exec_lua([[return vim.t.fn.get()]]))
  360. exec_lua([[vim.api.nvim_tabpage_get_var(0, 'fn').add()]])
  361. eq(6, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'fn').get()]]))
  362. eq('((foo))', eval([['foo'->t:AddParens()->t:AddParens()]]))
  363. exec_lua [[
  364. local counter = 0
  365. local function add_counter() counter = counter + 1 end
  366. local function get_counter() return counter end
  367. vim.api.nvim_tabpage_set_var(0, 'AddCounter', add_counter)
  368. vim.api.nvim_tabpage_set_var(0, 'GetCounter', get_counter)
  369. vim.api.nvim_tabpage_set_var(0, 'fn', {add = add_counter, get = get_counter})
  370. vim.api.nvim_tabpage_set_var(0, 'AddParens', function(s) return '(' .. s .. ')' end)
  371. ]]
  372. eq(0, eval('t:GetCounter()'))
  373. eval('t:AddCounter()')
  374. eq(1, eval('t:GetCounter()'))
  375. eval('t:AddCounter()')
  376. eq(2, eval('t:GetCounter()'))
  377. exec_lua([[vim.t.AddCounter()]])
  378. eq(3, exec_lua([[return vim.t.GetCounter()]]))
  379. exec_lua([[vim.api.nvim_tabpage_get_var(0, 'AddCounter')()]])
  380. eq(4, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'GetCounter')()]]))
  381. exec_lua([[vim.t.fn.add()]])
  382. eq(5, exec_lua([[return vim.t.fn.get()]]))
  383. exec_lua([[vim.api.nvim_tabpage_get_var(0, 'fn').add()]])
  384. eq(6, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'fn').get()]]))
  385. eq('((foo))', eval([['foo'->t:AddParens()->t:AddParens()]]))
  386. exec_lua [[
  387. vim.cmd "tabnew"
  388. ]]
  389. eq(NIL, fn.luaeval 'vim.t.testing')
  390. eq(NIL, fn.luaeval 'vim.t.other')
  391. eq(NIL, fn.luaeval 'vim.t.nonexistent')
  392. end)
  393. it('vim.env', function()
  394. exec_lua([[vim.fn.setenv('A', 123)]])
  395. eq('123', fn.luaeval('vim.env.A'))
  396. exec_lua([[vim.env.A = 456]])
  397. eq('456', fn.luaeval('vim.env.A'))
  398. exec_lua([[vim.env.A = nil]])
  399. eq(NIL, fn.luaeval('vim.env.A'))
  400. eq(true, fn.luaeval('vim.env.B == nil'))
  401. command([[let $HOME = 'foo']])
  402. eq('foo', fn.expand('~'))
  403. eq('foo', fn.luaeval('vim.env.HOME'))
  404. exec_lua([[vim.env.HOME = nil]])
  405. eq('foo', fn.expand('~'))
  406. exec_lua([[vim.env.HOME = 'bar']])
  407. eq('bar', fn.expand('~'))
  408. eq('bar', fn.luaeval('vim.env.HOME'))
  409. end)
  410. it('vim.v', function()
  411. eq(fn.luaeval "vim.api.nvim_get_vvar('progpath')", fn.luaeval 'vim.v.progpath')
  412. eq(false, fn.luaeval "vim.v['false']")
  413. eq(NIL, fn.luaeval 'vim.v.null')
  414. matches([[attempt to index .* nil value]], pcall_err(exec_lua, 'return vim.v[0].progpath'))
  415. eq('Key is read-only: count', pcall_err(exec_lua, [[vim.v.count = 42]]))
  416. eq('Dict is locked', pcall_err(exec_lua, [[vim.v.nosuchvar = 42]]))
  417. eq('Key is fixed: errmsg', pcall_err(exec_lua, [[vim.v.errmsg = nil]]))
  418. exec_lua([[vim.v.errmsg = 'set by Lua']])
  419. eq('set by Lua', eval('v:errmsg'))
  420. exec_lua([[vim.v.errmsg = 42]])
  421. eq('42', eval('v:errmsg'))
  422. exec_lua([[vim.v.oldfiles = { 'one', 'two' }]])
  423. eq({ 'one', 'two' }, eval('v:oldfiles'))
  424. exec_lua([[vim.v.oldfiles = {}]])
  425. eq({}, eval('v:oldfiles'))
  426. eq(
  427. 'Setting v:oldfiles to value with wrong type',
  428. pcall_err(exec_lua, [[vim.v.oldfiles = 'a']])
  429. )
  430. eq({}, eval('v:oldfiles'))
  431. feed('i foo foo foo<Esc>0/foo<CR>')
  432. eq({ 1, 1 }, api.nvim_win_get_cursor(0))
  433. eq(1, eval('v:searchforward'))
  434. feed('n')
  435. eq({ 1, 5 }, api.nvim_win_get_cursor(0))
  436. exec_lua([[vim.v.searchforward = 0]])
  437. eq(0, eval('v:searchforward'))
  438. feed('n')
  439. eq({ 1, 1 }, api.nvim_win_get_cursor(0))
  440. exec_lua([[vim.v.searchforward = 1]])
  441. eq(1, eval('v:searchforward'))
  442. feed('n')
  443. eq({ 1, 5 }, api.nvim_win_get_cursor(0))
  444. local screen = Screen.new(60, 3)
  445. eq(1, eval('v:hlsearch'))
  446. screen:expect {
  447. grid = [[
  448. {10:foo} {10:^foo} {10:foo} |
  449. {1:~ }|
  450. |
  451. ]],
  452. }
  453. exec_lua([[vim.v.hlsearch = 0]])
  454. eq(0, eval('v:hlsearch'))
  455. screen:expect {
  456. grid = [[
  457. foo ^foo foo |
  458. {1:~ }|
  459. |
  460. ]],
  461. }
  462. exec_lua([[vim.v.hlsearch = 1]])
  463. eq(1, eval('v:hlsearch'))
  464. screen:expect {
  465. grid = [[
  466. {10:foo} {10:^foo} {10:foo} |
  467. {1:~ }|
  468. |
  469. ]],
  470. }
  471. end)
  472. end)
  473. describe('options', function()
  474. describe('vim.bo', function()
  475. it('can get and set options', function()
  476. eq('', fn.luaeval 'vim.bo.filetype')
  477. exec_lua(function()
  478. _G.BUF = vim.api.nvim_create_buf(false, true)
  479. vim.api.nvim_set_option_value('filetype', 'markdown', {})
  480. vim.api.nvim_set_option_value('modifiable', false, { buf = _G.BUF })
  481. end)
  482. eq(false, fn.luaeval 'vim.bo.modified')
  483. eq('markdown', fn.luaeval 'vim.bo.filetype')
  484. eq(false, fn.luaeval 'vim.bo[BUF].modifiable')
  485. exec_lua(function()
  486. vim.bo.filetype = ''
  487. vim.bo[_G.BUF].modifiable = true
  488. end)
  489. eq('', fn.luaeval 'vim.bo.filetype')
  490. eq(true, fn.luaeval 'vim.bo[BUF].modifiable')
  491. end)
  492. it('errors', function()
  493. matches("Unknown option 'nosuchopt'$", pcall_err(exec_lua, 'return vim.bo.nosuchopt'))
  494. matches('Expected Lua string$', pcall_err(exec_lua, 'return vim.bo[0][0].autoread'))
  495. matches('Invalid buffer id: %-1$', pcall_err(exec_lua, 'return vim.bo[-1].filetype'))
  496. end)
  497. end)
  498. describe('vim.wo', function()
  499. it('can get and set options', function()
  500. exec_lua(function()
  501. vim.api.nvim_set_option_value('cole', 2, {})
  502. vim.cmd 'split'
  503. vim.api.nvim_set_option_value('cole', 2, {})
  504. end)
  505. eq(2, fn.luaeval 'vim.wo.cole')
  506. exec_lua(function()
  507. vim.wo.conceallevel = 0
  508. end)
  509. eq(0, fn.luaeval 'vim.wo.cole')
  510. eq(0, fn.luaeval 'vim.wo[0].cole')
  511. eq(0, fn.luaeval 'vim.wo[1001].cole')
  512. matches("Unknown option 'notanopt'$", pcall_err(exec_lua, 'return vim.wo.notanopt'))
  513. matches('Invalid window id: %-1$', pcall_err(exec_lua, 'return vim.wo[-1].list'))
  514. eq(2, fn.luaeval 'vim.wo[1000].cole')
  515. exec_lua(function()
  516. vim.wo[1000].cole = 0
  517. end)
  518. eq(0, fn.luaeval 'vim.wo[1000].cole')
  519. -- Can handle global-local values
  520. exec_lua [[vim.o.scrolloff = 100]]
  521. exec_lua [[vim.wo.scrolloff = 200]]
  522. eq(200, fn.luaeval 'vim.wo.scrolloff')
  523. exec_lua [[vim.wo.scrolloff = -1]]
  524. eq(100, fn.luaeval 'vim.wo.scrolloff')
  525. exec_lua(function()
  526. vim.wo[0][0].scrolloff = 200
  527. vim.cmd 'enew'
  528. end)
  529. eq(100, fn.luaeval 'vim.wo.scrolloff')
  530. end)
  531. it('errors', function()
  532. matches('only bufnr=0 is supported', pcall_err(exec_lua, 'vim.wo[0][10].signcolumn = "no"'))
  533. matches(
  534. 'only bufnr=0 is supported',
  535. pcall_err(exec_lua, 'local a = vim.wo[0][10].signcolumn')
  536. )
  537. end)
  538. end)
  539. describe('vim.opt', function()
  540. -- TODO: We still need to write some tests for optlocal, opt and then getting the options
  541. -- Probably could also do some stuff with getting things from viml side as well to confirm behavior is the same.
  542. it('allows setting number values', function()
  543. local scrolloff = exec_lua [[
  544. vim.opt.scrolloff = 10
  545. return vim.o.scrolloff
  546. ]]
  547. eq(10, scrolloff)
  548. end)
  549. pending('handles STUPID window things', function()
  550. eq_exec_lua({}, function()
  551. return {
  552. vim.api.nvim_get_option_value('scrolloff', { scope = 'global' }),
  553. vim.api.nvim_get_option_value('scrolloff', { win = 0 }),
  554. }
  555. end)
  556. end)
  557. it('allows setting tables', function()
  558. eq_exec_lua('hello,world', function()
  559. vim.opt.wildignore = { 'hello', 'world' }
  560. return vim.o.wildignore
  561. end)
  562. end)
  563. it('allows setting tables with shortnames', function()
  564. eq_exec_lua('hello,world', function()
  565. vim.opt.wig = { 'hello', 'world' }
  566. return vim.o.wildignore
  567. end)
  568. end)
  569. it('errors when you attempt to set string values to numeric options', function()
  570. eq_exec_lua(false, function()
  571. return ({
  572. pcall(function()
  573. vim.opt.textwidth = 'hello world'
  574. end),
  575. })[1]
  576. end)
  577. end)
  578. it('errors when you attempt to setlocal a global value', function()
  579. eq_exec_lua(false, function()
  580. return pcall(function()
  581. vim.opt_local.clipboard = 'hello'
  582. end)
  583. end)
  584. end)
  585. it('allows you to set boolean values', function()
  586. eq_exec_lua({ true, false, true }, function()
  587. local results = {}
  588. vim.opt.autoindent = true
  589. table.insert(results, vim.bo.autoindent)
  590. vim.opt.autoindent = false
  591. table.insert(results, vim.bo.autoindent)
  592. vim.opt.autoindent = not vim.opt.autoindent:get()
  593. table.insert(results, vim.bo.autoindent)
  594. return results
  595. end)
  596. end)
  597. it('changes current buffer values and defaults for global local values', function()
  598. local result = exec_lua(function()
  599. local result = {}
  600. vim.opt.makeprg = 'global-local'
  601. table.insert(result, vim.go.makeprg)
  602. table.insert(result, vim.api.nvim_get_option_value('makeprg', { buf = 0 }))
  603. vim.opt_local.mp = 'only-local'
  604. table.insert(result, vim.go.makeprg)
  605. table.insert(result, vim.api.nvim_get_option_value('makeprg', { buf = 0 }))
  606. vim.opt_global.makeprg = 'only-global'
  607. table.insert(result, vim.go.makeprg)
  608. table.insert(result, vim.api.nvim_get_option_value('makeprg', { buf = 0 }))
  609. vim.opt.makeprg = 'global-local'
  610. table.insert(result, vim.go.makeprg)
  611. table.insert(result, vim.api.nvim_get_option_value('makeprg', { buf = 0 }))
  612. return result
  613. end)
  614. -- Set -> global & local
  615. eq('global-local', result[1])
  616. eq('', result[2])
  617. -- Setlocal -> only local
  618. eq('global-local', result[3])
  619. eq('only-local', result[4])
  620. -- Setglobal -> only global
  621. eq('only-global', result[5])
  622. eq('only-local', result[6])
  623. -- Set -> sets global value and resets local value
  624. eq('global-local', result[7])
  625. eq('', result[8])
  626. end)
  627. it('allows you to retrieve window opts even if they have not been set', function()
  628. eq_exec_lua({ false, false, true, true }, function()
  629. local result = {}
  630. table.insert(result, vim.opt.number:get())
  631. table.insert(result, vim.opt_local.number:get())
  632. vim.opt_local.number = true
  633. table.insert(result, vim.opt.number:get())
  634. table.insert(result, vim.opt_local.number:get())
  635. return result
  636. end)
  637. end)
  638. it('allows all sorts of string manipulation', function()
  639. eq_exec_lua({ 'hello', 'hello world', 'start hello world' }, function()
  640. local results = {}
  641. vim.opt.makeprg = 'hello'
  642. table.insert(results, vim.o.makeprg)
  643. vim.opt.makeprg = vim.opt.makeprg + ' world'
  644. table.insert(results, vim.o.makeprg)
  645. vim.opt.makeprg = vim.opt.makeprg ^ 'start '
  646. table.insert(results, vim.o.makeprg)
  647. return results
  648. end)
  649. end)
  650. describe('option:get()', function()
  651. it('works for boolean values', function()
  652. eq_exec_lua(false, function()
  653. vim.opt.number = false
  654. return vim.opt.number:get()
  655. end)
  656. end)
  657. it('works for number values', function()
  658. eq_exec_lua(10, function()
  659. vim.opt.tabstop = 10
  660. return vim.opt.tabstop:get()
  661. end)
  662. end)
  663. it('works for string values', function()
  664. eq_exec_lua('hello world', function()
  665. vim.opt.makeprg = 'hello world'
  666. return vim.opt.makeprg:get()
  667. end)
  668. end)
  669. it('works for set type flaglists', function()
  670. local formatoptions = exec_lua(function()
  671. vim.opt.formatoptions = 'tcro'
  672. return vim.opt.formatoptions:get()
  673. end)
  674. eq(true, formatoptions.t)
  675. eq(true, not formatoptions.q)
  676. end)
  677. it('works for set type flaglists', function()
  678. local formatoptions = exec_lua(function()
  679. vim.opt.formatoptions = { t = true, c = true, r = true, o = true }
  680. return vim.opt.formatoptions:get()
  681. end)
  682. eq(true, formatoptions.t)
  683. eq(true, not formatoptions.q)
  684. end)
  685. it('works for array list type options', function()
  686. local wildignore = exec_lua(function()
  687. vim.opt.wildignore = '*.c,*.o,__pycache__'
  688. return vim.opt.wildignore:get()
  689. end)
  690. eq(3, #wildignore)
  691. eq('*.c', wildignore[1])
  692. end)
  693. it('works for options that are both commalist and flaglist', function()
  694. eq_exec_lua({ b = true, s = true }, function()
  695. vim.opt.whichwrap = 'b,s'
  696. return vim.opt.whichwrap:get()
  697. end)
  698. eq_exec_lua({ b = true, h = true }, function()
  699. vim.opt.whichwrap = { b = true, s = false, h = true }
  700. return vim.opt.whichwrap:get()
  701. end)
  702. end)
  703. it('works for key-value pair options', function()
  704. eq_exec_lua({ tab = '> ', space = '_' }, function()
  705. vim.opt.listchars = 'tab:> ,space:_'
  706. return vim.opt.listchars:get()
  707. end)
  708. end)
  709. it('allows you to add numeric options', function()
  710. eq_exec_lua(16, function()
  711. vim.opt.tabstop = 12
  712. vim.opt.tabstop = vim.opt.tabstop + 4
  713. return vim.bo.tabstop
  714. end)
  715. end)
  716. it('allows you to subtract numeric options', function()
  717. eq_exec_lua(2, function()
  718. vim.opt.tabstop = 4
  719. vim.opt.tabstop = vim.opt.tabstop - 2
  720. return vim.bo.tabstop
  721. end)
  722. end)
  723. end)
  724. describe('key:value style options', function()
  725. it('handles dict style', function()
  726. eq_exec_lua('eol:~,space:.', function()
  727. vim.opt.listchars = { eol = '~', space = '.' }
  728. return vim.o.listchars
  729. end)
  730. end)
  731. it('allows adding dict style', function()
  732. eq_exec_lua('eol:~,space:-', function()
  733. vim.opt.listchars = { eol = '~', space = '.' }
  734. vim.opt.listchars = vim.opt.listchars + { space = '-' }
  735. return vim.o.listchars
  736. end)
  737. end)
  738. it('allows adding dict style', function()
  739. eq_exec_lua('eol:~,space:_', function()
  740. vim.opt.listchars = { eol = '~', space = '.' }
  741. vim.opt.listchars = vim.opt.listchars + { space = '-' } + { space = '_' }
  742. return vim.o.listchars
  743. end)
  744. end)
  745. it('allows completely new keys', function()
  746. eq_exec_lua('eol:~,space:.,tab:>>>', function()
  747. vim.opt.listchars = { eol = '~', space = '.' }
  748. vim.opt.listchars = vim.opt.listchars + { tab = '>>>' }
  749. return vim.o.listchars
  750. end)
  751. end)
  752. it('allows subtracting dict style', function()
  753. eq_exec_lua('eol:~', function()
  754. vim.opt.listchars = { eol = '~', space = '.' }
  755. vim.opt.listchars = vim.opt.listchars - 'space'
  756. return vim.o.listchars
  757. end)
  758. end)
  759. it('allows subtracting dict style', function()
  760. eq_exec_lua('', function()
  761. vim.opt.listchars = { eol = '~', space = '.' }
  762. vim.opt.listchars = vim.opt.listchars - 'space' - 'eol'
  763. return vim.o.listchars
  764. end)
  765. end)
  766. it('allows subtracting dict style multiple times', function()
  767. eq_exec_lua('eol:~', function()
  768. vim.opt.listchars = { eol = '~', space = '.' }
  769. vim.opt.listchars = vim.opt.listchars - 'space' - 'space'
  770. return vim.o.listchars
  771. end)
  772. end)
  773. it('allows adding a key:value string to a listchars', function()
  774. eq_exec_lua('eol:~,space:.,tab:>~', function()
  775. vim.opt.listchars = { eol = '~', space = '.' }
  776. vim.opt.listchars = vim.opt.listchars + 'tab:>~'
  777. return vim.o.listchars
  778. end)
  779. end)
  780. it('allows prepending a key:value string to a listchars', function()
  781. eq_exec_lua('eol:~,space:.,tab:>~', function()
  782. vim.opt.listchars = { eol = '~', space = '.' }
  783. vim.opt.listchars = vim.opt.listchars ^ 'tab:>~'
  784. return vim.o.listchars
  785. end)
  786. end)
  787. end)
  788. it('automatically sets when calling remove', function()
  789. eq_exec_lua('foo,baz', function()
  790. vim.opt.wildignore = 'foo,bar,baz'
  791. vim.opt.wildignore:remove('bar')
  792. return vim.o.wildignore
  793. end)
  794. end)
  795. it('automatically sets when calling remove with a table', function()
  796. eq_exec_lua('foo', function()
  797. vim.opt.wildignore = 'foo,bar,baz'
  798. vim.opt.wildignore:remove { 'bar', 'baz' }
  799. return vim.o.wildignore
  800. end)
  801. end)
  802. it('automatically sets when calling append', function()
  803. eq_exec_lua('foo,bar,baz,bing', function()
  804. vim.opt.wildignore = 'foo,bar,baz'
  805. vim.opt.wildignore:append('bing')
  806. return vim.o.wildignore
  807. end)
  808. end)
  809. it('automatically sets when calling append with a table', function()
  810. eq_exec_lua('foo,bar,baz,bing,zap', function()
  811. vim.opt.wildignore = 'foo,bar,baz'
  812. vim.opt.wildignore:append { 'bing', 'zap' }
  813. return vim.o.wildignore
  814. end)
  815. end)
  816. it('allows adding tables', function()
  817. eq_exec_lua('foo', function()
  818. vim.opt.wildignore = 'foo'
  819. return vim.o.wildignore
  820. end)
  821. eq_exec_lua('foo,bar,baz', function()
  822. vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' }
  823. return vim.o.wildignore
  824. end)
  825. end)
  826. it('handles adding duplicates', function()
  827. eq_exec_lua('foo', function()
  828. vim.opt.wildignore = 'foo'
  829. return vim.o.wildignore
  830. end)
  831. eq_exec_lua('foo,bar,baz', function()
  832. vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' }
  833. return vim.o.wildignore
  834. end)
  835. eq_exec_lua('foo,bar,baz', function()
  836. vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' }
  837. return vim.o.wildignore
  838. end)
  839. end)
  840. it('allows adding multiple times', function()
  841. eq_exec_lua('foo,bar,baz', function()
  842. vim.opt.wildignore = 'foo'
  843. vim.opt.wildignore = vim.opt.wildignore + 'bar' + 'baz'
  844. return vim.o.wildignore
  845. end)
  846. end)
  847. it('removes values when you use minus', function()
  848. eq_exec_lua('foo', function()
  849. vim.opt.wildignore = 'foo'
  850. return vim.o.wildignore
  851. end)
  852. eq_exec_lua('foo,bar,baz', function()
  853. vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' }
  854. return vim.o.wildignore
  855. end)
  856. eq_exec_lua('foo,baz', function()
  857. vim.opt.wildignore = vim.opt.wildignore - 'bar'
  858. return vim.o.wildignore
  859. end)
  860. end)
  861. it('prepends values when using ^', function()
  862. eq_exec_lua('first,foo', function()
  863. vim.opt.wildignore = 'foo'
  864. vim.opt.wildignore = vim.opt.wildignore ^ 'first'
  865. return vim.o.wildignore
  866. end)
  867. eq_exec_lua('super_first,first,foo', function()
  868. vim.opt.wildignore = vim.opt.wildignore ^ 'super_first'
  869. return vim.o.wildignore
  870. end)
  871. end)
  872. it('does not remove duplicates from wildmode: #14708', function()
  873. eq_exec_lua('full,list,full', function()
  874. vim.opt.wildmode = { 'full', 'list', 'full' }
  875. return vim.o.wildmode
  876. end)
  877. end)
  878. describe('option types', function()
  879. it('allows to set option with numeric value', function()
  880. eq_exec_lua(4, function()
  881. vim.opt.tabstop = 4
  882. return vim.bo.tabstop
  883. end)
  884. matches(
  885. "Invalid option type 'string' for 'tabstop'",
  886. pcall_err(exec_lua, [[vim.opt.tabstop = '4']])
  887. )
  888. matches(
  889. "Invalid option type 'boolean' for 'tabstop'",
  890. pcall_err(exec_lua, [[vim.opt.tabstop = true]])
  891. )
  892. matches(
  893. "Invalid option type 'table' for 'tabstop'",
  894. pcall_err(exec_lua, [[vim.opt.tabstop = {4, 2}]])
  895. )
  896. matches(
  897. "Invalid option type 'function' for 'tabstop'",
  898. pcall_err(exec_lua, [[vim.opt.tabstop = function() return 4 end]])
  899. )
  900. end)
  901. it('allows to set option with boolean value', function()
  902. eq_exec_lua(true, function()
  903. vim.opt.undofile = true
  904. return vim.bo.undofile
  905. end)
  906. matches(
  907. "Invalid option type 'number' for 'undofile'",
  908. pcall_err(exec_lua, [[vim.opt.undofile = 0]])
  909. )
  910. matches(
  911. "Invalid option type 'table' for 'undofile'",
  912. pcall_err(exec_lua, [[vim.opt.undofile = {true}]])
  913. )
  914. matches(
  915. "Invalid option type 'string' for 'undofile'",
  916. pcall_err(exec_lua, [[vim.opt.undofile = 'true']])
  917. )
  918. matches(
  919. "Invalid option type 'function' for 'undofile'",
  920. pcall_err(exec_lua, [[vim.opt.undofile = function() return true end]])
  921. )
  922. end)
  923. it('allows to set option with array or string value', function()
  924. eq_exec_lua('indent,eol,start', function()
  925. vim.opt.backspace = { 'indent', 'eol', 'start' }
  926. return vim.go.backspace
  927. end)
  928. eq_exec_lua('indent,eol,start', function()
  929. vim.opt.backspace = 'indent,eol,start'
  930. return vim.go.backspace
  931. end)
  932. matches(
  933. "Invalid option type 'boolean' for 'backspace'",
  934. pcall_err(exec_lua, [[vim.opt.backspace = true]])
  935. )
  936. matches(
  937. "Invalid option type 'number' for 'backspace'",
  938. pcall_err(exec_lua, [[vim.opt.backspace = 2]])
  939. )
  940. matches(
  941. "Invalid option type 'function' for 'backspace'",
  942. pcall_err(exec_lua, [[vim.opt.backspace = function() return 'indent,eol,start' end]])
  943. )
  944. end)
  945. it('allows set option with map or string value', function()
  946. eq_exec_lua('eol:~,space:.', function()
  947. vim.opt.listchars = { eol = '~', space = '.' }
  948. return vim.o.listchars
  949. end)
  950. eq_exec_lua('eol:~,space:.,tab:>~', function()
  951. vim.opt.listchars = 'eol:~,space:.,tab:>~'
  952. return vim.o.listchars
  953. end)
  954. matches(
  955. "Invalid option type 'boolean' for 'listchars'",
  956. pcall_err(exec_lua, [[vim.opt.listchars = true]])
  957. )
  958. matches(
  959. "Invalid option type 'number' for 'listchars'",
  960. pcall_err(exec_lua, [[vim.opt.listchars = 2]])
  961. )
  962. matches(
  963. "Invalid option type 'function' for 'listchars'",
  964. pcall_err(
  965. exec_lua,
  966. [[vim.opt.listchars = function() return "eol:~,space:.,tab:>~" end]]
  967. )
  968. )
  969. end)
  970. it('allows set option with set or string value', function()
  971. eq_exec_lua('b,s', function()
  972. vim.opt.whichwrap = { b = true, s = 1 }
  973. return vim.go.whichwrap
  974. end)
  975. eq_exec_lua('b,s,<,>,[,]', function()
  976. vim.opt.whichwrap = 'b,s,<,>,[,]'
  977. return vim.go.whichwrap
  978. end)
  979. matches(
  980. "Invalid option type 'boolean' for 'whichwrap'",
  981. pcall_err(exec_lua, [[vim.opt.whichwrap = true]])
  982. )
  983. matches(
  984. "Invalid option type 'number' for 'whichwrap'",
  985. pcall_err(exec_lua, [[vim.opt.whichwrap = 2]])
  986. )
  987. matches(
  988. "Invalid option type 'function' for 'whichwrap'",
  989. pcall_err(exec_lua, [[vim.opt.whichwrap = function() return "b,s,<,>,[,]" end]])
  990. )
  991. end)
  992. end)
  993. -- isfname=a,b,c,,,d,e,f
  994. it('can handle isfname ,,,', function()
  995. eq_exec_lua({ { ',', 'a', 'b', 'c' }, 'a,b,,,c' }, function()
  996. vim.opt.isfname = 'a,b,,,c'
  997. return { vim.opt.isfname:get(), vim.go.isfname }
  998. end)
  999. end)
  1000. -- isfname=a,b,c,^,,def
  1001. it('can handle isfname ,^,,', function()
  1002. eq_exec_lua({ { '^,', 'a', 'b', 'c' }, 'a,b,^,,c' }, function()
  1003. vim.opt.isfname = 'a,b,^,,c'
  1004. return { vim.opt.isfname:get(), vim.go.isfname }
  1005. end)
  1006. end)
  1007. describe('https://github.com/neovim/neovim/issues/14828', function()
  1008. it('gives empty list when item is empty:array', function()
  1009. eq_exec_lua({}, function()
  1010. vim.cmd('set wildignore=')
  1011. return vim.opt.wildignore:get()
  1012. end)
  1013. eq_exec_lua({}, function()
  1014. vim.opt.wildignore = {}
  1015. return vim.opt.wildignore:get()
  1016. end)
  1017. end)
  1018. it('gives empty list when item is empty:set', function()
  1019. eq_exec_lua({}, function()
  1020. vim.cmd('set formatoptions=')
  1021. return vim.opt.formatoptions:get()
  1022. end)
  1023. eq_exec_lua({}, function()
  1024. vim.opt.formatoptions = {}
  1025. return vim.opt.formatoptions:get()
  1026. end)
  1027. end)
  1028. it('does not append to empty item', function()
  1029. eq_exec_lua({ '*.foo', '*.bar' }, function()
  1030. vim.opt.wildignore = {}
  1031. vim.opt.wildignore:append { '*.foo', '*.bar' }
  1032. return vim.opt.wildignore:get()
  1033. end)
  1034. end)
  1035. it('does not prepend to empty item', function()
  1036. eq_exec_lua({ '*.foo', '*.bar' }, function()
  1037. vim.opt.wildignore = {}
  1038. vim.opt.wildignore:prepend { '*.foo', '*.bar' }
  1039. return vim.opt.wildignore:get()
  1040. end)
  1041. end)
  1042. it('append to empty set', function()
  1043. eq_exec_lua({ t = true }, function()
  1044. vim.opt.formatoptions = {}
  1045. vim.opt.formatoptions:append('t')
  1046. return vim.opt.formatoptions:get()
  1047. end)
  1048. end)
  1049. it('prepend to empty set', function()
  1050. eq_exec_lua({ t = true }, function()
  1051. vim.opt.formatoptions = {}
  1052. vim.opt.formatoptions:prepend('t')
  1053. return vim.opt.formatoptions:get()
  1054. end)
  1055. end)
  1056. end)
  1057. end) -- vim.opt
  1058. describe('vim.opt_local', function()
  1059. it('appends into global value when changing local option value', function()
  1060. eq_exec_lua('foo,bar,baz,qux', function()
  1061. vim.opt.tags = 'foo,bar'
  1062. vim.opt_local.tags:append('baz')
  1063. vim.opt_local.tags:append('qux')
  1064. return vim.bo.tags
  1065. end)
  1066. end)
  1067. end)
  1068. describe('vim.opt_global', function()
  1069. it('gets current global option value', function()
  1070. eq_exec_lua({ 'yes' }, function()
  1071. vim.cmd 'setglobal signcolumn=yes'
  1072. return { vim.opt_global.signcolumn:get() }
  1073. end)
  1074. end)
  1075. end)
  1076. end)
  1077. end)