1" Tests for Lua. 2 3source check.vim 4 5" This test also works without the lua feature. 6func Test_skip_lua() 7 if 0 8 lua print("Not executed") 9 endif 10endfunc 11 12CheckFeature lua 13CheckFeature float 14 15" Depending on the lua version, the error messages are different. 16let [s:major, s:minor, s:patch] = luaeval('vim.lua_version')->split('\.')->map({-> str2nr(v:val)}) 17let s:lua_53_or_later = 0 18let s:lua_543_or_later = 0 19if (s:major == 5 && s:minor >= 3) || s:major > 5 20 let s:lua_53_or_later = 1 21 if (s:major == 5 22 \ && ((s:minor == 4 && s:patch >= 3) || s:minor > 4)) 23 \ || s:major > 5 24 let s:lua_543_or_later = 1 25 endif 26endif 27 28func TearDown() 29 " Run garbage collection after each test to exercise luaV_setref(). 30 call test_garbagecollect_now() 31endfunc 32 33" Check that switching to another buffer does not trigger ml_get error. 34func Test_lua_command_new_no_ml_get_error() 35 new 36 let wincount = winnr('$') 37 call setline(1, ['one', 'two', 'three']) 38 luado vim.command("new") 39 call assert_equal(wincount + 1, winnr('$')) 40 %bwipe! 41endfunc 42 43" Test vim.command() 44func Test_lua_command() 45 new 46 call setline(1, ['one', 'two', 'three']) 47 luado vim.command("1,2d_") 48 call assert_equal(['three'], getline(1, '$')) 49 bwipe! 50endfunc 51 52func Test_lua_luado() 53 new 54 call setline(1, ['one', 'two']) 55 luado return(linenr) 56 call assert_equal(['1', '2'], getline(1, '$')) 57 close! 58 59 " Error cases 60 call assert_fails('luado string.format()', 61 \ "[string \"vim chunk\"]:1: bad argument #1 to 'format' (string expected, got no value)") 62 if s:lua_543_or_later 63 let msg = "[string \"vim chunk\"]:1: global 'func' is not callable (a nil value)" 64 elseif s:lua_53_or_later 65 let msg = "[string \"vim chunk\"]:1: attempt to call a nil value (global 'func')" 66 else 67 let msg = "[string \"vim chunk\"]:1: attempt to call global 'func' (a nil value)" 68 endif 69 call assert_fails('luado func()', msg) 70 call assert_fails('luado error("failed")', "[string \"vim chunk\"]:1: failed") 71endfunc 72 73" Test vim.eval() 74func Test_lua_eval() 75 " lua.eval with a number 76 lua v = vim.eval('123') 77 call assert_equal('number', luaeval('vim.type(v)')) 78 call assert_equal(123, luaeval('v')) 79 80 " lua.eval with a string 81 lua v = vim.eval('"abc"') 82 call assert_equal('string', 'vim.type(v)'->luaeval()) 83 call assert_equal('abc', luaeval('v')) 84 85 " lua.eval with a list 86 lua v = vim.eval("['a']") 87 call assert_equal('list', luaeval('vim.type(v)')) 88 call assert_equal(['a'], luaeval('v')) 89 90 " lua.eval with a dict 91 lua v = vim.eval("{'a':'b'}") 92 call assert_equal('dict', luaeval('vim.type(v)')) 93 call assert_equal({'a':'b'}, luaeval('v')) 94 95 " lua.eval with a blob 96 lua v = vim.eval("0z00112233.deadbeef") 97 call assert_equal('blob', luaeval('vim.type(v)')) 98 call assert_equal(0z00112233.deadbeef, luaeval('v')) 99 100 " lua.eval with a float 101 lua v = vim.eval('3.14') 102 call assert_equal('number', luaeval('vim.type(v)')) 103 call assert_equal(3.14, luaeval('v')) 104 105 " lua.eval with a bool 106 lua v = vim.eval('v:true') 107 call assert_equal('number', luaeval('vim.type(v)')) 108 call assert_equal(1, luaeval('v')) 109 lua v = vim.eval('v:false') 110 call assert_equal('number', luaeval('vim.type(v)')) 111 call assert_equal(0, luaeval('v')) 112 113 " lua.eval with a null 114 lua v = vim.eval('v:null') 115 call assert_equal('nil', luaeval('vim.type(v)')) 116 call assert_equal(v:null, luaeval('v')) 117 118 call assert_fails('lua v = vim.eval(nil)', 119 \ "[string \"vim chunk\"]:1: bad argument #1 to 'eval' (string expected, got nil)") 120 call assert_fails('lua v = vim.eval(true)', 121 \ "[string \"vim chunk\"]:1: bad argument #1 to 'eval' (string expected, got boolean)") 122 call assert_fails('lua v = vim.eval({})', 123 \ "[string \"vim chunk\"]:1: bad argument #1 to 'eval' (string expected, got table)") 124 call assert_fails('lua v = vim.eval(print)', 125 \ "[string \"vim chunk\"]:1: bad argument #1 to 'eval' (string expected, got function)") 126 call assert_fails('lua v = vim.eval(vim.buffer())', 127 \ "[string \"vim chunk\"]:1: bad argument #1 to 'eval' (string expected, got userdata)") 128 129 lua v = nil 130endfunc 131 132" Test luaeval() with lambda 133func Test_luaeval_with_lambda() 134 lua function hello_luaeval_lambda(a, cb) return a .. cb() end 135 call assert_equal('helloworld', 136 \ luaeval('hello_luaeval_lambda(_A[1], _A[2])', 137 \ ['hello', {->'world'}])) 138 lua hello_luaeval_lambda = nil 139endfunc 140 141" Test vim.window() 142func Test_lua_window() 143 e Xfoo2 144 new Xfoo1 145 146 " Window 1 (top window) contains Xfoo1 147 " Window 2 (bottom window) contains Xfoo2 148 call assert_equal('Xfoo1', luaeval('vim.window(1):buffer().name')) 149 call assert_equal('Xfoo2', luaeval('vim.window(2):buffer().name')) 150 151 " Window 3 does not exist so vim.window(3) should return nil 152 call assert_equal('nil', luaeval('tostring(vim.window(3))')) 153 154 if s:lua_543_or_later 155 let msg = "[string \"luaeval\"]:1: field 'xyz' is not callable (a nil value)" 156 elseif s:lua_53_or_later 157 let msg = "[string \"luaeval\"]:1: attempt to call a nil value (field 'xyz')" 158 else 159 let msg = "[string \"luaeval\"]:1: attempt to call field 'xyz' (a nil value)" 160 endif 161 call assert_fails("let n = luaeval('vim.window().xyz()')", msg) 162 call assert_fails('lua vim.window().xyz = 1', 163 \ "[string \"vim chunk\"]:1: invalid window property: `xyz'") 164 165 %bwipe! 166endfunc 167 168" Test vim.window().height 169func Test_lua_window_height() 170 new 171 lua vim.window().height = 2 172 call assert_equal(2, winheight(0)) 173 lua vim.window().height = vim.window().height + 1 174 call assert_equal(3, winheight(0)) 175 bwipe! 176endfunc 177 178" Test vim.window().width 179func Test_lua_window_width() 180 vert new 181 lua vim.window().width = 2 182 call assert_equal(2, winwidth(0)) 183 lua vim.window().width = vim.window().width + 1 184 call assert_equal(3, winwidth(0)) 185 bwipe! 186endfunc 187 188" Test vim.window().line and vim.window.col 189func Test_lua_window_line_col() 190 new 191 call setline(1, ['line1', 'line2', 'line3']) 192 lua vim.window().line = 2 193 lua vim.window().col = 4 194 call assert_equal([0, 2, 4, 0], getpos('.')) 195 lua vim.window().line = vim.window().line + 1 196 lua vim.window().col = vim.window().col - 1 197 call assert_equal([0, 3, 3, 0], getpos('.')) 198 199 call assert_fails('lua vim.window().line = 10', 200 \ '[string "vim chunk"]:1: line out of range') 201 bwipe! 202endfunc 203 204" Test vim.call 205func Test_lua_call() 206 call assert_equal(has('lua'), luaeval('vim.call("has", "lua")')) 207 call assert_equal(printf("Hello %s", "vim"), luaeval('vim.call("printf", "Hello %s", "vim")')) 208 209 " Error cases 210 call assert_fails("call luaeval('vim.call(\"min\", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21)')", 211 \ s:lua_53_or_later 212 \ ? '[string "luaeval"]:1: Function called with too many arguments' 213 \ : 'Function called with too many arguments') 214 lua co = coroutine.create(function () print("hi") end) 215 call assert_fails("call luaeval('vim.call(\"type\", co)')", 216 \ s:lua_53_or_later 217 \ ? '[string "luaeval"]:1: lua: cannot convert value' 218 \ : 'lua: cannot convert value') 219 lua co = nil 220 call assert_fails("call luaeval('vim.call(\"abc\")')", 221 \ ['E117:', s:lua_53_or_later ? '\[string "luaeval"]:1: lua: call_vim_function failed' 222 \ : 'lua: call_vim_function failed']) 223endfunc 224 225" Test vim.fn.* 226func Test_lua_fn() 227 call assert_equal(has('lua'), luaeval('vim.fn.has("lua")')) 228 call assert_equal(printf("Hello %s", "vim"), luaeval('vim.fn.printf("Hello %s", "vim")')) 229endfunc 230 231" Test setting the current window 232func Test_lua_window_set_current() 233 new Xfoo1 234 lua w1 = vim.window() 235 new Xfoo2 236 lua w2 = vim.window() 237 238 call assert_equal('Xfoo2', bufname('%')) 239 lua w1() 240 call assert_equal('Xfoo1', bufname('%')) 241 lua w2() 242 call assert_equal('Xfoo2', bufname('%')) 243 244 lua w1, w2 = nil 245 %bwipe! 246endfunc 247 248" Test vim.window().buffer 249func Test_lua_window_buffer() 250 new Xfoo1 251 lua w1 = vim.window() 252 lua b1 = w1.buffer() 253 new Xfoo2 254 lua w2 = vim.window() 255 lua b2 = w2.buffer() 256 257 lua b1() 258 call assert_equal('Xfoo1', bufname('%')) 259 lua b2() 260 call assert_equal('Xfoo2', bufname('%')) 261 262 lua b1, b2, w1, w2 = nil 263 %bwipe! 264endfunc 265 266" Test vim.window():previous() and vim.window():next() 267func Test_lua_window_next_previous() 268 new Xfoo1 269 new Xfoo2 270 new Xfoo3 271 wincmd j 272 273 call assert_equal('Xfoo2', luaeval('vim.window().buffer().name')) 274 call assert_equal('Xfoo1', luaeval('vim.window():next():buffer().name')) 275 call assert_equal('Xfoo3', luaeval('vim.window():previous():buffer().name')) 276 277 %bwipe! 278endfunc 279 280" Test vim.window():isvalid() 281func Test_lua_window_isvalid() 282 new Xfoo 283 lua w = vim.window() 284 call assert_true(luaeval('w:isvalid()')) 285 286 " FIXME: how to test the case when isvalid() returns v:false? 287 " isvalid() gives errors when the window is deleted. Is it a bug? 288 289 lua w = nil 290 bwipe! 291endfunc 292 293" Test vim.buffer() with and without argument 294func Test_lua_buffer() 295 new Xfoo1 296 let bn1 = bufnr('%') 297 new Xfoo2 298 let bn2 = bufnr('%') 299 300 " Test vim.buffer() without argument. 301 call assert_equal('Xfoo2', luaeval("vim.buffer().name")) 302 303 " Test vim.buffer() with string argument. 304 call assert_equal('Xfoo1', luaeval("vim.buffer('Xfoo1').name")) 305 call assert_equal('Xfoo2', luaeval("vim.buffer('Xfoo2').name")) 306 307 " Test vim.buffer() with integer argument. 308 call assert_equal('Xfoo1', luaeval("vim.buffer(" . bn1 . ").name")) 309 call assert_equal('Xfoo2', luaeval("vim.buffer(" . bn2 . ").name")) 310 311 lua bn1, bn2 = nil 312 %bwipe! 313endfunc 314 315" Test vim.buffer().name and vim.buffer().fname 316func Test_lua_buffer_name() 317 new 318 call assert_equal('', luaeval('vim.buffer().name')) 319 call assert_equal('', luaeval('vim.buffer().fname')) 320 bwipe! 321 322 new Xfoo 323 call assert_equal('Xfoo', luaeval('vim.buffer().name')) 324 call assert_equal(expand('%:p'), luaeval('vim.buffer().fname')) 325 bwipe! 326endfunc 327 328" Test vim.buffer().number 329func Test_lua_buffer_number() 330 " All numbers in Lua are floating points number (no integers). 331 call assert_equal(bufnr('%'), float2nr(luaeval('vim.buffer().number'))) 332endfunc 333 334" Test inserting lines in buffer. 335func Test_lua_buffer_insert() 336 new 337 lua vim.buffer()[1] = '3' 338 lua vim.buffer():insert('1', 0) 339 lua vim.buffer():insert('2', 1) 340 lua vim.buffer():insert('4', 10) 341 342 call assert_equal(['1', '2', '3', '4'], getline(1, '$')) 343 call assert_equal('4', luaeval('vim.buffer()[4]')) 344 call assert_equal(v:null, luaeval('vim.buffer()[5]')) 345 call assert_equal(v:null, luaeval('vim.buffer()[{}]')) 346 if s:lua_543_or_later 347 let msg = "[string \"vim chunk\"]:1: method 'xyz' is not callable (a nil value)" 348 elseif s:lua_53_or_later 349 let msg = "[string \"vim chunk\"]:1: attempt to call a nil value (method 'xyz')" 350 else 351 let msg = "[string \"vim chunk\"]:1: attempt to call method 'xyz' (a nil value)" 352 endif 353 call assert_fails('lua vim.buffer():xyz()', msg) 354 call assert_fails('lua vim.buffer()[1] = {}', 355 \ '[string "vim chunk"]:1: wrong argument to change') 356 bwipe! 357endfunc 358 359" Test deleting line in buffer 360func Test_lua_buffer_delete() 361 new 362 call setline(1, ['1', '2', '3']) 363 call cursor(3, 1) 364 lua vim.buffer()[2] = nil 365 call assert_equal(['1', '3'], getline(1, '$')) 366 367 call assert_fails('lua vim.buffer()[3] = nil', 368 \ '[string "vim chunk"]:1: invalid line number') 369 bwipe! 370endfunc 371 372" Test #vim.buffer() i.e. number of lines in buffer 373func Test_lua_buffer_number_lines() 374 new 375 call setline(1, ['a', 'b', 'c']) 376 call assert_equal(3, luaeval('#vim.buffer()')) 377 bwipe! 378endfunc 379 380" Test vim.buffer():next() and vim.buffer():previous() 381" Note that these functions get the next or previous buffers 382" but do not switch buffer. 383func Test_lua_buffer_next_previous() 384 new Xfoo1 385 new Xfoo2 386 new Xfoo3 387 b Xfoo2 388 389 lua bn = vim.buffer():next() 390 lua bp = vim.buffer():previous() 391 392 call assert_equal('Xfoo2', luaeval('vim.buffer().name')) 393 call assert_equal('Xfoo1', luaeval('bp.name')) 394 call assert_equal('Xfoo3', luaeval('bn.name')) 395 396 call assert_equal('Xfoo2', bufname('%')) 397 398 lua bn() 399 call assert_equal('Xfoo3', luaeval('vim.buffer().name')) 400 call assert_equal('Xfoo3', bufname('%')) 401 402 lua bp() 403 call assert_equal('Xfoo1', luaeval('vim.buffer().name')) 404 call assert_equal('Xfoo1', bufname('%')) 405 406 lua bn, bp = nil 407 %bwipe! 408endfunc 409 410" Test vim.buffer():isvalid() 411func Test_lua_buffer_isvalid() 412 new Xfoo 413 lua b = vim.buffer() 414 call assert_true(luaeval('b:isvalid()')) 415 416 " FIXME: how to test the case when isvalid() returns v:false? 417 " isvalid() gives errors when the buffer is wiped. Is it a bug? 418 419 lua b = nil 420 bwipe! 421endfunc 422 423func Test_lua_list() 424 call assert_equal([], luaeval('vim.list()')) 425 426 let l = [] 427 lua l = vim.eval('l') 428 lua l:add(123) 429 lua l:add('abc') 430 lua l:add(true) 431 lua l:add(false) 432 lua l:add(nil) 433 lua l:add(vim.eval("[1, 2, 3]")) 434 lua l:add(vim.eval("{'a':1, 'b':2, 'c':3}")) 435 call assert_equal([123, 'abc', v:true, v:false, v:null, [1, 2, 3], {'a': 1, 'b': 2, 'c': 3}], l) 436 call assert_equal(7, luaeval('#l')) 437 call assert_match('^list: \%(0x\)\?\x\+$', luaeval('tostring(l)')) 438 439 lua l[1] = 124 440 lua l[6] = nil 441 lua l:insert('first') 442 lua l:insert('xx', 3) 443 call assert_fails('lua l:insert("xx", -20)', 444 \ '[string "vim chunk"]:1: invalid position') 445 call assert_equal(['first', 124, 'abc', 'xx', v:true, v:false, v:null, {'a': 1, 'b': 2, 'c': 3}], l) 446 447 lockvar 1 l 448 call assert_fails('lua l:add("x")', '[string "vim chunk"]:1: list is locked') 449 call assert_fails('lua l:insert(2)', '[string "vim chunk"]:1: list is locked') 450 call assert_fails('lua l[9] = 1', '[string "vim chunk"]:1: list is locked') 451 452 unlockvar l 453 let l = [1, 2] 454 lua ll = vim.eval('l') 455 let x = luaeval("ll[3]") 456 call assert_equal(v:null, x) 457 if s:lua_543_or_later 458 let msg = "[string \"luaeval\"]:1: method 'xyz' is not callable (a nil value)" 459 elseif s:lua_53_or_later 460 let msg = "[string \"luaeval\"]:1: attempt to call a nil value (method 'xyz')" 461 else 462 let msg = "[string \"luaeval\"]:1: attempt to call method 'xyz' (a nil value)" 463 endif 464 call assert_fails('let x = luaeval("ll:xyz(3)")', msg) 465 let y = luaeval("ll[{}]") 466 call assert_equal(v:null, y) 467 468 lua l = nil 469endfunc 470 471func Test_lua_list_table() 472 " See :help lua-vim 473 " Non-numeric keys should not be used to initialize the list 474 " so say = 'hi' should be ignored. 475 lua t = {3.14, 'hello', false, true, say = 'hi'} 476 call assert_equal([3.14, 'hello', v:false, v:true], luaeval('vim.list(t)')) 477 lua t = nil 478 479 call assert_fails('lua vim.list(1)', '[string "vim chunk"]:1: table expected, got number') 480 call assert_fails('lua vim.list("x")', '[string "vim chunk"]:1: table expected, got string') 481 call assert_fails('lua vim.list(print)', '[string "vim chunk"]:1: table expected, got function') 482 call assert_fails('lua vim.list(true)', '[string "vim chunk"]:1: table expected, got boolean') 483endfunc 484 485func Test_lua_list_table_insert_remove() 486 if !s:lua_53_or_later 487 throw 'Skipped: Lua version < 5.3' 488 endif 489 490 let l = [1, 2] 491 lua t = vim.eval('l') 492 lua table.insert(t, 10) 493 lua t[#t + 1] = 20 494 lua table.insert(t, 2, 30) 495 call assert_equal(l, [1, 30, 2, 10, 20]) 496 lua table.remove(t, 2) 497 call assert_equal(l, [1, 2, 10, 20]) 498 lua t[3] = nil 499 call assert_equal(l, [1, 2, 20]) 500 lua removed_value = table.remove(t, 3) 501 call assert_equal(luaeval('removed_value'), 20) 502 lua t = nil 503 lua removed_value = nil 504 unlet l 505endfunc 506 507" Test l() i.e. iterator on list 508func Test_lua_list_iter() 509 lua l = vim.list():add('foo'):add('bar') 510 lua str = '' 511 lua for v in l() do str = str .. v end 512 call assert_equal('foobar', luaeval('str')) 513 514 lua str, l = nil 515endfunc 516 517func Test_lua_recursive_list() 518 lua l = vim.list():add(1):add(2) 519 lua l = l:add(l) 520 521 call assert_equal(1, luaeval('l[1]')) 522 call assert_equal(2, luaeval('l[2]')) 523 524 call assert_equal(1, luaeval('l[3][1]')) 525 call assert_equal(2, luaeval('l[3][2]')) 526 527 call assert_equal(1, luaeval('l[3][3][1]')) 528 call assert_equal(2, luaeval('l[3][3][2]')) 529 530 call assert_equal('[1, 2, [...]]', string(luaeval('l'))) 531 532 call assert_match('^list: \%(0x\)\?\x\+$', luaeval('tostring(l)')) 533 call assert_equal(luaeval('tostring(l)'), luaeval('tostring(l[3])')) 534 535 call assert_equal(luaeval('l'), luaeval('l[3]')) 536 call assert_equal(luaeval('l'), luaeval('l[3][3]')) 537 538 lua l = nil 539endfunc 540 541func Test_lua_dict() 542 call assert_equal({}, luaeval('vim.dict()')) 543 544 let d = {} 545 lua d = vim.eval('d') 546 lua d[0] = 123 547 lua d[1] = "abc" 548 lua d[2] = true 549 lua d[3] = false 550 lua d[4] = vim.eval("[1, 2, 3]") 551 lua d[5] = vim.eval("{'a':1, 'b':2, 'c':3}") 552 call assert_equal({'0':123, '1':'abc', '2':v:true, '3':v:false, '4': [1, 2, 3], '5': {'a':1, 'b':2, 'c':3}}, d) 553 call assert_equal(6, luaeval('#d')) 554 call assert_match('^dict: \%(0x\)\?\x\+$', luaeval('tostring(d)')) 555 556 call assert_equal('abc', luaeval('d[1]')) 557 call assert_equal(v:null, luaeval('d[22]')) 558 559 lua d[0] = 124 560 lua d[4] = nil 561 call assert_equal({'0':124, '1':'abc', '2':v:true, '3':v:false, '5': {'a':1, 'b':2, 'c':3}}, d) 562 563 lockvar 1 d 564 call assert_fails('lua d[6] = 1', '[string "vim chunk"]:1: dict is locked') 565 unlockvar d 566 567 " Error case 568 lua d = {} 569 lua d[''] = 10 570 call assert_fails("let t = luaeval('vim.dict(d)')", 571 \ s:lua_53_or_later 572 \ ? '[string "luaeval"]:1: table has empty key' 573 \ : 'table has empty key') 574 let d = {} 575 lua x = vim.eval('d') 576 call assert_fails("lua x[''] = 10", '[string "vim chunk"]:1: empty key') 577 lua x['a'] = nil 578 call assert_equal({}, d) 579 580 " cannot assign funcrefs in the global scope 581 lua x = vim.eval('g:') 582 call assert_fails("lua x['min'] = vim.funcref('max')", 583 \ '[string "vim chunk"]:1: cannot assign funcref to builtin scope') 584 585 lua d = nil 586endfunc 587 588func Test_lua_dict_table() 589 lua t = {key1 = 'x', key2 = 3.14, key3 = true, key4 = false} 590 call assert_equal({'key1': 'x', 'key2': 3.14, 'key3': v:true, 'key4': v:false}, 591 \ luaeval('vim.dict(t)')) 592 593 " Same example as in :help lua-vim. 594 lua t = {math.pi, false, say = 'hi'} 595 " FIXME: commented out as it currently does not work as documented: 596 " Expected {'say': 'hi'} 597 " but got {'1': 3.141593, '2': v:false, 'say': 'hi'} 598 " Is the documentation or the code wrong? 599 "call assert_equal({'say' : 'hi'}, luaeval('vim.dict(t)')) 600 lua t = nil 601 602 call assert_fails('lua vim.dict(1)', '[string "vim chunk"]:1: table expected, got number') 603 call assert_fails('lua vim.dict("x")', '[string "vim chunk"]:1: table expected, got string') 604 call assert_fails('lua vim.dict(print)', '[string "vim chunk"]:1: table expected, got function') 605 call assert_fails('lua vim.dict(true)', '[string "vim chunk"]:1: table expected, got boolean') 606endfunc 607 608" Test d() i.e. iterator on dictionary 609func Test_lua_dict_iter() 610 let d = {'a': 1, 'b':2} 611 lua d = vim.eval('d') 612 lua str = '' 613 lua for k,v in d() do str = str .. k ..':' .. v .. ',' end 614 call assert_equal('a:1,b:2,', luaeval('str')) 615 616 lua str, d = nil 617endfunc 618 619func Test_lua_blob() 620 call assert_equal(0z, luaeval('vim.blob("")')) 621 call assert_equal(0z31326162, luaeval('vim.blob("12ab")')) 622 call assert_equal(0z00010203, luaeval('vim.blob("\x00\x01\x02\x03")')) 623 call assert_equal(0z8081FEFF, luaeval('vim.blob("\x80\x81\xfe\xff")')) 624 625 lua b = vim.blob("\x00\x00\x00\x00") 626 call assert_equal(0z00000000, luaeval('b')) 627 call assert_equal(4, luaeval('#b')) 628 lua b[0], b[1], b[2], b[3] = 1, 32, 256, 0xff 629 call assert_equal(0z012000ff, luaeval('b')) 630 lua b[4] = string.byte("z", 1) 631 call assert_equal(0z012000ff.7a, luaeval('b')) 632 call assert_equal(5, luaeval('#b')) 633 call assert_fails('lua b[#b+1] = 0x80', '[string "vim chunk"]:1: index out of range') 634 lua b:add("12ab") 635 call assert_equal(0z012000ff.7a313261.62, luaeval('b')) 636 call assert_equal(9, luaeval('#b')) 637 call assert_fails('lua b:add(nil)', '[string "vim chunk"]:1: string expected, got nil') 638 call assert_fails('lua b:add(true)', '[string "vim chunk"]:1: string expected, got boolean') 639 call assert_fails('lua b:add({})', '[string "vim chunk"]:1: string expected, got table') 640 lua b = nil 641 642 let b = 0z0102 643 lua lb = vim.eval('b') 644 let n = luaeval('lb[1]') 645 call assert_equal(2, n) 646 let n = luaeval('lb[6]') 647 call assert_equal(v:null, n) 648 if s:lua_543_or_later 649 let msg = "[string \"luaeval\"]:1: method 'xyz' is not callable (a nil value)" 650 elseif s:lua_53_or_later 651 let msg = "[string \"luaeval\"]:1: attempt to call a nil value (method 'xyz')" 652 else 653 let msg = "[string \"luaeval\"]:1: attempt to call method 'xyz' (a nil value)" 654 endif 655 call assert_fails('let x = luaeval("lb:xyz(3)")', msg) 656 let y = luaeval("lb[{}]") 657 call assert_equal(v:null, y) 658 659 lockvar b 660 call assert_fails('lua lb[1] = 2', '[string "vim chunk"]:1: blob is locked') 661 call assert_fails('lua lb:add("12")', '[string "vim chunk"]:1: blob is locked') 662 663 " Error cases 664 lua t = {} 665 call assert_fails('lua b = vim.blob(t)', 666 \ '[string "vim chunk"]:1: string expected, got table') 667endfunc 668 669func Test_lua_funcref() 670 function I(x) 671 return a:x 672 endfunction 673 let R = function('I') 674 lua i1 = vim.funcref"I" 675 lua i2 = vim.eval"R" 676 lua msg = "funcref|test|" .. (#i2(i1) == #i1(i2) and "OK" or "FAIL") 677 lua msg = vim.funcref"tr"(msg, "|", " ") 678 call assert_equal("funcref test OK", luaeval('msg')) 679 680 " Error cases 681 call assert_fails('lua f1 = vim.funcref("")', 682 \ '[string "vim chunk"]:1: invalid function name: ') 683 call assert_fails('lua f1 = vim.funcref("10")', 684 \ '[string "vim chunk"]:1: invalid function name: 10') 685 let fname = test_null_string() 686 call assert_fails('lua f1 = vim.funcref(fname)', 687 \ "[string \"vim chunk\"]:1: bad argument #1 to 'funcref' (string expected, got nil)") 688 call assert_fails('lua vim.funcref("abc")()', 689 \ ['E117:', '\[string "vim chunk"]:1: cannot call funcref']) 690 691 " dict funcref 692 function Mylen() dict 693 return len(self.data) 694 endfunction 695 let l = [0, 1, 2, 3] 696 let mydict = {'data': l} 697 lua d = vim.eval"mydict" 698 lua d.len = vim.funcref"Mylen" -- assign d as 'self' 699 lua res = (d.len() == vim.funcref"len"(vim.eval"l")) and "OK" or "FAIL" 700 call assert_equal("OK", luaeval('res')) 701 call assert_equal(function('Mylen', {'data': l, 'len': function('Mylen')}), mydict.len) 702 703 lua i1, i2, msg, d, res = nil 704endfunc 705 706" Test vim.type() 707func Test_lua_type() 708 " The following values are identical to Lua's type function. 709 call assert_equal('string', luaeval('vim.type("foo")')) 710 call assert_equal('number', luaeval('vim.type(1)')) 711 call assert_equal('number', luaeval('vim.type(1.2)')) 712 call assert_equal('function', luaeval('vim.type(print)')) 713 call assert_equal('table', luaeval('vim.type({})')) 714 call assert_equal('boolean', luaeval('vim.type(true)')) 715 call assert_equal('boolean', luaeval('vim.type(false)')) 716 call assert_equal('nil', luaeval('vim.type(nil)')) 717 718 " The following values are specific to Vim. 719 call assert_equal('window', luaeval('vim.type(vim.window())')) 720 call assert_equal('buffer', luaeval('vim.type(vim.buffer())')) 721 call assert_equal('list', luaeval('vim.type(vim.list())')) 722 call assert_equal('dict', luaeval('vim.type(vim.dict())')) 723 call assert_equal('funcref', luaeval('vim.type(vim.funcref("Test_type"))')) 724endfunc 725 726" Test vim.open() 727func Test_lua_open() 728 call assert_notmatch('XOpen', execute('ls')) 729 730 " Open a buffer XOpen1, but do not jump to it. 731 lua b = vim.open('XOpen1') 732 call assert_equal('XOpen1', luaeval('b.name')) 733 call assert_equal('', bufname('%')) 734 735 call assert_match('XOpen1', execute('ls')) 736 call assert_notequal('XOpen2', bufname('%')) 737 738 " Open a buffer XOpen2 and jump to it. 739 lua b = vim.open('XOpen2')() 740 call assert_equal('XOpen2', luaeval('b.name')) 741 call assert_equal('XOpen2', bufname('%')) 742 743 lua b = nil 744 %bwipe! 745endfunc 746 747func Test_update_package_paths() 748 set runtimepath+=./testluaplugin 749 call assert_equal("hello from lua", luaeval("require('testluaplugin').hello()")) 750endfunc 751 752func Vim_func_call_lua_callback(Concat, Cb) 753 let l:message = a:Concat("hello", "vim") 754 call a:Cb(l:message) 755endfunc 756 757func Test_pass_lua_callback_to_vim_from_lua() 758 lua pass_lua_callback_to_vim_from_lua_result = "" 759 call assert_equal("", luaeval("pass_lua_callback_to_vim_from_lua_result")) 760 lua <<EOF 761 vim.funcref('Vim_func_call_lua_callback')( 762 function(greeting, message) 763 return greeting .. " " .. message 764 end, 765 function(message) 766 pass_lua_callback_to_vim_from_lua_result = message 767 end) 768EOF 769 call assert_equal("hello vim", luaeval("pass_lua_callback_to_vim_from_lua_result")) 770endfunc 771 772func Vim_func_call_metatable_lua_callback(Greet) 773 return a:Greet("world") 774endfunc 775 776func Test_pass_lua_metatable_callback_to_vim_from_lua() 777 let result = luaeval("vim.funcref('Vim_func_call_metatable_lua_callback')(setmetatable({ space = ' '}, { __call = function(tbl, msg) return 'hello' .. tbl.space .. msg end }) )") 778 call assert_equal("hello world", result) 779endfunc 780 781" Test vim.line() 782func Test_lua_line() 783 new 784 call setline(1, ['first line', 'second line']) 785 1 786 call assert_equal('first line', luaeval('vim.line()')) 787 2 788 call assert_equal('second line', luaeval('vim.line()')) 789 bwipe! 790endfunc 791 792" Test vim.beep() 793func Test_lua_beep() 794 call assert_beeps('lua vim.beep()') 795endfunc 796 797" Test errors in luaeval() 798func Test_luaeval_error() 799 " Compile error 800 call assert_fails("call luaeval('-nil')", 801 \ '[string "luaeval"]:1: attempt to perform arithmetic on a nil value') 802 call assert_fails("call luaeval(']')", 803 \ "[string \"luaeval\"]:1: unexpected symbol near ']'") 804 lua co = coroutine.create(function () print("hi") end) 805 call assert_fails('let i = luaeval("co")', 'luaeval: cannot convert value') 806 lua co = nil 807 call assert_fails('let m = luaeval("{}")', 'luaeval: cannot convert value') 808endfunc 809 810" Test :luafile foo.lua 811func Test_luafile() 812 call delete('Xlua_file') 813 call writefile(["str = 'hello'", "num = 123" ], 'Xlua_file') 814 call setfperm('Xlua_file', 'r-xr-xr-x') 815 816 luafile Xlua_file 817 call assert_equal('hello', luaeval('str')) 818 call assert_equal(123, luaeval('num')) 819 820 lua str, num = nil 821 call delete('Xlua_file') 822endfunc 823 824" Test :luafile % 825func Test_luafile_percent() 826 new Xlua_file 827 append 828 str, num = 'foo', 321.0 829 print(string.format('str=%s, num=%d', str, num)) 830. 831 w! 832 luafile % 833 let msg = split(execute('message'), "\n")[-1] 834 call assert_equal('str=foo, num=321', msg) 835 836 lua str, num = nil 837 call delete('Xlua_file') 838 bwipe! 839endfunc 840 841" Test :luafile with syntax error 842func Test_luafile_error() 843 new Xlua_file 844 call writefile(['nil = 0' ], 'Xlua_file') 845 call setfperm('Xlua_file', 'r-xr-xr-x') 846 847 call assert_fails('luafile Xlua_file', "Xlua_file:1: unexpected symbol near 'nil'") 848 849 call delete('Xlua_file') 850 bwipe! 851endfunc 852 853" Test :luafile printing a long string 854func Test_luafile_print() 855 new Xlua_file 856 let lines =<< trim END 857 local data = '' 858 for i = 1, 130 do 859 data = data .. 'xxxxx asd as as dad sad sad xz cxz czxcxzczxc ad ad asd asd asd asd asd' 860 end 861 print(data) 862 END 863 call setline(1, lines) 864 w 865 luafile % 866 867 call delete('Xlua_file') 868 bwipe! 869endfunc 870 871" Test for dealing with strings containing newlines and null character 872func Test_lua_string_with_newline() 873 let x = execute('lua print("Hello\nWorld", 2)') 874 call assert_equal("\nHello\nWorld 2", x) 875 new 876 lua k = vim.buffer(vim.eval('bufnr()')) 877 lua k:insert("Hello\0World", 0) 878 call assert_equal(["Hello\nWorld", ''], getline(1, '$')) 879 close! 880endfunc 881 882func Test_lua_set_cursor() 883 " Check that setting the cursor position works. 884 new 885 call setline(1, ['first line', 'second line']) 886 normal gg 887 lua << trim EOF 888 w = vim.window() 889 w.line = 1 890 w.col = 5 891 EOF 892 call assert_equal([1, 5], [line('.'), col('.')]) 893 894 " Check that movement after setting cursor position keeps current column. 895 normal j 896 call assert_equal([2, 5], [line('.'), col('.')]) 897endfunc 898 899" Test for various heredoc syntax 900func Test_lua_heredoc() 901 lua << END 902vim.command('let s = "A"') 903END 904 lua << 905vim.command('let s ..= "B"') 906. 907 lua << trim END 908 vim.command('let s ..= "C"') 909 END 910 lua << trim 911 vim.command('let s ..= "D"') 912 . 913 lua << trim eof 914 vim.command('let s ..= "E"') 915 eof 916 call assert_equal('ABCDE', s) 917endfunc 918 919" Test for adding, accessing and removing global variables using the vim.g 920" Lua table 921func Test_lua_global_var_table() 922 " Access global variables with different types of values 923 let g:Var1 = 10 924 let g:Var2 = 'Hello' 925 let g:Var3 = ['a', 'b'] 926 let g:Var4 = #{x: 'edit', y: 'run'} 927 let g:Var5 = function('min') 928 call assert_equal(10, luaeval('vim.g.Var1')) 929 call assert_equal('Hello', luaeval('vim.g.Var2')) 930 call assert_equal(['a', 'b'], luaeval('vim.g.Var3')) 931 call assert_equal(#{x: 'edit', y: 'run'}, luaeval('vim.g.Var4')) 932 call assert_equal(2, luaeval('vim.g.Var5')([5, 9, 2])) 933 934 " Access list of dictionaries and dictionary of lists 935 let g:Var1 = [#{a: 10}, #{b: 20}] 936 let g:Var2 = #{p: [5, 6], q: [1.1, 2.2]} 937 call assert_equal([#{a: 10}, #{b: 20}], luaeval('vim.g.Var1')) 938 call assert_equal(#{p: [5, 6], q: [1.1, 2.2]}, luaeval('vim.g.Var2')) 939 940 " Create new global variables with different types of values 941 unlet g:Var1 g:Var2 g:Var3 g:Var4 g:Var5 942 lua << trim END 943 vim.g.Var1 = 34 944 vim.g.Var2 = 'World' 945 vim.g.Var3 = vim.list({'#', '$'}) 946 vim.g.Var4 = vim.dict({model='honda', year=2020}) 947 vim.g.Var5 = vim.funcref('max') 948 END 949 call assert_equal(34, g:Var1) 950 call assert_equal('World', g:Var2) 951 call assert_equal(['#', '$'], g:Var3) 952 call assert_equal(#{model: 'honda', year: 2020}, g:Var4) 953 call assert_equal(10, g:Var5([5, 10, 9])) 954 955 " Create list of dictionaries and dictionary of lists 956 unlet g:Var1 g:Var2 957 lua << trim END 958 vim.g.Var1 = vim.list({vim.dict({a=10}), vim.dict({b=20})}) 959 vim.g.Var2 = vim.dict({p=vim.list({5, 6}), q=vim.list({1.1, 2.2})}) 960 END 961 call assert_equal([#{a: 10}, #{b: 20}], luaeval('vim.g.Var1')) 962 call assert_equal(#{p: [5, 6], q: [1.1, 2.2]}, luaeval('vim.g.Var2')) 963 964 " Modify a global variable with a list value or a dictionary value 965 let g:Var1 = [10, 20] 966 let g:Var2 = #{one: 'mercury', two: 'mars'} 967 lua << trim END 968 vim.g.Var1[2] = Nil 969 vim.g.Var1[3] = 15 970 vim.g.Var2['two'] = Nil 971 vim.g.Var2['three'] = 'earth' 972 END 973 call assert_equal([10, 15], g:Var1) 974 call assert_equal(#{one: 'mercury', three: 'earth'}, g:Var2) 975 976 " Remove global variables with different types of values 977 let g:Var1 = 10 978 let g:Var2 = 'Hello' 979 let g:Var3 = ['a', 'b'] 980 let g:Var4 = #{x: 'edit', y: 'run'} 981 let g:Var5 = function('min') 982 lua << trim END 983 vim.g.Var1 = Nil 984 vim.g.Var2 = Nil 985 vim.g.Var3 = Nil 986 vim.g.Var4 = Nil 987 vim.g.Var5 = Nil 988 END 989 call assert_false(exists('g:Var1')) 990 call assert_false(exists('g:Var2')) 991 call assert_false(exists('g:Var3')) 992 call assert_false(exists('g:Var4')) 993 call assert_false(exists('g:Var5')) 994 995 " Try to modify and remove a locked global variable 996 let g:Var1 = 10 997 lockvar g:Var1 998 call assert_fails('lua vim.g.Var1 = 20', 'variable is locked') 999 call assert_fails('lua vim.g.Var1 = Nil', 'variable is locked') 1000 unlockvar g:Var1 1001 let g:Var2 = [7, 14] 1002 lockvar 0 g:Var2 1003 lua vim.g.Var2[2] = Nil 1004 lua vim.g.Var2[3] = 21 1005 call assert_fails('lua vim.g.Var2 = Nil', 'variable is locked') 1006 call assert_equal([7, 21], g:Var2) 1007 lockvar 1 g:Var2 1008 call assert_fails('lua vim.g.Var2[2] = Nil', 'list is locked') 1009 call assert_fails('lua vim.g.Var2[3] = 21', 'list is locked') 1010 unlockvar g:Var2 1011 1012 let g:TestFunc = function('len') 1013 call assert_fails('lua vim.g.func = vim.g.TestFunc', ['E704:', 'Couldn''t add to dictionary']) 1014 unlet g:TestFunc 1015 1016 " Attempt to access a non-existing global variable 1017 call assert_equal(v:null, luaeval('vim.g.NonExistingVar')) 1018 lua vim.g.NonExisting = Nil 1019 1020 unlet! g:Var1 g:Var2 g:Var3 g:Var4 g:Var5 1021endfunc 1022 1023" Test for accessing and modifying predefined vim variables using the vim.v 1024" Lua table 1025func Test_lua_predefined_var_table() 1026 call assert_equal(v:progpath, luaeval('vim.v.progpath')) 1027 let v:errmsg = 'SomeError' 1028 call assert_equal('SomeError', luaeval('vim.v.errmsg')) 1029 lua vim.v.errmsg = 'OtherError' 1030 call assert_equal('OtherError', v:errmsg) 1031 call assert_fails('lua vim.v.errmsg = Nil', 'variable is fixed') 1032 let v:oldfiles = ['one', 'two'] 1033 call assert_equal(['one', 'two'], luaeval('vim.v.oldfiles')) 1034 lua vim.v.oldfiles = vim.list({}) 1035 call assert_equal([], v:oldfiles) 1036 call assert_equal(v:null, luaeval('vim.v.null')) 1037 call assert_fails('lua vim.v.argv[1] = Nil', 'list is locked') 1038 call assert_fails('lua vim.v.newvar = 1', 'Dictionary is locked') 1039endfunc 1040 1041" Test for adding, accessing and modifying window-local variables using the 1042" vim.w Lua table 1043func Test_lua_window_var_table() 1044 " Access window variables with different types of values 1045 new 1046 let w:wvar1 = 10 1047 let w:wvar2 = 'edit' 1048 let w:wvar3 = 3.14 1049 let w:wvar4 = 0zdeadbeef 1050 let w:wvar5 = ['a', 'b'] 1051 let w:wvar6 = #{action: 'run'} 1052 call assert_equal(10, luaeval('vim.w.wvar1')) 1053 call assert_equal('edit', luaeval('vim.w.wvar2')) 1054 call assert_equal(3.14, luaeval('vim.w.wvar3')) 1055 call assert_equal(0zdeadbeef, luaeval('vim.w.wvar4')) 1056 call assert_equal(['a', 'b'], luaeval('vim.w.wvar5')) 1057 call assert_equal(#{action: 'run'}, luaeval('vim.w.wvar6')) 1058 call assert_equal(v:null, luaeval('vim.w.NonExisting')) 1059 1060 " modify a window variable 1061 lua vim.w.wvar2 = 'paste' 1062 call assert_equal('paste', w:wvar2) 1063 1064 " change the type stored in a variable 1065 let w:wvar2 = [1, 2] 1066 lua vim.w.wvar2 = vim.dict({a=10, b=20}) 1067 call assert_equal(#{a: 10, b: 20}, w:wvar2) 1068 1069 " create a new window variable 1070 lua vim.w.wvar7 = vim.dict({a=vim.list({1, 2}), b=20}) 1071 call assert_equal(#{a: [1, 2], b: 20}, w:wvar7) 1072 1073 " delete a window variable 1074 lua vim.w.wvar2 = Nil 1075 call assert_false(exists('w:wvar2')) 1076 1077 new 1078 call assert_equal(v:null, luaeval('vim.w.wvar1')) 1079 call assert_equal(v:null, luaeval('vim.w.wvar2')) 1080 %bw! 1081endfunc 1082 1083" Test for adding, accessing and modifying buffer-local variables using the 1084" vim.b Lua table 1085func Test_lua_buffer_var_table() 1086 " Access buffer variables with different types of values 1087 let b:bvar1 = 10 1088 let b:bvar2 = 'edit' 1089 let b:bvar3 = 3.14 1090 let b:bvar4 = 0zdeadbeef 1091 let b:bvar5 = ['a', 'b'] 1092 let b:bvar6 = #{action: 'run'} 1093 call assert_equal(10, luaeval('vim.b.bvar1')) 1094 call assert_equal('edit', luaeval('vim.b.bvar2')) 1095 call assert_equal(3.14, luaeval('vim.b.bvar3')) 1096 call assert_equal(0zdeadbeef, luaeval('vim.b.bvar4')) 1097 call assert_equal(['a', 'b'], luaeval('vim.b.bvar5')) 1098 call assert_equal(#{action: 'run'}, luaeval('vim.b.bvar6')) 1099 call assert_equal(v:null, luaeval('vim.b.NonExisting')) 1100 1101 " modify a buffer variable 1102 lua vim.b.bvar2 = 'paste' 1103 call assert_equal('paste', b:bvar2) 1104 1105 " change the type stored in a variable 1106 let b:bvar2 = [1, 2] 1107 lua vim.b.bvar2 = vim.dict({a=10, b=20}) 1108 call assert_equal(#{a: 10, b: 20}, b:bvar2) 1109 1110 " create a new buffer variable 1111 lua vim.b.bvar7 = vim.dict({a=vim.list({1, 2}), b=20}) 1112 call assert_equal(#{a: [1, 2], b: 20}, b:bvar7) 1113 1114 " delete a buffer variable 1115 lua vim.b.bvar2 = Nil 1116 call assert_false(exists('b:bvar2')) 1117 1118 new 1119 call assert_equal(v:null, luaeval('vim.b.bvar1')) 1120 call assert_equal(v:null, luaeval('vim.b.bvar2')) 1121 %bw! 1122endfunc 1123 1124" Test for adding, accessing and modifying tabpage-local variables using the 1125" vim.t Lua table 1126func Test_lua_tabpage_var_table() 1127 " Access tabpage variables with different types of values 1128 let t:tvar1 = 10 1129 let t:tvar2 = 'edit' 1130 let t:tvar3 = 3.14 1131 let t:tvar4 = 0zdeadbeef 1132 let t:tvar5 = ['a', 'b'] 1133 let t:tvar6 = #{action: 'run'} 1134 call assert_equal(10, luaeval('vim.t.tvar1')) 1135 call assert_equal('edit', luaeval('vim.t.tvar2')) 1136 call assert_equal(3.14, luaeval('vim.t.tvar3')) 1137 call assert_equal(0zdeadbeef, luaeval('vim.t.tvar4')) 1138 call assert_equal(['a', 'b'], luaeval('vim.t.tvar5')) 1139 call assert_equal(#{action: 'run'}, luaeval('vim.t.tvar6')) 1140 call assert_equal(v:null, luaeval('vim.t.NonExisting')) 1141 1142 " modify a tabpage variable 1143 lua vim.t.tvar2 = 'paste' 1144 call assert_equal('paste', t:tvar2) 1145 1146 " change the type stored in a variable 1147 let t:tvar2 = [1, 2] 1148 lua vim.t.tvar2 = vim.dict({a=10, b=20}) 1149 call assert_equal(#{a: 10, b: 20}, t:tvar2) 1150 1151 " create a new tabpage variable 1152 lua vim.t.tvar7 = vim.dict({a=vim.list({1, 2}), b=20}) 1153 call assert_equal(#{a: [1, 2], b: 20}, t:tvar7) 1154 1155 " delete a tabpage variable 1156 lua vim.t.tvar2 = Nil 1157 call assert_false(exists('t:tvar2')) 1158 1159 tabnew 1160 call assert_equal(v:null, luaeval('vim.t.tvar1')) 1161 call assert_equal(v:null, luaeval('vim.t.tvar2')) 1162 %bw! 1163endfunc 1164 1165" Test for vim.version() 1166func Test_lua_vim_version() 1167 lua << trim END 1168 vimver = vim.version() 1169 vimver_n = vimver.major * 100 + vimver.minor 1170 END 1171 call assert_equal(v:version, luaeval('vimver_n')) 1172endfunc 1173 1174" Test for running multiple commands using vim.command() 1175func Test_lua_multiple_commands() 1176 lua << trim END 1177 vim.command([[ 1178 let Var1 = [] 1179 for i in range(3) 1180 let Var1 += [#{name: 'x'}] 1181 endfor 1182 augroup Luagroup 1183 autocmd! 1184 autocmd User Luatest echo 'Hello' 1185 augroup END 1186 ]]) 1187 END 1188 call assert_equal([{'name': 'x'}, {'name': 'x'}, {'name': 'x'}], Var1) 1189 call assert_true(exists('#Luagroup')) 1190 call assert_true(exists('#Luagroup#User#Luatest')) 1191 augroup Luagroup 1192 autocmd! 1193 augroup END 1194 augroup! Luagroup 1195endfunc 1196 1197" vim: shiftwidth=2 sts=2 expandtab 1198