1" Tests for Lua. 2 3if !has('lua') 4 finish 5endif 6 7" Check that switching to another buffer does not trigger ml_get error. 8func Test_command_new_no_ml_get_error() 9 new 10 let wincount = winnr('$') 11 call setline(1, ['one', 'two', 'three']) 12 luado vim.command("new") 13 call assert_equal(wincount + 1, winnr('$')) 14 %bwipe! 15endfunc 16 17" Test vim.command() 18func Test_command() 19 new 20 call setline(1, ['one', 'two', 'three']) 21 luado vim.command("1,2d_") 22 call assert_equal(['three'], getline(1, '$')) 23 bwipe! 24endfunc 25 26" Test vim.eval() 27func Test_eval() 28 " lua.eval with a number 29 lua v = vim.eval('123') 30 call assert_equal('number', luaeval('vim.type(v)')) 31 call assert_equal(123.0, luaeval('v')) 32 33 " lua.eval with a string 34 lua v = vim.eval('"abc"') 35 call assert_equal('string', luaeval('vim.type(v)')) 36 call assert_equal('abc', luaeval('v')) 37 38 " lua.eval with a list 39 lua v = vim.eval("['a']") 40 call assert_equal('list', luaeval('vim.type(v)')) 41 call assert_equal(['a'], luaeval('v')) 42 43 " lua.eval with a dict 44 lua v = vim.eval("{'a':'b'}") 45 call assert_equal('dict', luaeval('vim.type(v)')) 46 call assert_equal({'a':'b'}, luaeval('v')) 47 48 call assert_fails('lua v = vim.eval(nil)', 49 \ "[string \"vim chunk\"]:1: bad argument #1 to 'eval' (string expected, got nil)") 50 call assert_fails('lua v = vim.eval(true)', 51 \ "[string \"vim chunk\"]:1: bad argument #1 to 'eval' (string expected, got boolean)") 52 call assert_fails('lua v = vim.eval({})', 53 \ "[string \"vim chunk\"]:1: bad argument #1 to 'eval' (string expected, got table)") 54 call assert_fails('lua v = vim.eval(print)', 55 \ "[string \"vim chunk\"]:1: bad argument #1 to 'eval' (string expected, got function)") 56 call assert_fails('lua v = vim.eval(vim.buffer())', 57 \ "[string \"vim chunk\"]:1: bad argument #1 to 'eval' (string expected, got userdata)") 58 59 lua v = nil 60endfunc 61 62" Test vim.window() 63func Test_window() 64 e Xfoo2 65 new Xfoo1 66 67 " Window 1 (top window) contains Xfoo1 68 " Window 2 (bottom window) contains Xfoo2 69 call assert_equal('Xfoo1', luaeval('vim.window(1):buffer().name')) 70 call assert_equal('Xfoo2', luaeval('vim.window(2):buffer().name')) 71 72 " Window 3 does not exist so vim.window(3) should return nil 73 call assert_equal('nil', luaeval('tostring(vim.window(3))')) 74 75 %bwipe! 76endfunc 77 78" Test vim.window().height 79func Test_window_height() 80 new 81 lua vim.window().height = 2 82 call assert_equal(2, winheight(0)) 83 lua vim.window().height = vim.window().height + 1 84 call assert_equal(3, winheight(0)) 85 bwipe! 86endfunc 87 88" Test vim.window().width 89func Test_window_width() 90 vert new 91 lua vim.window().width = 2 92 call assert_equal(2, winwidth(0)) 93 lua vim.window().width = vim.window().width + 1 94 call assert_equal(3, winwidth(0)) 95 bwipe! 96endfunc 97 98" Test vim.window().line and vim.window.col 99func Test_window_line_col() 100 new 101 call setline(1, ['line1', 'line2', 'line3']) 102 lua vim.window().line = 2 103 lua vim.window().col = 4 104 call assert_equal([0, 2, 4, 0], getpos('.')) 105 lua vim.window().line = vim.window().line + 1 106 lua vim.window().col = vim.window().col - 1 107 call assert_equal([0, 3, 3, 0], getpos('.')) 108 109 call assert_fails('lua vim.window().line = 10', 110 \ '[string "vim chunk"]:1: line out of range') 111 bwipe! 112endfunc 113 114" Test setting the current window 115func Test_window_set_current() 116 new Xfoo1 117 lua w1 = vim.window() 118 new Xfoo2 119 lua w2 = vim.window() 120 121 call assert_equal('Xfoo2', bufname('%')) 122 lua w1() 123 call assert_equal('Xfoo1', bufname('%')) 124 lua w2() 125 call assert_equal('Xfoo2', bufname('%')) 126 127 lua w1, w2 = nil 128 %bwipe! 129endfunc 130 131" Test vim.window().buffer 132func Test_window_buffer() 133 new Xfoo1 134 lua w1 = vim.window() 135 lua b1 = w1.buffer() 136 new Xfoo2 137 lua w2 = vim.window() 138 lua b2 = w2.buffer() 139 140 lua b1() 141 call assert_equal('Xfoo1', bufname('%')) 142 lua b2() 143 call assert_equal('Xfoo2', bufname('%')) 144 145 lua b1, b2, w1, w2 = nil 146 %bwipe! 147endfunc 148 149" Test vim.window():previous() and vim.window():next() 150func Test_window_next_previous() 151 new Xfoo1 152 new Xfoo2 153 new Xfoo3 154 wincmd j 155 156 call assert_equal('Xfoo2', luaeval('vim.window().buffer().name')) 157 call assert_equal('Xfoo1', luaeval('vim.window():next():buffer().name')) 158 call assert_equal('Xfoo3', luaeval('vim.window():previous():buffer().name')) 159 160 %bwipe! 161endfunc 162 163" Test vim.window():isvalid() 164func Test_window_isvalid() 165 new Xfoo 166 lua w = vim.window() 167 call assert_true(luaeval('w:isvalid()')) 168 169 " FIXME: how to test the case when isvalid() returns v:false? 170 " isvalid() gives errors when the window is deleted. Is it a bug? 171 172 lua w = nil 173 bwipe! 174endfunc 175 176" Test vim.buffer() with and without argument 177func Test_buffer() 178 new Xfoo1 179 let bn1 = bufnr('%') 180 new Xfoo2 181 let bn2 = bufnr('%') 182 183 " Test vim.buffer() without argument. 184 call assert_equal('Xfoo2', luaeval("vim.buffer().name")) 185 186 " Test vim.buffer() with string argument. 187 call assert_equal('Xfoo1', luaeval("vim.buffer('Xfoo1').name")) 188 call assert_equal('Xfoo2', luaeval("vim.buffer('Xfoo2').name")) 189 190 " Test vim.buffer() with integer argument. 191 call assert_equal('Xfoo1', luaeval("vim.buffer(" . bn1 . ").name")) 192 call assert_equal('Xfoo2', luaeval("vim.buffer(" . bn2 . ").name")) 193 194 lua bn1, bn2 = nil 195 %bwipe! 196endfunc 197 198" Test vim.buffer().name and vim.buffer().fname 199func Test_buffer_name() 200 new 201 " FIXME: for an unnamed buffer, I would expect 202 " vim.buffer().name to give an empty string, but 203 " it returns 0. Is it a bug? 204 " so this assert_equal is commented out. 205 " call assert_equal('', luaeval('vim.buffer().name')) 206 bwipe! 207 208 new Xfoo 209 call assert_equal('Xfoo', luaeval('vim.buffer().name')) 210 call assert_equal(expand('%:p'), luaeval('vim.buffer().fname')) 211 bwipe! 212endfunc 213 214" Test vim.buffer().number 215func Test_buffer_number() 216 " All numbers in Lua are floating points number (no integers). 217 call assert_equal(bufnr('%'), float2nr(luaeval('vim.buffer().number'))) 218endfunc 219 220" Test inserting lines in buffer. 221func Test_buffer_insert() 222 new 223 lua vim.buffer()[1] = '3' 224 lua vim.buffer():insert('1', 0) 225 lua vim.buffer():insert('2', 1) 226 lua vim.buffer():insert('4', 10) 227 228 call assert_equal(['1', '2', '3', '4'], getline(1, '$')) 229 bwipe! 230endfunc 231 232" Test deleting line in buffer 233func Test_buffer_delete() 234 new 235 call setline(1, ['1', '2', '3']) 236 lua vim.buffer()[2] = nil 237 call assert_equal(['1', '3'], getline(1, '$')) 238 239 call assert_fails('lua vim.buffer()[3] = nil', 240 \ '[string "vim chunk"]:1: invalid line number') 241 bwipe! 242endfunc 243 244" Test #vim.buffer() i.e. number of lines in buffer 245func Test_buffer_number_lines() 246 new 247 call setline(1, ['a', 'b', 'c']) 248 call assert_equal(3.0, luaeval('#vim.buffer()')) 249 bwipe! 250endfunc 251 252" Test vim.buffer():next() and vim.buffer():previous() 253" Note that these functions get the next or previous buffers 254" but do not switch buffer. 255func Test_buffer_next_previous() 256 new Xfoo1 257 new Xfoo2 258 new Xfoo3 259 b Xfoo2 260 261 lua bn = vim.buffer():next() 262 lua bp = vim.buffer():previous() 263 264 call assert_equal('Xfoo2', luaeval('vim.buffer().name')) 265 call assert_equal('Xfoo1', luaeval('bp.name')) 266 call assert_equal('Xfoo3', luaeval('bn.name')) 267 268 call assert_equal('Xfoo2', bufname('%')) 269 270 lua bn() 271 call assert_equal('Xfoo3', luaeval('vim.buffer().name')) 272 call assert_equal('Xfoo3', bufname('%')) 273 274 lua bp() 275 call assert_equal('Xfoo1', luaeval('vim.buffer().name')) 276 call assert_equal('Xfoo1', bufname('%')) 277 278 lua bn, bp = nil 279 %bwipe! 280endfunc 281 282" Test vim.buffer():isvalid() 283func Test_buffer_isvalid() 284 new Xfoo 285 lua b = vim.buffer() 286 call assert_true(luaeval('b:isvalid()')) 287 288 " FIXME: how to test the case when isvalid() returns v:false? 289 " isvalid() gives errors when the buffer is wiped. Is it a bug? 290 291 lua b = nil 292 bwipe! 293endfunc 294 295func Test_list() 296 call assert_equal([], luaeval('vim.list()')) 297 298 let l = [] 299 lua l = vim.eval('l') 300 lua l:add(123) 301 lua l:add('abc') 302 lua l:add(true) 303 lua l:add(false) 304 lua l:add(vim.eval("[1, 2, 3]")) 305 lua l:add(vim.eval("{'a':1, 'b':2, 'c':3}")) 306 call assert_equal([123.0, 'abc', v:true, v:false, [1, 2, 3], {'a': 1, 'b': 2, 'c': 3}], l) 307 call assert_equal(6.0, luaeval('#l')) 308 call assert_match('^list: \%(0x\)\?\x\+$', luaeval('tostring(l)')) 309 310 lua l[0] = 124 311 lua l[4] = nil 312 lua l:insert('first') 313 lua l:insert('xx', 3) 314 call assert_equal(['first', 124.0, 'abc', 'xx', v:true, v:false, {'a': 1, 'b': 2, 'c': 3}], l) 315 316 lockvar 1 l 317 call assert_fails('lua l:add("x")', '[string "vim chunk"]:1: list is locked') 318 319 lua l = nil 320endfunc 321 322func Test_list_table() 323 " See :help lua-vim 324 " Non-numeric keys should not be used to initialize the list 325 " so say = 'hi' should be ignored. 326 lua t = {3.14, 'hello', false, true, say = 'hi'} 327 call assert_equal([3.14, 'hello', v:false, v:true], luaeval('vim.list(t)')) 328 lua t = nil 329 330 call assert_fails('lua vim.list(1)', '[string "vim chunk"]:1: table expected, got number') 331 call assert_fails('lua vim.list("x")', '[string "vim chunk"]:1: table expected, got string') 332 call assert_fails('lua vim.list(print)', '[string "vim chunk"]:1: table expected, got function') 333 call assert_fails('lua vim.list(true)', '[string "vim chunk"]:1: table expected, got boolean') 334endfunc 335 336" Test l() i.e. iterator on list 337func Test_list_iter() 338 lua l = vim.list():add('foo'):add('bar') 339 lua str = '' 340 lua for v in l() do str = str .. v end 341 call assert_equal('foobar', luaeval('str')) 342 343 lua str, l = nil 344endfunc 345 346func Test_recursive_list() 347 lua l = vim.list():add(1):add(2) 348 lua l = l:add(l) 349 350 call assert_equal(1.0, luaeval('l[0]')) 351 call assert_equal(2.0, luaeval('l[1]')) 352 353 call assert_equal(1.0, luaeval('l[2][0]')) 354 call assert_equal(2.0, luaeval('l[2][1]')) 355 356 call assert_equal(1.0, luaeval('l[2][2][0]')) 357 call assert_equal(2.0, luaeval('l[2][2][1]')) 358 359 call assert_equal('[1.0, 2.0, [...]]', string(luaeval('l'))) 360 361 call assert_match('^list: \%(0x\)\?\x\+$', luaeval('tostring(l)')) 362 call assert_equal(luaeval('tostring(l)'), luaeval('tostring(l[2])')) 363 364 call assert_equal(luaeval('l'), luaeval('l[2]')) 365 call assert_equal(luaeval('l'), luaeval('l[2][2]')) 366 367 lua l = nil 368endfunc 369 370func Test_dict() 371 call assert_equal({}, luaeval('vim.dict()')) 372 373 let d = {} 374 lua d = vim.eval('d') 375 lua d[0] = 123 376 lua d[1] = "abc" 377 lua d[2] = true 378 lua d[3] = false 379 lua d[4] = vim.eval("[1, 2, 3]") 380 lua d[5] = vim.eval("{'a':1, 'b':2, 'c':3}") 381 call assert_equal({'0':123.0, '1':'abc', '2':v:true, '3':v:false, '4': [1, 2, 3], '5': {'a':1, 'b':2, 'c':3}}, d) 382 call assert_equal(6.0, luaeval('#d')) 383 call assert_match('^dict: \%(0x\)\?\x\+$', luaeval('tostring(d)')) 384 385 call assert_equal('abc', luaeval('d[1]')) 386 387 lua d[0] = 124 388 lua d[4] = nil 389 call assert_equal({'0':124.0, '1':'abc', '2':v:true, '3':v:false, '5': {'a':1, 'b':2, 'c':3}}, d) 390 391 lockvar 1 d 392 call assert_fails('lua d[6] = 1', '[string "vim chunk"]:1: dict is locked') 393 394 lua d = nil 395endfunc 396 397func Test_dict_table() 398 lua t = {key1 = 'x', key2 = 3.14, key3 = true, key4 = false} 399 call assert_equal({'key1': 'x', 'key2': 3.14, 'key3': v:true, 'key4': v:false}, 400 \ luaeval('vim.dict(t)')) 401 402 " Same example as in :help lua-vim. 403 lua t = {math.pi, false, say = 'hi'} 404 " FIXME: commented out as it currently does not work as documented: 405 " Expected {'say': 'hi'} 406 " but got {'1': 3.141593, '2': v:false, 'say': 'hi'} 407 " Is the documentation or the code wrong? 408 "call assert_equal({'say' : 'hi'}, luaeval('vim.dict(t)')) 409 lua t = nil 410 411 call assert_fails('lua vim.dict(1)', '[string "vim chunk"]:1: table expected, got number') 412 call assert_fails('lua vim.dict("x")', '[string "vim chunk"]:1: table expected, got string') 413 call assert_fails('lua vim.dict(print)', '[string "vim chunk"]:1: table expected, got function') 414 call assert_fails('lua vim.dict(true)', '[string "vim chunk"]:1: table expected, got boolean') 415endfunc 416 417" Test d() i.e. iterator on dictionary 418func Test_dict_iter() 419 let d = {'a': 1, 'b':2} 420 lua d = vim.eval('d') 421 lua str = '' 422 lua for k,v in d() do str = str .. k ..':' .. v .. ',' end 423 call assert_equal('a:1,b:2,', luaeval('str')) 424 425 lua str, d = nil 426endfunc 427 428func Test_funcref() 429 function I(x) 430 return a:x 431 endfunction 432 let R = function('I') 433 lua i1 = vim.funcref"I" 434 lua i2 = vim.eval"R" 435 lua msg = "funcref|test|" .. (#i2(i1) == #i1(i2) and "OK" or "FAIL") 436 lua msg = vim.funcref"tr"(msg, "|", " ") 437 call assert_equal("funcref test OK", luaeval('msg')) 438 439 " dict funcref 440 function Mylen() dict 441 return len(self.data) 442 endfunction 443 let l = [0, 1, 2, 3] 444 let mydict = {'data': l} 445 lua d = vim.eval"mydict" 446 lua d.len = vim.funcref"Mylen" -- assign d as 'self' 447 lua res = (d.len() == vim.funcref"len"(vim.eval"l")) and "OK" or "FAIL" 448 call assert_equal("OK", luaeval('res')) 449 450 lua i1, i2, msg, d, res = nil 451endfunc 452 453" Test vim.type() 454func Test_type() 455 " The following values are identical to Lua's type function. 456 call assert_equal('string', luaeval('vim.type("foo")')) 457 call assert_equal('number', luaeval('vim.type(1)')) 458 call assert_equal('number', luaeval('vim.type(1.2)')) 459 call assert_equal('function', luaeval('vim.type(print)')) 460 call assert_equal('table', luaeval('vim.type({})')) 461 call assert_equal('boolean', luaeval('vim.type(true)')) 462 call assert_equal('boolean', luaeval('vim.type(false)')) 463 call assert_equal('nil', luaeval('vim.type(nil)')) 464 465 " The following values are specific to Vim. 466 call assert_equal('window', luaeval('vim.type(vim.window())')) 467 call assert_equal('buffer', luaeval('vim.type(vim.buffer())')) 468 call assert_equal('list', luaeval('vim.type(vim.list())')) 469 call assert_equal('dict', luaeval('vim.type(vim.dict())')) 470 call assert_equal('funcref', luaeval('vim.type(vim.funcref("Test_type"))')) 471endfunc 472 473" Test vim.open() 474func Test_open() 475 call assert_notmatch('XOpen', execute('ls')) 476 477 " Open a buffer XOpen1, but do not jump to it. 478 lua b = vim.open('XOpen1') 479 call assert_equal('XOpen1', luaeval('b.name')) 480 call assert_equal('', bufname('%')) 481 482 call assert_match('XOpen1', execute('ls')) 483 call assert_notequal('XOpen2', bufname('%')) 484 485 " Open a buffer XOpen2 and jump to it. 486 lua b = vim.open('XOpen2')() 487 call assert_equal('XOpen2', luaeval('b.name')) 488 call assert_equal('XOpen2', bufname('%')) 489 490 lua b = nil 491 %bwipe! 492endfunc 493 494" Test vim.line() 495func Test_line() 496 new 497 call setline(1, ['first line', 'second line']) 498 1 499 call assert_equal('first line', luaeval('vim.line()')) 500 2 501 call assert_equal('second line', luaeval('vim.line()')) 502 bwipe! 503endfunc 504 505" Test vim.beep() 506func Test_beep() 507 call assert_beeps('lua vim.beep()') 508endfunc 509 510" Test errors in luaeval() 511func Test_luaeval_error() 512 " Compile error 513 call assert_fails("call luaeval('-nil')", 514 \ '[string "luaeval"]:1: attempt to perform arithmetic on a nil value') 515 call assert_fails("call luaeval(']')", 516 \ "[string \"luaeval\"]:1: unexpected symbol near ']'") 517endfunc 518 519" Test :luafile foo.lua 520func Test_luafile() 521 call delete('Xlua_file') 522 call writefile(["str = 'hello'", "num = 123.0" ], 'Xlua_file') 523 call setfperm('Xlua_file', 'r-xr-xr-x') 524 525 luafile Xlua_file 526 call assert_equal('hello', luaeval('str')) 527 call assert_equal(123.0, luaeval('num')) 528 529 lua str, num = nil 530 call delete('Xlua_file') 531endfunc 532 533" Test :luafile % 534func Test_luafile_percent() 535 new Xlua_file 536 append 537 str, num = 'foo', 321.0 538 print(string.format('str=%s, num=%d', str, num)) 539. 540 w! 541 luafile % 542 let msg = split(execute('message'), "\n")[-1] 543 call assert_equal('str=foo, num=321', msg) 544 545 lua str, num = nil 546 call delete('Xlua_file') 547 bwipe! 548endfunc 549 550" Test :luafile with syntax error 551func Test_luafile_error() 552 new Xlua_file 553 call writefile(['nil = 0' ], 'Xlua_file') 554 call setfperm('Xlua_file', 'r-xr-xr-x') 555 556 call assert_fails('luafile Xlua_file', "Xlua_file:1: unexpected symbol near 'nil'") 557 558 call delete('Xlua_file') 559 bwipe! 560endfunc 561