Add v:lua.func() vimL syntax for calling lua

Also simplify error messages when calling lua from vimL.
This commit is contained in:
Björn Linse
2019-10-30 20:53:09 +01:00
parent 18096631b1
commit dab40f43b1
10 changed files with 442 additions and 217 deletions

View File

@@ -155,41 +155,41 @@ describe('luaeval(vim.api.…)', function()
it('errors out correctly when working with API', function()
-- Conversion errors
eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Cannot convert given lua type',
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Cannot convert given lua type',
exc_exec([[call luaeval("vim.api.nvim__id(vim.api.nvim__id)")]]))
eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Cannot convert given lua table',
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Cannot convert given lua table',
exc_exec([[call luaeval("vim.api.nvim__id({1, foo=42})")]]))
eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Cannot convert given lua type',
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Cannot convert given lua type',
exc_exec([[call luaeval("vim.api.nvim__id({42, vim.api.nvim__id})")]]))
-- Errors in number of arguments
eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected 1 argument',
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected 1 argument',
exc_exec([[call luaeval("vim.api.nvim__id()")]]))
eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected 1 argument',
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected 1 argument',
exc_exec([[call luaeval("vim.api.nvim__id(1, 2)")]]))
eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected 2 arguments',
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected 2 arguments',
exc_exec([[call luaeval("vim.api.nvim_set_var(1, 2, 3)")]]))
-- Error in argument types
eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected lua string',
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua string',
exc_exec([[call luaeval("vim.api.nvim_set_var(1, 2)")]]))
eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected lua number',
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua number',
exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 'test', 1, false)")]]))
eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Number is not integral',
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Number is not integral',
exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 1.5, 1, false)")]]))
eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected lua table',
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua table',
exc_exec([[call luaeval("vim.api.nvim__id_float('test')")]]))
eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Unexpected type',
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Unexpected type',
exc_exec([[call luaeval("vim.api.nvim__id_float({[vim.type_idx]=vim.types.dictionary})")]]))
eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected lua table',
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua table',
exc_exec([[call luaeval("vim.api.nvim__id_array(1)")]]))
eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Unexpected type',
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Unexpected type',
exc_exec([[call luaeval("vim.api.nvim__id_array({[vim.type_idx]=vim.types.dictionary})")]]))
eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected lua table',
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua table',
exc_exec([[call luaeval("vim.api.nvim__id_dictionary(1)")]]))
eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Unexpected type',
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Unexpected type',
exc_exec([[call luaeval("vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.array})")]]))
-- TODO: check for errors with Tabpage argument
-- TODO: check for errors with Window argument

View File

