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:luaver = split(split(systemlist('lua -v')[0], ' ')[1], '\.') 17if len(s:luaver) < 3 18 " Didn't get something that looks like a version, use _VERSION. 19 let s:luaver = split(split(luaeval('_VERSION'), ' ')[1], '\.') 20endif 21let s:major = str2nr(s:luaver[0]) 22let s:minor = str2nr(s:luaver[1]) 23if len(s:luaver >= 3) 24 let s:patch = str2nr(s:luaver[2]) 25else 26 let s:patch = 0 27endif 28let s:lua_53_or_later = 0 29let s:lua_543_or_later = 0 30if (s:major == 5 && s:minor >= 3) || s:major > 5 31 let s:lua_53_or_later = 1 32 if (s:major == 5 33 \ && ((s:minor == 4 && s:patch >= 3) || s:minor > 4)) 34 \ || s:major > 5 35 let s:lua_543_or_later = 1 36 endif 37endif 38 39func TearDown() 40 " Run garbage collection after each test to exercise luaV_setref(). 41 call test_garbagecollect_now() 42endfunc 43 44" Check that switching to another buffer does not trigger ml_get error. 45func Test_lua_command_new_no_ml_get_error() 46 new 47 let wincount = winnr('$') 48 call setline(1, ['one', 'two', 'three']) 49 luado vim.command("new") 50 call assert_equal(wincount + 1, winnr('$')) 51 %bwipe! 52endfunc 53 54" Test vim.command() 55func Test_lua_command() 56 new 57 call setline(1, ['one', 'two', 'three']) 58 luado vim.command("1,2d_") 59 call assert_equal(['three'], getline(1, '$')) 60 bwipe! 61endfunc 62 63func Test_lua_luado() 64 new 65 call setline(1, ['one', 'two']) 66 luado return(linenr) 67 call assert_equal(['1', '2'], getline(1, '$')) 68 close! 69 70 " Error cases 71 call assert_fails('luado string.format()', 72 \ "[string \"vim chunk\"]:1: bad argument #1 to 'format' (string expected, got no value)") 73 if s:lua_543_or_later 74 let msg = "[string \"vim chunk\"]:1: global 'func' is not callable (a nil value)" 75 elseif s:lua_53_or_later 76 let msg = "[string \"vim chunk\"]:1: attempt to call a nil value (global 'func')" 77 else 78 let msg = "[string \"vim chunk\"]:1: attempt to call global 'func' (a nil value)" 79 endif 80 call assert_fails('luado func()', msg) 81 call assert_fails('luado error("failed")', "[string \"vim chunk\"]:1: failed") 82endfunc 83 84" Test vim.eval() 85func Test_lua_eval() 86 " lua.eval with a number 87 lua v = vim.eval('123') 88 call assert_equal('number', luaeval('vim.type(v)')) 89 call assert_equal(123, luaeval('v')) 90 91 " lua.eval with a string 92 lua v = vim.eval('"abc"') 93 call assert_equal('string', 'vim.type(v)'->luaeval()) 94 call assert_equal('abc', luaeval('v')) 95 96 " lua.eval with a list 97 lua v = vim.eval("['a']") 98 call assert_equal('list', luaeval('vim.type(v)')) 99 call assert_equal(['a'], luaeval('v')) 100 101 " lua.eval with a dict 102 lua v = vim.eval("{'a':'b'}") 103 call assert_equal('dict', luaeval('vim.type(v)')) 104 call assert_equal({'a':'b'}, luaeval('v')) 105 106 " lua.eval with a blob 107 lua v = vim.eval("0z00112233.deadbeef") 108 call assert_equal('blob', luaeval('vim.type(v)')) 109 call assert_equal(0z00112233.deadbeef, luaeval('v')) 110 111 " lua.eval with a float 112 lua v = vim.eval('3.14') 113 call assert_equal('number', luaeval('vim.type(v)')) 114 call assert_equal(3.14, luaeval('v')) 115 116 " lua.eval with a bool 117 lua v = vim.eval('v:true') 118 call assert_equal('number', luaeval('vim.type(v)')) 119 call assert_equal(1, luaeval('v')) 120 lua v = vim.eval('v:false') 121 call assert_equal('number', luaeval('vim.type(v)')) 122 call assert_equal(0, luaeval('v')) 123 124 " lua.eval with a null 125 lua v = vim.eval('v:null') 126 call assert_equal('nil', luaeval('vim.type(v)')) 127 call assert_equal(v:null, luaeval('v')) 128 129 call assert_fails('lua v = vim.eval(nil)', 130 \ "[string \"vim chunk\"]:1: bad argument #1 to 'eval' (string expected, got nil)") 131 call assert_fails('lua v = vim.eval(true)', 132 \ "[string \"vim chunk\"]:1: bad argument #1 to 'eval' (string expected, got boolean)") 133 call assert_fails('lua v = vim.eval({})', 134 \ "[string \"vim chunk\"]:1: bad argument #1 to 'eval' (string expected, got table)") 135 call assert_fails('lua v = vim.eval(print)', 136 \ "[string \"vim chunk\"]:1: bad argument #1 to 'eval' (string expected, got function)") 137 call assert_fails('lua v = vim.eval(vim.buffer())', 138 \ "[string \"vim chunk\"]:1: bad argument #1 to 'eval' (string expected, got userdata)") 139 140 lua v = nil 141endfunc 142 143" Test luaeval() with lambda 144func Test_luaeval_with_lambda() 145 lua function hello_luaeval_lambda(a, cb) return a .. cb() end 146 call assert_equal('helloworld', 147 \ luaeval('hello_luaeval_lambda(_A[1], _A[2])', 148 \ ['hello', {->'world'}])) 149 lua hello_luaeval_lambda = nil 150endfunc 151 152" Test vim.window() 153func Test_lua_window() 154 e Xfoo2 155 new Xfoo1 156 157 " Window 1 (top window) contains Xfoo1 158 " Window 2 (bottom window) contains Xfoo2 159 call assert_equal('Xfoo1', luaeval('vim.window(1):buffer().name')) 160 call assert_equal('Xfoo2', luaeval('vim.window(2):buffer().name')) 161 162 " Window 3 does not exist so vim.window(3) should return nil 163 call assert_equal('nil', luaeval('tostring(vim.window(3))')) 164 165 if s:lua_543_or_later 166 let msg = "[string \"luaeval\"]:1: field 'xyz' is not callable (a nil value)" 167 elseif s:lua_53_or_later 168 let msg = "[string \"luaeval\"]:1: attempt to call a nil value (field 'xyz')" 169 else 170 let msg = "[string \"luaeval\"]:1: attempt to call field 'xyz' (a nil value)" 171 endif 172 call assert_fails("let n = luaeval('vim.window().xyz()')", msg) 173 call assert_fails('lua vim.window().xyz = 1', 174 \ "[string \"vim chunk\"]:1: invalid window property: `xyz'") 175 176 %bwipe! 177endfunc 178 179" Test vim.window().height 180func Test_lua_window_height() 181 new 182 lua vim.window().height = 2 183 call assert_equal(2, winheight(0)) 184 lua vim.window().height = vim.window().height + 1 185 call assert_equal(3, winheight(0)) 186 bwipe! 187endfunc 188 189" Test vim.window().width 190func Test_lua_window_width() 191 vert new 192 lua vim.window().width = 2 193 call assert_equal(2, winwidth(0)) 194 lua vim.window().width = vim.window().width + 1 195 call assert_equal(3, winwidth(0)) 196 bwipe! 197endfunc 198 199" Test vim.window().line and vim.window.col 200func Test_lua_window_line_col() 201 new 202 call setline(1, ['line1', 'line2', 'line3']) 203 lua vim.window().line = 2 204 lua vim.window().col = 4 205 call assert_equal([0, 2, 4, 0], getpos('.')) 206 lua vim.window().line = vim.window().line + 1 207 lua vim.window().col = vim.window().col - 1 208 call assert_equal([0, 3, 3, 0], getpos('.')) 209 210 call assert_fails('lua vim.window().line = 10', 211 \ '[string "vim chunk"]:1: line out of range') 212 bwipe! 213endfunc 214 215" Test vim.call 216func Test_lua_call() 217 call assert_equal(has('lua'), luaeval('vim.call("has", "lua")')) 218 call assert_equal(printf("Hello %s", "vim"), luaeval('vim.call("printf", "Hello %s", "vim")')) 219 220 " Error cases 221 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)')", 222 \ s:lua_53_or_later 223 \ ? '[string "luaeval"]:1: Function called with too many arguments' 224 \ : 'Function called with too many arguments') 225 lua co = coroutine.create(function () print("hi") end) 226 call assert_fails("call luaeval('vim.call(\"type\", co)')", 227 \ s:lua_53_or_later 228 \ ? '[string "luaeval"]:1: lua: cannot convert value' 229 \ : 'lua: cannot convert value') 230 lua co = nil 231 call assert_fails("call luaeval('vim.call(\"abc\")')", 232 \ ['E117:', s:lua_53_or_later ? '\[string "luaeval"]:1: lua: call_vim_function failed' 233 \ : 'lua: call_vim_function failed']) 234endfunc 235 236" Test vim.fn.* 237func Test_lua_fn() 238 call assert_equal(has('lua'), luaeval('vim.fn.has("lua")')) 239 call assert_equal(printf("Hello %s", "vim"), luaeval('vim.fn.printf("Hello %s", "vim")')) 240endfunc 241 242" Test setting the current window 243func Test_lua_window_set_current() 244 new Xfoo1 245 lua w1 = vim.window() 246 new Xfoo2 247 lua w2 = vim.window() 248 249 call assert_equal('Xfoo2', bufname('%')) 250 lua w1() 251 call assert_equal('Xfoo1', bufname('%')) 252 lua w2() 253 call assert_equal('Xfoo2', bufname('%')) 254 255 lua w1, w2 = nil 256 %bwipe! 257endfunc 258 259" Test vim.window().buffer 260func Test_lua_window_buffer() 261 new Xfoo1 262 lua w1 = vim.window() 263 lua b1 = w1.buffer() 264 new Xfoo2 265 lua w2 = vim.window() 266 lua b2 = w2.buffer() 267 268 lua b1() 269 call assert_equal('Xfoo1', bufname('%')) 270 lua b2() 271 call assert_equal('Xfoo2', bufname('%')) 272 273 lua b1, b2, w1, w2 = nil 274 %bwipe! 275endfunc 276 277" Test vim.window():previous() and vim.window():next() 278func Test_lua_window_next_previous() 279 new Xfoo1 280 new Xfoo2 281 new Xfoo3 282 wincmd j 283 284 call assert_equal('Xfoo2', luaeval('vim.window().buffer().name')) 285 call assert_equal('Xfoo1', luaeval('vim.window():next():buffer().name')) 286 call assert_equal('Xfoo3', luaeval('vim.window():previous():buffer().name')) 287 288 %bwipe! 289endfunc 290 291" Test vim.window():isvalid() 292func Test_lua_window_isvalid() 293 new Xfoo 294 lua w = vim.window() 295 call assert_true(luaeval('w:isvalid()')) 296 297 " FIXME: how to test the case when isvalid() returns v:false? 298 " isvalid() gives errors when the window is deleted. Is it a bug? 299 300 lua w = nil 301 bwipe! 302endfunc 303 304" Test vim.buffer() with and without argument 305func Test_lua_buffer() 306 new Xfoo1 307 let bn1 = bufnr('%') 308 new Xfoo2 309 let bn2 = bufnr('%') 310 311 " Test vim.buffer() without argument. 312 call assert_equal('Xfoo2', luaeval("vim.buffer().name")) 313 314 " Test vim.buffer() with string argument. 315 call assert_equal('Xfoo1', luaeval("vim.buffer('Xfoo1').name")) 316 call assert_equal('Xfoo2', luaeval("vim.buffer('Xfoo2').name")) 317 318 " Test vim.buffer() with integer argument. 319 call assert_equal('Xfoo1', luaeval("vim.buffer(" . bn1 . ").name")) 320 call assert_equal('Xfoo2', luaeval("vim.buffer(" . bn2 . ").name")) 321 322 lua bn1, bn2 = nil 323 %bwipe! 324endfunc 325 326" Test vim.buffer().name and vim.buffer().fname 327func Test_lua_buffer_name() 328 new 329 call assert_equal('', luaeval('vim.buffer().name')) 330 call assert_equal('', luaeval('vim.buffer().fname')) 331 bwipe! 332 333 new Xfoo 334 call assert_equal('Xfoo', luaeval('vim.buffer().name')) 335 call assert_equal(expand('%:p'), luaeval('vim.buffer().fname')) 336 bwipe! 337endfunc 338 339" Test vim.buffer().number 340func Test_lua_buffer_number() 341 " All numbers in Lua are floating points number (no integers). 342 call assert_equal(bufnr('%'), float2nr(luaeval('vim.buffer().number'))) 343endfunc 344 345" Test inserting lines in buffer. 346func Test_lua_buffer_insert() 347 new 348 lua vim.buffer()[1] = '3' 349 lua vim.buffer():insert('1', 0) 350 lua vim.buffer():insert('2', 1) 351 lua vim.buffer():insert('4', 10) 352 353 call assert_equal(['1', '2', '3', '4'], getline(1, '$')) 354 call assert_equal('4', luaeval('vim.buffer()[4]')) 355 call assert_equal(v:null, luaeval('vim.buffer()[5]')) 356 call assert_equal(v:null, luaeval('vim.buffer()[{}]')) 357 if s:lua_543_or_later 358 let msg = "[string \"vim chunk\"]:1: method 'xyz' is not callable (a nil value)" 359 elseif s:lua_53_or_later 360 let msg = "[string \"vim chunk\"]:1: attempt to call a nil value (method 'xyz')" 361 else 362 let msg = "[string \"vim chunk\"]:1: attempt to call method 'xyz' (a nil value)" 363 endif 364 call assert_fails('lua vim.buffer():xyz()', msg) 365 call assert_fails('lua vim.buffer()[1] = {}', 366 \ '[string "vim chunk"]:1: wrong argument to change') 367 bwipe! 368endfunc 369 370" Test deleting line in buffer 371func Test_lua_buffer_delete() 372 new 373 call setline(1, ['1', '2', '3']) 374 call cursor(3, 1) 375 lua vim.buffer()[2] = nil 376 call assert_equal(['1', '3'], getline(1, '$')) 377 378 call assert_fails('lua vim.buffer()[3] = nil', 379 \ '[string "vim chunk"]:1: invalid line number') 380 bwipe! 381endfunc 382 383" Test #vim.buffer() i.e. number of lines in buffer 384func Test_lua_buffer_number_lines() 385 new 386 call setline(1, ['a', 'b', 'c']) 387 call assert_equal(3, luaeval('#vim.buffer()')) 388 bwipe! 389endfunc 390 391" Test vim.buffer():next() and vim.buffer():previous() 392" Note that these functions get the next or previous buffers 393" but do not switch buffer. 394func Test_lua_buffer_next_previous() 395 new Xfoo1 396 new Xfoo2 397 new Xfoo3 398 b Xfoo2 399 400 lua bn = vim.buffer():next() 401 lua bp = vim.buffer():previous() 402 403 call assert_equal('Xfoo2', luaeval('vim.buffer().name')) 404 call assert_equal('Xfoo1', luaeval('bp.name')) 405 call assert_equal('Xfoo3', luaeval('bn.name')) 406 407 call assert_equal('Xfoo2', bufname('%')) 408 409 lua bn() 410 call assert_equal('Xfoo3', luaeval('vim.buffer().name')) 411 call assert_equal('Xfoo3', bufname('%')) 412 413 lua bp() 414 call assert_equal('Xfoo1', luaeval('vim.buffer().name')) 415 call assert_equal('Xfoo1', bufname('%')) 416 417 lua bn, bp = nil 418 %bwipe! 419endfunc 420 421" Test vim.buffer():isvalid() 422func Test_lua_buffer_isvalid() 423 new Xfoo 424 lua b = vim.buffer() 425 call assert_true(luaeval('b:isvalid()')) 426 427 " FIXME: how to test the case when isvalid() returns v:false? 428 " isvalid() gives errors when the buffer is wiped. Is it a bug? 429 430 lua b = nil 431 bwipe! 432endfunc 433 434func Test_lua_list() 435 call assert_equal([], luaeval('vim.list()')) 436 437 let l = [] 438 lua l = vim.eval('l') 439 lua l:add(123) 440 lua l:add('abc') 441 lua l:add(true) 442 lua l:add(false) 443 lua l:add(nil) 444 lua l:add(vim.eval("[1, 2, 3]")) 445 lua l:add(vim.eval("{'a':1, 'b':2, 'c':3}")) 446 call assert_equal([123, 'abc', v:true, v:false, v:null, [1, 2, 3], {'a': 1, 'b': 2, 'c': 3}], l) 447 call assert_equal(7, luaeval('#l')) 448 call assert_match('^list: \%(0x\)\?\x\+$', luaeval('tostring(l)')) 449 450 lua l[1] = 124 451 lua l[6] = nil 452 lua l:insert('first') 453 lua l:insert('xx', 3) 454 call assert_fails('lua l:insert("xx", -20)', 455 \ '[string "vim chunk"]:1: invalid position') 456 call assert_equal(['first', 124, 'abc', 'xx', v:true, v:false, v:null, {'a': 1, 'b': 2, 'c': 3}], l) 457 458 lockvar 1 l 459 call assert_fails('lua l:add("x")', '[string "vim chunk"]:1: list is locked') 460 call assert_fails('lua l:insert(2)', '[string "vim chunk"]:1: list is locked') 461 call assert_fails('lua l[9] = 1', '[string "vim chunk"]:1: list is locked') 462 463 unlockvar l 464 let l = [1, 2] 465 lua ll = vim.eval('l') 466 let x = luaeval("ll[3]") 467 call assert_equal(v:null, x) 468 if s:lua_543_or_later 469 let msg = "[string \"luaeval\"]:1: method 'xyz' is not callable (a nil value)" 470 elseif s:lua_53_or_later 471 let msg = "[string \"luaeval\"]:1: attempt to call a nil value (method 'xyz')" 472 else 473 let msg = "[string \"luaeval\"]:1: attempt to call method 'xyz' (a nil value)" 474 endif 475 call assert_fails('let x = luaeval("ll:xyz(3)")', msg) 476 let y = luaeval("ll[{}]") 477 call assert_equal(v:null, y) 478 479 lua l = nil 480endfunc 481 482func Test_lua_list_table() 483 " See :help lua-vim 484 " Non-numeric keys should not be used to initialize the list 485 " so say = 'hi' should be ignored. 486 lua t = {3.14, 'hello', false, true, say = 'hi'} 487 call assert_equal([3.14, 'hello', v:false, v:true], luaeval('vim.list(t)')) 488 lua t = nil 489 490 call assert_fails('lua vim.list(1)', '[string "vim chunk"]:1: table expected, got number') 491 call assert_fails('lua vim.list("x")', '[string "vim chunk"]:1: table expected, got string') 492 call assert_fails('lua vim.list(print)', '[string "vim chunk"]:1: table expected, got function') 493 call assert_fails('lua vim.list(true)', '[string "vim chunk"]:1: table expected, got boolean') 494endfunc 495 496func Test_lua_list_table_insert_remove() 497 if !s:lua_53_or_later 498 throw 'Skipped: Lua version < 5.3' 499 endif 500 501 let l = [1, 2] 502 lua t = vim.eval('l') 503 lua table.insert(t, 10) 504 lua t[#t + 1] = 20 505 lua table.insert(t, 2, 30) 506 call assert_equal(l, [1, 30, 2, 10, 20]) 507 lua table.remove(t, 2) 508 call assert_equal(l, [1, 2, 10, 20]) 509 lua t[3] = nil 510 call assert_equal(l, [1, 2, 20]) 511 lua removed_value = table.remove(t, 3) 512 call assert_equal(luaeval('removed_value'), 20) 513 lua t = nil 514 lua removed_value = nil 515 unlet l 516endfunc 517 518" Test l() i.e. iterator on list 519func Test_lua_list_iter() 520 lua l = vim.list():add('foo'):add('bar') 521 lua str = '' 522 lua for v in l() do str = str .. v end 523 call assert_equal('foobar', luaeval('str')) 524 525 lua str, l = nil 526endfunc 527 528func Test_lua_recursive_list() 529 lua l = vim.list():add(1):add(2) 530 lua l = l:add(l) 531 532 call assert_equal(1, luaeval('l[1]')) 533 call assert_equal(2, luaeval('l[2]')) 534 535 call assert_equal(1, luaeval('l[3][1]')) 536 call assert_equal(2, luaeval('l[3][2]')) 537 538 call assert_equal(1, luaeval('l[3][3][1]')) 539 call assert_equal(2, luaeval('l[3][3][2]')) 540 541 call assert_equal('[1, 2, [...]]', string(luaeval('l'))) 542 543 call assert_match('^list: \%(0x\)\?\x\+$', luaeval('tostring(l)')) 544 call assert_equal(luaeval('tostring(l)'), luaeval('tostring(l[3])')) 545 546 call assert_equal(luaeval('l'), luaeval('l[3]')) 547 call assert_equal(luaeval('l'), luaeval('l[3][3]')) 548 549 lua l = nil 550endfunc 551 552func Test_lua_dict() 553 call assert_equal({}, luaeval('vim.dict()')) 554 555 let d = {} 556 lua d = vim.eval('d') 557 lua d[0] = 123 558 lua d[1] = "abc" 559 lua d[2] = true 560 lua d[3] = false 561 lua d[4] = vim.eval("[1, 2, 3]") 562 lua d[5] = vim.eval("{'a':1, 'b':2, 'c':3}") 563 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) 564 call assert_equal(6, luaeval('#d')) 565 call assert_match('^dict: \%(0x\)\?\x\+$', luaeval('tostring(d)')) 566 567 call assert_equal('abc', luaeval('d[1]')) 568 call assert_equal(v:null, luaeval('d[22]')) 569 570 lua d[0] = 124 571 lua d[4] = nil 572 call assert_equal({'0':124, '1':'abc', '2':v:true, '3':v:false, '5': {'a':1, 'b':2, 'c':3}}, d) 573 574 lockvar 1 d 575 call assert_fails('lua d[6] = 1', '[string "vim chunk"]:1: dict is locked') 576 unlockvar d 577 578 " Error case 579 lua d = {} 580 lua d[''] = 10 581 call assert_fails("let t = luaeval('vim.dict(d)')", 582 \ s:lua_53_or_later 583 \ ? '[string "luaeval"]:1: table has empty key' 584 \ : 'table has empty key') 585 let d = {} 586 lua x = vim.eval('d') 587 call assert_fails("lua x[''] = 10", '[string "vim chunk"]:1: empty key') 588 lua x['a'] = nil 589 call assert_equal({}, d) 590 591 " cannot assign funcrefs in the global scope 592 lua x = vim.eval('g:') 593 call assert_fails("lua x['min'] = vim.funcref('max')", 594 \ '[string "vim chunk"]:1: cannot assign funcref to builtin scope') 595 596 lua d = nil 597endfunc 598 599func Test_lua_dict_table() 600 lua t = {key1 = 'x', key2 = 3.14, key3 = true, key4 = false} 601 call assert_equal({'key1': 'x', 'key2': 3.14, 'key3': v:true, 'key4': v:false}, 602 \ luaeval('vim.dict(t)')) 603 604 " Same example as in :help lua-vim. 605 lua t = {math.pi, false, say = 'hi'} 606 " FIXME: commented out as it currently does not work as documented: 607 " Expected {'say': 'hi'} 608 " but got {'1': 3.141593, '2': v:false, 'say': 'hi'} 609 " Is the documentation or the code wrong? 610 "call assert_equal({'say' : 'hi'}, luaeval('vim.dict(t)')) 611 lua t = nil 612 613 call assert_fails('lua vim.dict(1)', '[string "vim chunk"]:1: table expected, got number') 614 call assert_fails('lua vim.dict("x")', '[string "vim chunk"]:1: table expected, got string') 615 call assert_fails('lua vim.dict(print)', '[string "vim chunk"]:1: table expected, got function') 616 call assert_fails('lua vim.dict(true)', '[string "vim chunk"]:1: table expected, got boolean') 617endfunc 618 619" Test d() i.e. iterator on dictionary 620func Test_lua_dict_iter() 621 let d = {'a': 1, 'b':2} 622 lua d = vim.eval('d') 623 lua str = '' 624 lua for k,v in d() do str = str .. k ..':' .. v .. ',' end 625 call assert_equal('a:1,b:2,', luaeval('str')) 626 627 lua str, d = nil 628endfunc 629 630func Test_lua_blob() 631 call assert_equal(0z, luaeval('vim.blob("")')) 632 call assert_equal(0z31326162, luaeval('vim.blob("12ab")')) 633 call assert_equal(0z00010203, luaeval('vim.blob("\x00\x01\x02\x03")')) 634 call assert_equal(0z8081FEFF, luaeval('vim.blob("\x80\x81\xfe\xff")')) 635 636 lua b = vim.blob("\x00\x00\x00\x00") 637 call assert_equal(0z00000000, luaeval('b')) 638 call assert_equal(4, luaeval('#b')) 639 lua b[0], b[1], b[2], b[3] = 1, 32, 256, 0xff 640 call assert_equal(0z012000ff, luaeval('b')) 641 lua b[4] = string.byte("z", 1) 642 call assert_equal(0z012000ff.7a, luaeval('b')) 643 call assert_equal(5, luaeval('#b')) 644 call assert_fails('lua b[#b+1] = 0x80', '[string "vim chunk"]:1: index out of range') 645 lua b:add("12ab") 646 call assert_equal(0z012000ff.7a313261.62, luaeval('b')) 647 call assert_equal(9, luaeval('#b')) 648 call assert_fails('lua b:add(nil)', '[string "vim chunk"]:1: string expected, got nil') 649 call assert_fails('lua b:add(true)', '[string "vim chunk"]:1: string expected, got boolean') 650 call assert_fails('lua b:add({})', '[string "vim chunk"]:1: string expected, got table') 651 lua b = nil 652 653 let b = 0z0102 654 lua lb = vim.eval('b') 655 let n = luaeval('lb[1]') 656 call assert_equal(2, n) 657 let n = luaeval('lb[6]') 658 call assert_equal(v:null, n) 659 if s:lua_543_or_later 660 let msg = "[string \"luaeval\"]:1: method 'xyz' is not callable (a nil value)" 661 elseif s:lua_53_or_later 662 let msg = "[string \"luaeval\"]:1: attempt to call a nil value (method 'xyz')" 663 else 664 let msg = "[string \"luaeval\"]:1: attempt to call method 'xyz' (a nil value)" 665 endif 666 call assert_fails('let x = luaeval("lb:xyz(3)")', msg) 667 let y = luaeval("lb[{}]") 668 call assert_equal(v:null, y) 669 670 lockvar b 671 call assert_fails('lua lb[1] = 2', '[string "vim chunk"]:1: blob is locked') 672 call assert_fails('lua lb:add("12")', '[string "vim chunk"]:1: blob is locked') 673 674 " Error cases 675 lua t = {} 676 call assert_fails('lua b = vim.blob(t)', 677 \ '[string "vim chunk"]:1: string expected, got table') 678endfunc 679 680func Test_lua_funcref() 681 function I(x) 682 return a:x 683 endfunction 684 let R = function('I') 685 lua i1 = vim.funcref"I" 686 lua i2 = vim.eval"R" 687 lua msg = "funcref|test|" .. (#i2(i1) == #i1(i2) and "OK" or "FAIL") 688 lua msg = vim.funcref"tr"(msg, "|", " ") 689 call assert_equal("funcref test OK", luaeval('msg')) 690 691 " Error cases 692 call assert_fails('lua f1 = vim.funcref("")', 693 \ '[string "vim chunk"]:1: invalid function name: ') 694 call assert_fails('lua f1 = vim.funcref("10")', 695 \ '[string "vim chunk"]:1: invalid function name: 10') 696 let fname = test_null_string() 697 call assert_fails('lua f1 = vim.funcref(fname)', 698 \ "[string \"vim chunk\"]:1: bad argument #1 to 'funcref' (string expected, got nil)") 699 call assert_fails('lua vim.funcref("abc")()', 700 \ ['E117:', '\[string "vim chunk"]:1: cannot call funcref']) 701 702 " dict funcref 703 function Mylen() dict 704 return len(self.data) 705 endfunction 706 let l = [0, 1, 2, 3] 707 let mydict = {'data': l} 708 lua d = vim.eval"mydict" 709 lua d.len = vim.funcref"Mylen" -- assign d as 'self' 710 lua res = (d.len() == vim.funcref"len"(vim.eval"l")) and "OK" or "FAIL" 711 call assert_equal("OK", luaeval('res')) 712 call assert_equal(function('Mylen', {'data': l, 'len': function('Mylen')}), mydict.len) 713 714 lua i1, i2, msg, d, res = nil 715endfunc 716 717" Test vim.type() 718func Test_lua_type() 719 " The following values are identical to Lua's type function. 720 call assert_equal('string', luaeval('vim.type("foo")')) 721 call assert_equal('number', luaeval('vim.type(1)')) 722 call assert_equal('number', luaeval('vim.type(1.2)')) 723 call assert_equal('function', luaeval('vim.type(print)')) 724 call assert_equal('table', luaeval('vim.type({})')) 725 call assert_equal('boolean', luaeval('vim.type(true)')) 726 call assert_equal('boolean', luaeval('vim.type(false)')) 727 call assert_equal('nil', luaeval('vim.type(nil)')) 728 729 " The following values are specific to Vim. 730 call assert_equal('window', luaeval('vim.type(vim.window())')) 731 call assert_equal('buffer', luaeval('vim.type(vim.buffer())')) 732 call assert_equal('list', luaeval('vim.type(vim.list())')) 733 call assert_equal('dict', luaeval('vim.type(vim.dict())')) 734 call assert_equal('funcref', luaeval('vim.type(vim.funcref("Test_type"))')) 735endfunc 736 737" Test vim.open() 738func Test_lua_open() 739 call assert_notmatch('XOpen', execute('ls')) 740 741 " Open a buffer XOpen1, but do not jump to it. 742 lua b = vim.open('XOpen1') 743 call assert_equal('XOpen1', luaeval('b.name')) 744 call assert_equal('', bufname('%')) 745 746 call assert_match('XOpen1', execute('ls')) 747 call assert_notequal('XOpen2', bufname('%')) 748 749 " Open a buffer XOpen2 and jump to it. 750 lua b = vim.open('XOpen2')() 751 call assert_equal('XOpen2', luaeval('b.name')) 752 call assert_equal('XOpen2', bufname('%')) 753 754 lua b = nil 755 %bwipe! 756endfunc 757 758func Test_update_package_paths() 759 set runtimepath+=./testluaplugin 760 call assert_equal("hello from lua", luaeval("require('testluaplugin').hello()")) 761endfunc 762 763func Vim_func_call_lua_callback(Concat, Cb) 764 let l:message = a:Concat("hello", "vim") 765 call a:Cb(l:message) 766endfunc 767 768func Test_pass_lua_callback_to_vim_from_lua() 769 lua pass_lua_callback_to_vim_from_lua_result = "" 770 call assert_equal("", luaeval("pass_lua_callback_to_vim_from_lua_result")) 771 lua <<EOF 772 vim.funcref('Vim_func_call_lua_callback')( 773 function(greeting, message) 774 return greeting .. " " .. message 775 end, 776 function(message) 777 pass_lua_callback_to_vim_from_lua_result = message 778 end) 779EOF 780 call assert_equal("hello vim", luaeval("pass_lua_callback_to_vim_from_lua_result")) 781endfunc 782 783func Vim_func_call_metatable_lua_callback(Greet) 784 return a:Greet("world") 785endfunc 786 787func Test_pass_lua_metatable_callback_to_vim_from_lua() 788 let result = luaeval("vim.funcref('Vim_func_call_metatable_lua_callback')(setmetatable({ space = ' '}, { __call = function(tbl, msg) return 'hello' .. tbl.space .. msg end }) )") 789 call assert_equal("hello world", result) 790endfunc 791 792" Test vim.line() 793func Test_lua_line() 794 new 795 call setline(1, ['first line', 'second line']) 796 1 797 call assert_equal('first line', luaeval('vim.line()')) 798 2 799 call assert_equal('second line', luaeval('vim.line()')) 800 bwipe! 801endfunc 802 803" Test vim.beep() 804func Test_lua_beep() 805 call assert_beeps('lua vim.beep()') 806endfunc 807 808" Test errors in luaeval() 809func Test_luaeval_error() 810 " Compile error 811 call assert_fails("call luaeval('-nil')", 812 \ '[string "luaeval"]:1: attempt to perform arithmetic on a nil value') 813 call assert_fails("call luaeval(']')", 814 \ "[string \"luaeval\"]:1: unexpected symbol near ']'") 815 lua co = coroutine.create(function () print("hi") end) 816 call assert_fails('let i = luaeval("co")', 'luaeval: cannot convert value') 817 lua co = nil 818 call assert_fails('let m = luaeval("{}")', 'luaeval: cannot convert value') 819endfunc 820 821" Test :luafile foo.lua 822func Test_luafile() 823 call delete('Xlua_file') 824 call writefile(["str = 'hello'", "num = 123" ], 'Xlua_file') 825 call setfperm('Xlua_file', 'r-xr-xr-x') 826 827 luafile Xlua_file 828 call assert_equal('hello', luaeval('str')) 829 call assert_equal(123, luaeval('num')) 830 831 lua str, num = nil 832 call delete('Xlua_file') 833endfunc 834 835" Test :luafile % 836func Test_luafile_percent() 837 new Xlua_file 838 append 839 str, num = 'foo', 321.0 840 print(string.format('str=%s, num=%d', str, num)) 841. 842 w! 843 luafile % 844 let msg = split(execute('message'), "\n")[-1] 845 call assert_equal('str=foo, num=321', msg) 846 847 lua str, num = nil 848 call delete('Xlua_file') 849 bwipe! 850endfunc 851 852" Test :luafile with syntax error 853func Test_luafile_error() 854 new Xlua_file 855 call writefile(['nil = 0' ], 'Xlua_file') 856 call setfperm('Xlua_file', 'r-xr-xr-x') 857 858 call assert_fails('luafile Xlua_file', "Xlua_file:1: unexpected symbol near 'nil'") 859 860 call delete('Xlua_file') 861 bwipe! 862endfunc 863 864" Test for dealing with strings containing newlines and null character 865func Test_lua_string_with_newline() 866 let x = execute('lua print("Hello\nWorld")') 867 call assert_equal("\nHello\nWorld", x) 868 new 869 lua k = vim.buffer(vim.eval('bufnr()')) 870 lua k:insert("Hello\0World", 0) 871 call assert_equal(["Hello\nWorld", ''], getline(1, '$')) 872 close! 873endfunc 874 875func Test_lua_set_cursor() 876 " Check that setting the cursor position works. 877 new 878 call setline(1, ['first line', 'second line']) 879 normal gg 880 lua << trim EOF 881 w = vim.window() 882 w.line = 1 883 w.col = 5 884 EOF 885 call assert_equal([1, 5], [line('.'), col('.')]) 886 887 " Check that movement after setting cursor position keeps current column. 888 normal j 889 call assert_equal([2, 5], [line('.'), col('.')]) 890endfunc 891 892" Test for various heredoc syntax 893func Test_lua_heredoc() 894 lua << END 895vim.command('let s = "A"') 896END 897 lua << 898vim.command('let s ..= "B"') 899. 900 lua << trim END 901 vim.command('let s ..= "C"') 902 END 903 lua << trim 904 vim.command('let s ..= "D"') 905 . 906 lua << trim eof 907 vim.command('let s ..= "E"') 908 eof 909 call assert_equal('ABCDE', s) 910endfunc 911 912" vim: shiftwidth=2 sts=2 expandtab 913