@@ -13,6 +13,7 @@ local source = helpers.source
local dedent = helpers.dedent
local command = helpers.command
local exc_exec = helpers.exc_exec
local pcall_err = helpers.pcall_err
local write_file = helpers.write_file
local redir_exec = helpers.redir_exec
local curbufmeths = helpers.curbufmeths
@@ -42,16 +43,16 @@ describe(':lua command', function()
eq({'', 'ETTS', 'TTSE', 'STTE'}, curbufmeths.get_lines(0, 100, false))
end)
it('throws catchable errors', function()
eq([[Vim(lua):E5104: Error while creating lua chunk: [string "<VimL compiled string>"]:1: unexpected symbol near ')']],
exc_exec('lua ()'))
eq([[Vim(lua):E5105: Error while calling lua chunk: [string "<VimL compiled string>"]:1: TEST]],
eq([[Vim(lua):E5107: Error loading lua [string ":lua"]:1: unexpected symbol near ')']],
pcall_err(command, 'lua ()'))
eq([[Vim(lua):E5108: Error executing lua [string ":lua"]:1: TEST]],
exc_exec('lua error("TEST")'))
eq([[Vim(lua):E5105: Error while calling lua chunk: [string "<VimL compiled string>"]:1: Invalid buffer id]],
eq([[Vim(lua):E5108: Error executing lua [string ":lua"]:1: Invalid buffer id]],
exc_exec('lua vim.api.nvim_buf_set_lines(-10, 1, 1, false, {"TEST"})'))
eq({''}, curbufmeths.get_lines(0, 100, false))
end)
it('works with NULL errors', function()
eq([=[Vim(lua):E5105: Error while calling lua chunk: [NULL]]=],
eq([=[Vim(lua):E5108: Error executing lua [NULL]]=],
exc_exec('lua error(nil)'))
end)
it('accepts embedded NLs without heredoc', function()
@@ -74,7 +75,7 @@ describe(':lua command', function()
it('works with long strings', function()
local s = ('x'):rep(100500)
eq('\nE5104: Error while creating lua chunk: [string "<VimL compiled string>"]:1: unfinished string near \'<eof>\'', redir_exec(('lua vim.api.nvim_buf_set_lines(1, 1, 2, false, {"%s})'):format(s)))
eq('\nE5107: Error loading lua [string ":lua"]:1: unfinished string near \'<eof>\'', redir_exec(('lua vim.api.nvim_buf_set_lines(1, 1, 2, false, {"%s})'):format(s)))
eq({''}, curbufmeths.get_lines(0, -1, false))
eq('', redir_exec(('lua vim.api.nvim_buf_set_lines(1, 1, 2, false, {"%s"})'):format(s)))
@@ -82,7 +83,7 @@ describe(':lua command', function()
end)
it('can show multiline error messages', function()
local screen = Screen.new(50,10)
local screen = Screen.new(40,10)
screen:attach()
screen:set_default_attr_ids({
[1] = {bold = true, foreground = Screen.colors.Blue1},
@@ -92,51 +93,51 @@ describe(':lua command', function()
})
feed(':lua error("fail\\nmuch error\\nsuch details")<cr>')
screen:expect([[
|
{1:~ }|
{1:~ }|
{1:~ }|
{2: }|
{3:E5105: Error while calling lua chunk: [string "<Vi}|
{3:mL compiled string>"]:1: fail} |
{3:much error} |
{3:such details} |
{4:Press ENTER or type command to continue}^ |
]])
screen:expect{grid=[[
|
{1:~ }|
{1:~ }|
{1:~ }|
{2: }|
{3:E5108: Error executing lua [string ":lua}|
{3:"]:1: fail} |
{3:much error} |
{3:such details} |
{4:Press ENTER or type command to continue}^ |
]]}
feed('<cr>')
screen:expect([[
^ |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
|
]])
eq('E5105: Error while calling lua chunk: [string "<VimL compiled string>"]:1: fail\nmuch error\nsuch details', eval('v:errmsg'))
screen:expect{grid=[[
^ |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
|
]]}
eq('E5108: Error executing lua [string ":lua"]:1: fail\nmuch error\nsuch details', eval('v:errmsg'))
local status, err = pcall(command,'lua error("some error\\nin a\\nAPI command")')
local expected = 'Vim(lua):E5105: Error while calling lua chunk: [string "<VimL compiled string>"]:1: some error\nin a\nAPI command'
local expected = 'Vim(lua):E5108: Error executing lua [string ":lua"]:1: some error\nin a\nAPI command'
eq(false, status)
eq(expected, string.sub(err, -string.len(expected)))
feed(':messages<cr>')
screen:expect([[
|
{1:~ }|
{1:~ }|
{1:~ }|
{2: }|
{3:E5105: Error while calling lua chunk: [string "<Vi}|
{3:mL compiled string>"]:1: fail} |
{3:much error} |
{3:such details} |
{4:Press ENTER or type command to continue}^ |
]])
screen:expect{grid=[[
|
{1:~ }|
{1:~ }|
{1:~ }|
{2: }|
{3:E5108: Error executing lua [string ":lua}|
{3:"]:1: fail} |
{3:much error} |
{3:such details} |
{4:Press ENTER or type command to continue}^ |
]]}
end)
end)
@@ -167,13 +168,13 @@ describe(':luado command', function()
eq({''}, curbufmeths.get_lines(0, -1, false))
end)
it('fails on errors', function()
eq([[Vim(luado):E5109: Error while creating lua chunk: [string "<VimL compiled string>"]:1: unexpected symbol near ')']],
eq([[Vim(luado):E5109: Error loading lua: [string ":luado"]:1: unexpected symbol near ')']],
exc_exec('luado ()'))
eq([[Vim(luado):E5111: Error while calling lua function: [string "<VimL compiled string>"]:1: attempt to perform arithmetic on global 'liness' (a nil value)]],
eq([[Vim(luado):E5111: Error calling lua: [string ":luado"]:1: attempt to perform arithmetic on global 'liness' (a nil value)]],
exc_exec('luado return liness + 1'))
end)
it('works with NULL errors', function()
eq([=[Vim(luado):E5111: Error while calling lua function: [NULL]]=],
eq([=[Vim(luado):E5111: Error calling lua: [NULL]]=],
exc_exec('luado error(nil)'))
end)
it('fails in sandbox when needed', function()
@@ -185,7 +186,7 @@ describe(':luado command', function()
it('works with long strings', function()
local s = ('x'):rep(100500)
eq('\nE5109: Error while creating lua chunk: [string "<VimL compiled string>"]:1: unfinished string near \'<eof>\'', redir_exec(('luado return "%s'):format(s)))
eq('\nE5109: Error loading lua: [string ":luado"]:1: unfinished string near \'<eof>\'', redir_exec(('luado return "%s'):format(s)))
eq({''}, curbufmeths.get_lines(0, -1, false))
eq('', redir_exec(('luado return "%s"'):format(s)))

View File

@@ -1,13 +1,17 @@
-- Test suite for testing luaeval() function
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local redir_exec = helpers.redir_exec
local pcall_err = helpers.pcall_err
local exc_exec = helpers.exc_exec
local exec_lua = helpers.exec_lua
local command = helpers.command
local meths = helpers.meths
local funcs = helpers.funcs
local clear = helpers.clear
local eval = helpers.eval
local feed = helpers.feed
local NIL = helpers.NIL
local eq = helpers.eq
@@ -186,9 +190,9 @@ describe('luaeval()', function()
exc_exec('call luaeval("{1, foo=2}")'))
eq("Vim(call):E5101: Cannot convert given lua type",
exc_exec('call luaeval("vim.api.nvim_buf_get_lines")'))
startswith("Vim(call):E5107: Error while creating lua chunk for luaeval(): ",
startswith("Vim(call):E5107: Error loading lua [string \"luaeval()\"]:",
exc_exec('call luaeval("1, 2, 3")'))
startswith("Vim(call):E5108: Error while calling lua chunk for luaeval(): ",
startswith("Vim(call):E5108: Error executing lua [string \"luaeval()\"]:",
exc_exec('call luaeval("(nil)()")'))
eq("Vim(call):E5101: Cannot convert given lua type",
exc_exec('call luaeval("{42, vim.api}")'))
@@ -237,19 +241,99 @@ describe('luaeval()', function()
it('errors out correctly when doing incorrect things in lua', function()
-- Conversion errors
eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: attempt to call field \'xxx_nonexistent_key_xxx\' (a nil value)',
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: attempt to call field \'xxx_nonexistent_key_xxx\' (a nil value)',
exc_exec([[call luaeval("vim.xxx_nonexistent_key_xxx()")]]))
eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: ERROR',
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: ERROR',
exc_exec([[call luaeval("error('ERROR')")]]))
eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [NULL]',
eq('Vim(call):E5108: Error executing lua [NULL]',
exc_exec([[call luaeval("error(nil)")]]))
end)
it('does not leak memory when called with too long line',
function()
local s = ('x'):rep(65536)
eq('Vim(call):E5107: Error while creating lua chunk for luaeval(): [string "<VimL compiled string>"]:1: unexpected symbol near \')\'',
eq('Vim(call):E5107: Error loading lua [string "luaeval()"]:1: unexpected symbol near \')\'',
exc_exec([[call luaeval("(']] .. s ..[[' + )")]]))
eq(s, funcs.luaeval('"' .. s .. '"'))
end)
end)
describe('v:lua', function()
before_each(function()
exec_lua([[
function _G.foo(a,b,n)
_G.val = n
return a+b
end
mymod = {}
function mymod.noisy(name)
vim.api.nvim_set_current_line("hey "..name)
end
function mymod.crashy()
nonexistent()
end
function mymod.omni(findstart, base)
if findstart == 1 then
return 5
else
if base == 'st' then
return {'stuff', 'steam', 'strange things'}
end
end
end
vim.api.nvim_buf_set_option(0, 'omnifunc', 'v:lua.mymod.omni')
]])
end)
it('works in expressions', function()
eq(7, eval('v:lua.foo(3,4,v:null)'))
eq(true, exec_lua([[return _G.val == vim.NIL]]))
eq(NIL, eval('v:lua.mymod.noisy("eval")'))
eq("hey eval", meths.get_current_line())
eq("Vim:E5108: Error executing lua [string \"<nvim>\"]:10: attempt to call global 'nonexistent' (a nil value)",
pcall_err(eval, 'v:lua.mymod.crashy()'))
end)
it('works in :call', function()
command(":call v:lua.mymod.noisy('command')")
eq("hey command", meths.get_current_line())
eq("Vim(call):E5108: Error executing lua [string \"<nvim>\"]:10: attempt to call global 'nonexistent' (a nil value)",
pcall_err(command, 'call v:lua.mymod.crashy()'))
end)
it('works in func options', function()
local screen = Screen.new(60, 8)
screen:set_default_attr_ids({
[1] = {bold = true, foreground = Screen.colors.Blue1},
[2] = {background = Screen.colors.WebGray},
[3] = {background = Screen.colors.LightMagenta},
[4] = {bold = true},
[5] = {bold = true, foreground = Screen.colors.SeaGreen4},
})
screen:attach()
feed('isome st<c-x><c-o>')
screen:expect{grid=[[
some stuff^ |
{1:~ }{2: stuff }{1: }|
{1:~ }{3: steam }{1: }|
{1:~ }{3: strange things }{1: }|
{1:~ }|
{1:~ }|
{1:~ }|
{4:-- Omni completion (^O^N^P) }{5:match 1 of 3} |
]]}
end)
it('throw errors for invalid use', function()
eq('Vim(let):E15: Invalid expression: v:lua.func', pcall_err(command, "let g:Func = v:lua.func"))
eq('Vim(let):E15: Invalid expression: v:lua', pcall_err(command, "let g:Func = v:lua"))
eq("Vim(let):E15: Invalid expression: v:['lua']", pcall_err(command, "let g:Func = v:['lua']"))
eq("Vim:E15: Invalid expression: v:['lua'].foo()", pcall_err(eval, "v:['lua'].foo()"))
eq("Vim(call):E461: Illegal variable name: v:['lua']", pcall_err(command, "call v:['lua'].baar()"))
eq("Vim(let):E46: Cannot change read-only variable \"v:['lua']\"", pcall_err(command, "let v:['lua'] = 'xx'"))
eq("Vim(let):E46: Cannot change read-only variable \"v:lua\"", pcall_err(command, "let v:lua = 'xx'"))
end)
end)

View File

@@ -54,11 +54,12 @@ describe('print', function()
v_tblout = setmetatable({}, meta_tblout)
]])
eq('', redir_exec('luafile ' .. fname))
eq('\nE5105: Error while calling lua chunk: E5114: Error while converting print argument #2: [NULL]',
-- TODO(bfredl): these look weird, print() should not use "E5114:" style errors..
eq('\nE5108: Error executing lua E5114: Error while converting print argument #2: [NULL]',
redir_exec('lua print("foo", v_nilerr, "bar")'))
eq('\nE5105: Error while calling lua chunk: E5114: Error while converting print argument #2: Xtest-functional-lua-overrides-luafile:2: abc',
eq('\nE5108: Error executing lua E5114: Error while converting print argument #2: Xtest-functional-lua-overrides-luafile:2: abc',
redir_exec('lua print("foo", v_abcerr, "bar")'))
eq('\nE5105: Error while calling lua chunk: E5114: Error while converting print argument #2: <Unknown error: lua_tolstring returned NULL for tostring result>',
eq('\nE5108: Error executing lua E5114: Error while converting print argument #2: <Unknown error: lua_tolstring returned NULL for tostring result>',
redir_exec('lua print("foo", v_tblout, "bar")'))
end)
it('prints strings with NULs and NLs correctly', function()
@@ -156,7 +157,8 @@ describe('debug.debug', function()
lua_debug> ^ |
]])
feed('<C-c>')
screen:expect([[
screen:expect{grid=[[
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
@@ -167,11 +169,10 @@ describe('debug.debug', function()
lua_debug> print("TEST") |
TEST |
|
{E:E5105: Error while calling lua chunk: [string "<VimL }|
{E:compiled string>"]:5: attempt to perform arithmetic o}|
{E:n local 'a' (a nil value)} |
{E:E5108: Error executing lua [string ":lua"]:5: attempt}|
{E: to perform arithmetic on local 'a' (a nil value)} |
Interrupt: {cr:Press ENTER or type command to continue}^ |
]])
]]}
feed('<C-l>:lua Test()\n')
screen:expect([[
{0:~ }|
@@ -190,7 +191,8 @@ describe('debug.debug', function()
lua_debug> ^ |
]])
feed('\n')
screen:expect([[
screen:expect{grid=[[
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
@@ -201,11 +203,10 @@ describe('debug.debug', function()
{0:~ }|
nil |
lua_debug> |
{E:E5105: Error while calling lua chunk: [string "<VimL }|
{E:compiled string>"]:5: attempt to perform arithmetic o}|
{E:n local 'a' (a nil value)} |
{E:E5108: Error executing lua [string ":lua"]:5: attempt}|
{E: to perform arithmetic on local 'a' (a nil value)} |
{cr:Press ENTER or type command to continue}^ |
]])
]]}
end)
it("can be safely exited with 'cont'", function()