mirror of
https://github.com/neovim/neovim.git
synced 2026-07-22 09:01:45 +00:00
Merge #4411 from ZyX-I/luaviml'/lua
This commit is contained in:
@@ -10,6 +10,7 @@ local insert = helpers.insert
|
||||
local NIL = helpers.NIL
|
||||
local meth_pcall = helpers.meth_pcall
|
||||
local command = helpers.command
|
||||
local bufmeths = helpers.bufmeths
|
||||
|
||||
describe('api/buf', function()
|
||||
before_each(clear)
|
||||
@@ -121,6 +122,15 @@ describe('api/buf', function()
|
||||
local get_lines, set_lines = curbufmeths.get_lines, curbufmeths.set_lines
|
||||
local line_count = curbufmeths.line_count
|
||||
|
||||
it('fails correctly when input is not valid', function()
|
||||
eq(1, curbufmeths.get_number())
|
||||
local err, emsg = pcall(bufmeths.set_lines, 1, 1, 2, false, {'b\na'})
|
||||
eq(false, err)
|
||||
local exp_emsg = 'String cannot contain newlines'
|
||||
-- Expected {filename}:{lnum}: {exp_emsg}
|
||||
eq(': ' .. exp_emsg, emsg:sub(-#exp_emsg - 2))
|
||||
end)
|
||||
|
||||
it('has correct line_count when inserting and deleting', function()
|
||||
eq(1, line_count())
|
||||
set_lines(-1, -1, true, {'line'})
|
||||
|
||||
@@ -337,6 +337,17 @@ describe('api', function()
|
||||
eq('\128\253\44', helpers.nvim('replace_termcodes',
|
||||
'<LeftMouse>', true, true, true))
|
||||
end)
|
||||
|
||||
it('does not crash when transforming an empty string', function()
|
||||
-- Actually does not test anything, because current code will use NULL for
|
||||
-- an empty string.
|
||||
--
|
||||
-- Problem here is that if String argument has .data in allocated memory
|
||||
-- then `return str` in vim_replace_termcodes body will make Neovim free
|
||||
-- `str.data` twice: once when freeing arguments, then when freeing return
|
||||
-- value.
|
||||
eq('', meths.replace_termcodes('', true, true, true))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('nvim_feedkeys', function()
|
||||
|
||||
@@ -9,6 +9,7 @@ local funcs = helpers.funcs
|
||||
local request = helpers.request
|
||||
local NIL = helpers.NIL
|
||||
local meth_pcall = helpers.meth_pcall
|
||||
local meths = helpers.meths
|
||||
local command = helpers.command
|
||||
|
||||
-- check if str is visible at the beginning of some line
|
||||
@@ -55,6 +56,12 @@ describe('api/win', function()
|
||||
eq('typing\n some dumb text', curbuf_contents())
|
||||
end)
|
||||
|
||||
it('does not leak memory when using invalid window ID with invalid pos',
|
||||
function()
|
||||
eq({false, 'Invalid window id'},
|
||||
meth_pcall(meths.win_set_cursor, 1, {"b\na"}))
|
||||
end)
|
||||
|
||||
it('updates the screen, and also when the window is unfocused', function()
|
||||
insert("prologue")
|
||||
feed('100o<esc>')
|
||||
|
||||
@@ -566,7 +566,7 @@ local function get_pathsep()
|
||||
return funcs.fnamemodify('.', ':p'):sub(-1)
|
||||
end
|
||||
|
||||
local M = {
|
||||
local module = {
|
||||
prepend_argv = prepend_argv,
|
||||
clear = clear,
|
||||
connect = connect,
|
||||
@@ -641,5 +641,5 @@ return function(after_each)
|
||||
check_cores('build/bin/nvim')
|
||||
end)
|
||||
end
|
||||
return M
|
||||
return module
|
||||
end
|
||||
|
||||
204
test/functional/lua/api_spec.lua
Normal file
204
test/functional/lua/api_spec.lua
Normal file
@@ -0,0 +1,204 @@
|
||||
-- Test suite for testing interactions with API bindings
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
|
||||
local exc_exec = helpers.exc_exec
|
||||
local funcs = helpers.funcs
|
||||
local clear = helpers.clear
|
||||
local eval = helpers.eval
|
||||
local NIL = helpers.NIL
|
||||
local eq = helpers.eq
|
||||
|
||||
before_each(clear)
|
||||
|
||||
describe('luaeval(vim.api.…)', function()
|
||||
describe('with channel_id and buffer handle', function()
|
||||
describe('nvim_buf_get_lines', function()
|
||||
it('works', function()
|
||||
funcs.setline(1, {"abc", "def", "a\nb", "ttt"})
|
||||
eq({{_TYPE={}, _VAL={'a\nb'}}},
|
||||
funcs.luaeval('vim.api.nvim_buf_get_lines(1, 2, 3, false)'))
|
||||
end)
|
||||
end)
|
||||
describe('nvim_buf_set_lines', function()
|
||||
it('works', function()
|
||||
funcs.setline(1, {"abc", "def", "a\nb", "ttt"})
|
||||
eq(NIL, funcs.luaeval('vim.api.nvim_buf_set_lines(1, 1, 2, false, {"b\\0a"})'))
|
||||
eq({'abc', {_TYPE={}, _VAL={'b\na'}}, {_TYPE={}, _VAL={'a\nb'}}, 'ttt'},
|
||||
funcs.luaeval('vim.api.nvim_buf_get_lines(1, 0, 4, false)'))
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
describe('with errors', function()
|
||||
it('transforms API error from nvim_buf_set_lines into lua error', function()
|
||||
funcs.setline(1, {"abc", "def", "a\nb", "ttt"})
|
||||
eq({false, 'String cannot contain newlines'},
|
||||
funcs.luaeval('{pcall(vim.api.nvim_buf_set_lines, 1, 1, 2, false, {"b\\na"})}'))
|
||||
end)
|
||||
|
||||
it('transforms API error from nvim_win_set_cursor into lua error', function()
|
||||
eq({false, 'Argument "pos" must be a [row, col] array'},
|
||||
funcs.luaeval('{pcall(vim.api.nvim_win_set_cursor, 0, {1, 2, 3})}'))
|
||||
-- Used to produce a memory leak due to a bug in nvim_win_set_cursor
|
||||
eq({false, 'Invalid window id'},
|
||||
funcs.luaeval('{pcall(vim.api.nvim_win_set_cursor, -1, {1, 2, 3})}'))
|
||||
end)
|
||||
|
||||
it('transforms API error from nvim_win_set_cursor + same array as in first test into lua error',
|
||||
function()
|
||||
eq({false, 'Argument "pos" must be a [row, col] array'},
|
||||
funcs.luaeval('{pcall(vim.api.nvim_win_set_cursor, 0, {"b\\na"})}'))
|
||||
end)
|
||||
end)
|
||||
|
||||
it('correctly evaluates API code which calls luaeval', function()
|
||||
local str = (([===[vim.api.nvim_eval([==[
|
||||
luaeval('vim.api.nvim_eval([=[
|
||||
luaeval("vim.api.nvim_eval([[
|
||||
luaeval(1)
|
||||
]])")
|
||||
]=])')
|
||||
]==])]===]):gsub('\n', ' '))
|
||||
eq(1, funcs.luaeval(str))
|
||||
end)
|
||||
|
||||
it('correctly converts from API objects', function()
|
||||
eq(1, funcs.luaeval('vim.api.nvim_eval("1")'))
|
||||
eq('1', funcs.luaeval([[vim.api.nvim_eval('"1"')]]))
|
||||
eq({}, funcs.luaeval('vim.api.nvim_eval("[]")'))
|
||||
eq({}, funcs.luaeval('vim.api.nvim_eval("{}")'))
|
||||
eq(1, funcs.luaeval('vim.api.nvim_eval("1.0")'))
|
||||
eq(true, funcs.luaeval('vim.api.nvim_eval("v:true")'))
|
||||
eq(false, funcs.luaeval('vim.api.nvim_eval("v:false")'))
|
||||
eq(NIL, funcs.luaeval('vim.api.nvim_eval("v:null")'))
|
||||
|
||||
eq(0, eval([[type(luaeval('vim.api.nvim_eval("1")'))]]))
|
||||
eq(1, eval([[type(luaeval('vim.api.nvim_eval("''1''")'))]]))
|
||||
eq(3, eval([[type(luaeval('vim.api.nvim_eval("[]")'))]]))
|
||||
eq(4, eval([[type(luaeval('vim.api.nvim_eval("{}")'))]]))
|
||||
eq(5, eval([[type(luaeval('vim.api.nvim_eval("1.0")'))]]))
|
||||
eq(6, eval([[type(luaeval('vim.api.nvim_eval("v:true")'))]]))
|
||||
eq(6, eval([[type(luaeval('vim.api.nvim_eval("v:false")'))]]))
|
||||
eq(7, eval([[type(luaeval('vim.api.nvim_eval("v:null")'))]]))
|
||||
|
||||
eq({foo=42}, funcs.luaeval([[vim.api.nvim_eval('{"foo": 42}')]]))
|
||||
eq({42}, funcs.luaeval([[vim.api.nvim_eval('[42]')]]))
|
||||
|
||||
eq({foo={bar=42}, baz=50}, funcs.luaeval([[vim.api.nvim_eval('{"foo": {"bar": 42}, "baz": 50}')]]))
|
||||
eq({{42}, {}}, funcs.luaeval([=[vim.api.nvim_eval('[[42], []]')]=]))
|
||||
end)
|
||||
|
||||
it('correctly converts to API objects', function()
|
||||
eq(1, funcs.luaeval('vim.api.nvim__id(1)'))
|
||||
eq('1', funcs.luaeval('vim.api.nvim__id("1")'))
|
||||
eq({1}, funcs.luaeval('vim.api.nvim__id({1})'))
|
||||
eq({foo=1}, funcs.luaeval('vim.api.nvim__id({foo=1})'))
|
||||
eq(1.5, funcs.luaeval('vim.api.nvim__id(1.5)'))
|
||||
eq(true, funcs.luaeval('vim.api.nvim__id(true)'))
|
||||
eq(false, funcs.luaeval('vim.api.nvim__id(false)'))
|
||||
eq(NIL, funcs.luaeval('vim.api.nvim__id(nil)'))
|
||||
|
||||
eq(0, eval([[type(luaeval('vim.api.nvim__id(1)'))]]))
|
||||
eq(1, eval([[type(luaeval('vim.api.nvim__id("1")'))]]))
|
||||
eq(3, eval([[type(luaeval('vim.api.nvim__id({1})'))]]))
|
||||
eq(4, eval([[type(luaeval('vim.api.nvim__id({foo=1})'))]]))
|
||||
eq(5, eval([[type(luaeval('vim.api.nvim__id(1.5)'))]]))
|
||||
eq(6, eval([[type(luaeval('vim.api.nvim__id(true)'))]]))
|
||||
eq(6, eval([[type(luaeval('vim.api.nvim__id(false)'))]]))
|
||||
eq(7, eval([[type(luaeval('vim.api.nvim__id(nil)'))]]))
|
||||
|
||||
eq({foo=1, bar={42, {{baz=true}, 5}}}, funcs.luaeval('vim.api.nvim__id({foo=1, bar={42, {{baz=true}, 5}}})'))
|
||||
end)
|
||||
|
||||
it('correctly converts container objects with type_idx to API objects', function()
|
||||
eq(5, eval('type(luaeval("vim.api.nvim__id({[vim.type_idx]=vim.types.float, [vim.val_idx]=0})"))'))
|
||||
eq(4, eval([[type(luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.dictionary})'))]]))
|
||||
eq(3, eval([[type(luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.array})'))]]))
|
||||
|
||||
eq({}, funcs.luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.array})'))
|
||||
|
||||
-- Presence of type_idx makes Vim ignore some keys
|
||||
eq({42}, funcs.luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})'))
|
||||
eq({foo=2}, funcs.luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})'))
|
||||
eq(10, funcs.luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})'))
|
||||
eq({}, funcs.luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2})'))
|
||||
end)
|
||||
|
||||
it('correctly converts arrays with type_idx to API objects', function()
|
||||
eq(3, eval([[type(luaeval('vim.api.nvim__id_array({[vim.type_idx]=vim.types.array})'))]]))
|
||||
|
||||
eq({}, funcs.luaeval('vim.api.nvim__id_array({[vim.type_idx]=vim.types.array})'))
|
||||
|
||||
eq({42}, funcs.luaeval('vim.api.nvim__id_array({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})'))
|
||||
eq({{foo=2}}, funcs.luaeval('vim.api.nvim__id_array({{[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})'))
|
||||
eq({10}, funcs.luaeval('vim.api.nvim__id_array({{[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})'))
|
||||
eq({}, funcs.luaeval('vim.api.nvim__id_array({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2})'))
|
||||
|
||||
eq({}, funcs.luaeval('vim.api.nvim__id_array({})'))
|
||||
eq(3, eval([[type(luaeval('vim.api.nvim__id_array({})'))]]))
|
||||
end)
|
||||
|
||||
it('correctly converts dictionaries with type_idx to API objects', function()
|
||||
eq(4, eval([[type(luaeval('vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.dictionary})'))]]))
|
||||
|
||||
eq({}, funcs.luaeval('vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.dictionary})'))
|
||||
|
||||
eq({v={42}}, funcs.luaeval('vim.api.nvim__id_dictionary({v={[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})'))
|
||||
eq({foo=2}, funcs.luaeval('vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})'))
|
||||
eq({v=10}, funcs.luaeval('vim.api.nvim__id_dictionary({v={[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})'))
|
||||
eq({v={}}, funcs.luaeval('vim.api.nvim__id_dictionary({v={[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2}})'))
|
||||
|
||||
-- If API requests dictionary, then empty table will be the one. This is not
|
||||
-- the case normally because empty table is an empty arrray.
|
||||
eq({}, funcs.luaeval('vim.api.nvim__id_dictionary({})'))
|
||||
eq(4, eval([[type(luaeval('vim.api.nvim__id_dictionary({})'))]]))
|
||||
end)
|
||||
|
||||
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',
|
||||
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',
|
||||
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',
|
||||
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',
|
||||
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',
|
||||
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',
|
||||
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',
|
||||
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',
|
||||
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',
|
||||
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',
|
||||
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',
|
||||
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',
|
||||
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',
|
||||
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',
|
||||
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',
|
||||
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
|
||||
-- TODO: check for errors with Buffer argument
|
||||
end)
|
||||
|
||||
it('accepts any value as API Boolean', function()
|
||||
eq('', funcs.luaeval('vim.api.nvim_replace_termcodes("", vim, false, nil)'))
|
||||
eq('', funcs.luaeval('vim.api.nvim_replace_termcodes("", 0, 1.5, "test")'))
|
||||
eq('', funcs.luaeval('vim.api.nvim_replace_termcodes("", true, {}, {[vim.type_idx]=vim.types.array})'))
|
||||
end)
|
||||
end)
|
||||
164
test/functional/lua/commands_spec.lua
Normal file
164
test/functional/lua/commands_spec.lua
Normal file
@@ -0,0 +1,164 @@
|
||||
-- Test suite for checking :lua* commands
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
|
||||
local eq = helpers.eq
|
||||
local NIL = helpers.NIL
|
||||
local clear = helpers.clear
|
||||
local meths = helpers.meths
|
||||
local funcs = helpers.funcs
|
||||
local source = helpers.source
|
||||
local dedent = helpers.dedent
|
||||
local exc_exec = helpers.exc_exec
|
||||
local write_file = helpers.write_file
|
||||
local redir_exec = helpers.redir_exec
|
||||
local curbufmeths = helpers.curbufmeths
|
||||
|
||||
before_each(clear)
|
||||
|
||||
describe(':lua command', function()
|
||||
it('works', function()
|
||||
eq('', redir_exec(
|
||||
'lua vim.api.nvim_buf_set_lines(1, 1, 2, false, {"TEST"})'))
|
||||
eq({'', 'TEST'}, curbufmeths.get_lines(0, 100, false))
|
||||
source(dedent([[
|
||||
lua << EOF
|
||||
vim.api.nvim_buf_set_lines(1, 1, 2, false, {"TSET"})
|
||||
EOF]]))
|
||||
eq({'', 'TSET'}, curbufmeths.get_lines(0, 100, false))
|
||||
source(dedent([[
|
||||
lua << EOF
|
||||
vim.api.nvim_buf_set_lines(1, 1, 2, false, {"SETT"})]]))
|
||||
eq({'', 'SETT'}, curbufmeths.get_lines(0, 100, false))
|
||||
source(dedent([[
|
||||
lua << EOF
|
||||
vim.api.nvim_buf_set_lines(1, 1, 2, false, {"ETTS"})
|
||||
vim.api.nvim_buf_set_lines(1, 2, 3, false, {"TTSE"})
|
||||
vim.api.nvim_buf_set_lines(1, 3, 4, false, {"STTE"})
|
||||
EOF]]))
|
||||
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]],
|
||||
exc_exec('lua error("TEST")'))
|
||||
eq([[Vim(lua):E5105: Error while calling lua chunk: [string "<VimL compiled string>"]: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]]=],
|
||||
exc_exec('lua error(nil)'))
|
||||
end)
|
||||
it('accepts embedded NLs without heredoc', function()
|
||||
-- Such code is usually used for `:execute 'lua' {generated_string}`:
|
||||
-- heredocs do not work in this case.
|
||||
meths.command([[
|
||||
lua
|
||||
vim.api.nvim_buf_set_lines(1, 1, 2, false, {"ETTS"})
|
||||
vim.api.nvim_buf_set_lines(1, 2, 3, false, {"TTSE"})
|
||||
vim.api.nvim_buf_set_lines(1, 3, 4, false, {"STTE"})
|
||||
]])
|
||||
eq({'', 'ETTS', 'TTSE', 'STTE'}, curbufmeths.get_lines(0, 100, false))
|
||||
end)
|
||||
it('preserves global and not preserves local variables', function()
|
||||
eq('', redir_exec('lua gvar = 42'))
|
||||
eq('', redir_exec('lua local lvar = 100500'))
|
||||
eq(NIL, funcs.luaeval('lvar'))
|
||||
eq(42, funcs.luaeval('gvar'))
|
||||
end)
|
||||
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({''}, curbufmeths.get_lines(0, -1, false))
|
||||
|
||||
eq('', redir_exec(('lua vim.api.nvim_buf_set_lines(1, 1, 2, false, {"%s"})'):format(s)))
|
||||
eq({'', s}, curbufmeths.get_lines(0, -1, false))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe(':luado command', function()
|
||||
it('works', function()
|
||||
curbufmeths.set_lines(0, 1, false, {"ABC", "def", "gHi"})
|
||||
eq('', redir_exec('luado lines = (lines or {}) lines[#lines + 1] = {linenr, line}'))
|
||||
eq({'ABC', 'def', 'gHi'}, curbufmeths.get_lines(0, -1, false))
|
||||
eq({{1, 'ABC'}, {2, 'def'}, {3, 'gHi'}}, funcs.luaeval('lines'))
|
||||
|
||||
-- Automatic transformation of numbers
|
||||
eq('', redir_exec('luado return linenr'))
|
||||
eq({'1', '2', '3'}, curbufmeths.get_lines(0, -1, false))
|
||||
|
||||
eq('', redir_exec('luado return ("<%02x>"):format(line:byte())'))
|
||||
eq({'<31>', '<32>', '<33>'}, curbufmeths.get_lines(0, -1, false))
|
||||
end)
|
||||
it('stops processing lines when suddenly out of lines', function()
|
||||
curbufmeths.set_lines(0, 1, false, {"ABC", "def", "gHi"})
|
||||
eq('', redir_exec('2,$luado runs = ((runs or 0) + 1) vim.api.nvim_command("%d")'))
|
||||
eq({''}, curbufmeths.get_lines(0, -1, false))
|
||||
eq(1, funcs.luaeval('runs'))
|
||||
end)
|
||||
it('works correctly when changing lines out of range', function()
|
||||
curbufmeths.set_lines(0, 1, false, {"ABC", "def", "gHi"})
|
||||
eq('\nE322: line number out of range: 1 past the end\nE320: Cannot find line 2',
|
||||
redir_exec('2,$luado vim.api.nvim_command("%d") return linenr'))
|
||||
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 ')']],
|
||||
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)]],
|
||||
exc_exec('luado return liness + 1'))
|
||||
end)
|
||||
it('works with NULL errors', function()
|
||||
eq([=[Vim(luado):E5111: Error while calling lua function: [NULL]]=],
|
||||
exc_exec('luado error(nil)'))
|
||||
end)
|
||||
it('fails in sandbox when needed', function()
|
||||
curbufmeths.set_lines(0, 1, false, {"ABC", "def", "gHi"})
|
||||
eq('\nE48: Not allowed in sandbox: sandbox luado runs = (runs or 0) + 1',
|
||||
redir_exec('sandbox luado runs = (runs or 0) + 1'))
|
||||
eq(NIL, funcs.luaeval('runs'))
|
||||
end)
|
||||
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({''}, curbufmeths.get_lines(0, -1, false))
|
||||
|
||||
eq('', redir_exec(('luado return "%s"'):format(s)))
|
||||
eq({s}, curbufmeths.get_lines(0, -1, false))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe(':luafile', function()
|
||||
local fname = 'Xtest-functional-lua-commands-luafile'
|
||||
|
||||
after_each(function()
|
||||
os.remove(fname)
|
||||
end)
|
||||
|
||||
it('works', function()
|
||||
write_file(fname, [[
|
||||
vim.api.nvim_buf_set_lines(1, 1, 2, false, {"ETTS"})
|
||||
vim.api.nvim_buf_set_lines(1, 2, 3, false, {"TTSE"})
|
||||
vim.api.nvim_buf_set_lines(1, 3, 4, false, {"STTE"})
|
||||
]])
|
||||
eq('', redir_exec('luafile ' .. fname))
|
||||
eq({'', 'ETTS', 'TTSE', 'STTE'}, curbufmeths.get_lines(0, 100, false))
|
||||
end)
|
||||
|
||||
it('correctly errors out', function()
|
||||
write_file(fname, '()')
|
||||
eq(("Vim(luafile):E5112: Error while creating lua chunk: %s:1: unexpected symbol near ')'"):format(fname),
|
||||
exc_exec('luafile ' .. fname))
|
||||
write_file(fname, 'vimm.api.nvim_buf_set_lines(1, 1, 2, false, {"ETTS"})')
|
||||
eq(("Vim(luafile):E5113: Error while calling lua chunk: %s:1: attempt to index global 'vimm' (a nil value)"):format(fname),
|
||||
exc_exec('luafile ' .. fname))
|
||||
end)
|
||||
it('works with NULL errors', function()
|
||||
write_file(fname, 'error(nil)')
|
||||
eq([=[Vim(luafile):E5113: Error while calling lua chunk: [NULL]]=],
|
||||
exc_exec('luafile ' .. fname))
|
||||
end)
|
||||
end)
|
||||
255
test/functional/lua/luaeval_spec.lua
Normal file
255
test/functional/lua/luaeval_spec.lua
Normal file
@@ -0,0 +1,255 @@
|
||||
-- Test suite for testing luaeval() function
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
|
||||
local redir_exec = helpers.redir_exec
|
||||
local exc_exec = helpers.exc_exec
|
||||
local command = helpers.command
|
||||
local meths = helpers.meths
|
||||
local funcs = helpers.funcs
|
||||
local clear = helpers.clear
|
||||
local eval = helpers.eval
|
||||
local NIL = helpers.NIL
|
||||
local eq = helpers.eq
|
||||
|
||||
before_each(clear)
|
||||
|
||||
local function startswith(expected, actual)
|
||||
eq(expected, actual:sub(1, #expected))
|
||||
end
|
||||
|
||||
describe('luaeval()', function()
|
||||
local nested_by_level = {}
|
||||
local nested = {}
|
||||
local nested_s = '{}'
|
||||
for i=1,100 do
|
||||
if i % 2 == 0 then
|
||||
nested = {nested}
|
||||
nested_s = '{' .. nested_s .. '}'
|
||||
else
|
||||
nested = {nested=nested}
|
||||
nested_s = '{nested=' .. nested_s .. '}'
|
||||
end
|
||||
nested_by_level[i] = {o=nested, s=nested_s}
|
||||
end
|
||||
|
||||
describe('second argument', function()
|
||||
it('is successfully received', function()
|
||||
local t = {t=true, f=false, --[[n=NIL,]] d={l={'string', 42, 0.42}}}
|
||||
eq(t, funcs.luaeval("_A", t))
|
||||
-- Not tested: nil, funcrefs, returned object identity: behaviour will
|
||||
-- most likely change.
|
||||
end)
|
||||
end)
|
||||
describe('lua values', function()
|
||||
it('are successfully transformed', function()
|
||||
eq({n=1, f=1.5, s='string', l={4, 2}},
|
||||
funcs.luaeval('{n=1, f=1.5, s="string", l={4, 2}}'))
|
||||
-- Not tested: nil inside containers: behaviour will most likely change.
|
||||
eq(NIL, funcs.luaeval('nil'))
|
||||
eq({['']=1}, funcs.luaeval('{[""]=1}'))
|
||||
end)
|
||||
end)
|
||||
describe('recursive lua values', function()
|
||||
it('are successfully transformed', function()
|
||||
funcs.luaeval('rawset(_G, "d", {})')
|
||||
funcs.luaeval('rawset(d, "d", d)')
|
||||
eq('\n{\'d\': {...@0}}', funcs.execute('echo luaeval("d")'))
|
||||
|
||||
funcs.luaeval('rawset(_G, "l", {})')
|
||||
funcs.luaeval('table.insert(l, l)')
|
||||
eq('\n[[...@0]]', funcs.execute('echo luaeval("l")'))
|
||||
end)
|
||||
end)
|
||||
describe('strings', function()
|
||||
it('are successfully converted to special dictionaries', function()
|
||||
command([[let s = luaeval('"\0"')]])
|
||||
eq({_TYPE={}, _VAL={'\n'}}, meths.get_var('s'))
|
||||
eq(1, funcs.eval('s._TYPE is v:msgpack_types.binary'))
|
||||
end)
|
||||
it('are successfully converted to special dictionaries in table keys',
|
||||
function()
|
||||
command([[let d = luaeval('{["\0"]=1}')]])
|
||||
eq({_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n'}}, 1}}}, meths.get_var('d'))
|
||||
eq(1, funcs.eval('d._TYPE is v:msgpack_types.map'))
|
||||
eq(1, funcs.eval('d._VAL[0][0]._TYPE is v:msgpack_types.string'))
|
||||
end)
|
||||
it('are successfully converted to special dictionaries from a list',
|
||||
function()
|
||||
command([[let l = luaeval('{"abc", "a\0b", "c\0d", "def"}')]])
|
||||
eq({'abc', {_TYPE={}, _VAL={'a\nb'}}, {_TYPE={}, _VAL={'c\nd'}}, 'def'},
|
||||
meths.get_var('l'))
|
||||
eq(1, funcs.eval('l[1]._TYPE is v:msgpack_types.binary'))
|
||||
eq(1, funcs.eval('l[2]._TYPE is v:msgpack_types.binary'))
|
||||
end)
|
||||
end)
|
||||
|
||||
-- Not checked: funcrefs converted to NIL. To be altered to something more
|
||||
-- meaningful later.
|
||||
|
||||
it('correctly evaluates scalars', function()
|
||||
eq(1, funcs.luaeval('1'))
|
||||
eq(0, eval('type(luaeval("1"))'))
|
||||
|
||||
eq(1.5, funcs.luaeval('1.5'))
|
||||
eq(5, eval('type(luaeval("1.5"))'))
|
||||
|
||||
eq("test", funcs.luaeval('"test"'))
|
||||
eq(1, eval('type(luaeval("\'test\'"))'))
|
||||
|
||||
eq('', funcs.luaeval('""'))
|
||||
eq({_TYPE={}, _VAL={'\n'}}, funcs.luaeval([['\0']]))
|
||||
eq({_TYPE={}, _VAL={'\n', '\n'}}, funcs.luaeval([['\0\n\0']]))
|
||||
eq(1, eval([[luaeval('"\0\n\0"')._TYPE is v:msgpack_types.binary]]))
|
||||
|
||||
eq(true, funcs.luaeval('true'))
|
||||
eq(false, funcs.luaeval('false'))
|
||||
eq(NIL, funcs.luaeval('nil'))
|
||||
end)
|
||||
|
||||
it('correctly evaluates containers', function()
|
||||
eq({}, funcs.luaeval('{}'))
|
||||
eq(3, eval('type(luaeval("{}"))'))
|
||||
|
||||
eq({test=1, foo=2}, funcs.luaeval('{test=1, foo=2}'))
|
||||
eq(4, eval('type(luaeval("{test=1, foo=2}"))'))
|
||||
|
||||
eq({4, 2}, funcs.luaeval('{4, 2}'))
|
||||
eq(3, eval('type(luaeval("{4, 2}"))'))
|
||||
|
||||
local level = 30
|
||||
eq(nested_by_level[level].o, funcs.luaeval(nested_by_level[level].s))
|
||||
|
||||
eq({_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n', '\n'}}, {_TYPE={}, _VAL={'\n', '\n\n'}}}}},
|
||||
funcs.luaeval([[{['\0\n\0']='\0\n\0\0'}]]))
|
||||
eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._TYPE is v:msgpack_types.map]]))
|
||||
eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._VAL[0][0]._TYPE is v:msgpack_types.string]]))
|
||||
eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._VAL[0][1]._TYPE is v:msgpack_types.binary]]))
|
||||
eq({nested={{_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n', '\n'}}, {_TYPE={}, _VAL={'\n', '\n\n'}}}}}}},
|
||||
funcs.luaeval([[{nested={{['\0\n\0']='\0\n\0\0'}}}]]))
|
||||
end)
|
||||
|
||||
it('correctly passes scalars as argument', function()
|
||||
eq(1, funcs.luaeval('_A', 1))
|
||||
eq(1.5, funcs.luaeval('_A', 1.5))
|
||||
eq('', funcs.luaeval('_A', ''))
|
||||
eq('test', funcs.luaeval('_A', 'test'))
|
||||
eq(NIL, funcs.luaeval('_A', NIL))
|
||||
eq(true, funcs.luaeval('_A', true))
|
||||
eq(false, funcs.luaeval('_A', false))
|
||||
end)
|
||||
|
||||
it('correctly passes containers as argument', function()
|
||||
eq({}, funcs.luaeval('_A', {}))
|
||||
eq({test=1}, funcs.luaeval('_A', {test=1}))
|
||||
eq({4, 2}, funcs.luaeval('_A', {4, 2}))
|
||||
local level = 28
|
||||
eq(nested_by_level[level].o, funcs.luaeval('_A', nested_by_level[level].o))
|
||||
end)
|
||||
|
||||
local function sp(typ, val)
|
||||
return ('{"_TYPE": v:msgpack_types.%s, "_VAL": %s}'):format(typ, val)
|
||||
end
|
||||
local function mapsp(...)
|
||||
local val = ''
|
||||
for i=1,(select('#', ...)/2) do
|
||||
val = ('%s[%s,%s],'):format(val, select(i * 2 - 1, ...),
|
||||
select(i * 2, ...))
|
||||
end
|
||||
return sp('map', '[' .. val .. ']')
|
||||
end
|
||||
local function luaevalarg(argexpr, expr)
|
||||
return eval(([=[
|
||||
[
|
||||
extend(g:, {'_ret': luaeval(%s, %s)})._ret,
|
||||
type(g:_ret)==type({})&&has_key(g:_ret, '_TYPE')
|
||||
? [
|
||||
get(keys(filter(copy(v:msgpack_types), 'v:val is g:_ret._TYPE')), 0,
|
||||
g:_ret._TYPE),
|
||||
get(g:_ret, '_VAL', g:_ret)
|
||||
]
|
||||
: [0, g:_ret]][1]
|
||||
]=]):format(expr or '"_A"', argexpr):gsub('\n', ''))
|
||||
end
|
||||
|
||||
it('correctly passes special dictionaries', function()
|
||||
eq({'binary', {'\n', '\n'}}, luaevalarg(sp('binary', '["\\n", "\\n"]')))
|
||||
eq({'binary', {'\n', '\n'}}, luaevalarg(sp('string', '["\\n", "\\n"]')))
|
||||
eq({0, true}, luaevalarg(sp('boolean', 1)))
|
||||
eq({0, false}, luaevalarg(sp('boolean', 0)))
|
||||
eq({0, NIL}, luaevalarg(sp('nil', 0)))
|
||||
eq({0, {[""]=""}}, luaevalarg(mapsp(sp('binary', '[""]'), '""')))
|
||||
eq({0, {[""]=""}}, luaevalarg(mapsp(sp('string', '[""]'), '""')))
|
||||
end)
|
||||
|
||||
it('issues an error in some cases', function()
|
||||
eq("Vim(call):E5100: Cannot convert given lua table: table should either have a sequence of positive integer keys or contain only string keys",
|
||||
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(): ",
|
||||
exc_exec('call luaeval("1, 2, 3")'))
|
||||
startswith("Vim(call):E5108: Error while calling lua chunk for luaeval(): ",
|
||||
exc_exec('call luaeval("(nil)()")'))
|
||||
eq("Vim(call):E5101: Cannot convert given lua type",
|
||||
exc_exec('call luaeval("{42, vim.api}")'))
|
||||
eq("Vim(call):E5101: Cannot convert given lua type",
|
||||
exc_exec('call luaeval("{foo=42, baz=vim.api}")'))
|
||||
|
||||
-- The following should not crash: conversion error happens inside
|
||||
eq("Vim(call):E5101: Cannot convert given lua type",
|
||||
exc_exec('call luaeval("vim.api")'))
|
||||
-- The following should not show internal error
|
||||
eq("\nE5101: Cannot convert given lua type\n0",
|
||||
redir_exec('echo luaeval("vim.api")'))
|
||||
end)
|
||||
|
||||
it('correctly converts containers with type_idx', function()
|
||||
eq(5, eval('type(luaeval("{[vim.type_idx]=vim.types.float, [vim.val_idx]=0}"))'))
|
||||
eq(4, eval([[type(luaeval('{[vim.type_idx]=vim.types.dictionary}'))]]))
|
||||
eq(3, eval([[type(luaeval('{[vim.type_idx]=vim.types.array}'))]]))
|
||||
|
||||
eq({}, funcs.luaeval('{[vim.type_idx]=vim.types.array}'))
|
||||
|
||||
-- Presence of type_idx makes Vim ignore some keys
|
||||
eq({42}, funcs.luaeval('{[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}'))
|
||||
eq({foo=2}, funcs.luaeval('{[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}'))
|
||||
eq(10, funcs.luaeval('{[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}'))
|
||||
|
||||
-- The following should not crash
|
||||
eq({}, funcs.luaeval('{[vim.type_idx]=vim.types.dictionary}'))
|
||||
end)
|
||||
|
||||
it('correctly converts self-containing containers', function()
|
||||
meths.set_var('l', {})
|
||||
eval('add(l, l)')
|
||||
eq(true, eval('luaeval("_A == _A[1]", l)'))
|
||||
eq(true, eval('luaeval("_A[1] == _A[1][1]", [l])'))
|
||||
eq(true, eval('luaeval("_A.d == _A.d[1]", {"d": l})'))
|
||||
eq(true, eval('luaeval("_A ~= _A[1]", [l])'))
|
||||
|
||||
meths.set_var('d', {foo=42})
|
||||
eval('extend(d, {"d": d})')
|
||||
eq(true, eval('luaeval("_A == _A.d", d)'))
|
||||
eq(true, eval('luaeval("_A[1] == _A[1].d", [d])'))
|
||||
eq(true, eval('luaeval("_A.d == _A.d.d", {"d": d})'))
|
||||
eq(true, eval('luaeval("_A ~= _A.d", {"d": d})'))
|
||||
end)
|
||||
|
||||
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)',
|
||||
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',
|
||||
exc_exec([[call luaeval("error('ERROR')")]]))
|
||||
eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [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 \')\'',
|
||||
exc_exec([[call luaeval("(']] .. s ..[[' + )")]]))
|
||||
eq(s, funcs.luaeval('"' .. s .. '"'))
|
||||
end)
|
||||
end)
|
||||
175
test/functional/lua/overrides_spec.lua
Normal file
175
test/functional/lua/overrides_spec.lua
Normal file
@@ -0,0 +1,175 @@
|
||||
-- Test for Vim overrides of lua built-ins
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
|
||||
local eq = helpers.eq
|
||||
local NIL = helpers.NIL
|
||||
local feed = helpers.feed
|
||||
local clear = helpers.clear
|
||||
local funcs = helpers.funcs
|
||||
local meths = helpers.meths
|
||||
local command = helpers.command
|
||||
local write_file = helpers.write_file
|
||||
local redir_exec = helpers.redir_exec
|
||||
|
||||
local screen
|
||||
|
||||
local fname = 'Xtest-functional-lua-overrides-luafile'
|
||||
|
||||
before_each(clear)
|
||||
|
||||
after_each(function()
|
||||
os.remove(fname)
|
||||
end)
|
||||
|
||||
describe('print', function()
|
||||
it('returns nothing', function()
|
||||
eq(NIL, funcs.luaeval('print("abc")'))
|
||||
eq(0, funcs.luaeval('select("#", print("abc"))'))
|
||||
end)
|
||||
it('allows catching printed text with :execute', function()
|
||||
eq('\nabc', funcs.execute('lua print("abc")'))
|
||||
eq('\nabc', funcs.execute('luado print("abc")'))
|
||||
eq('\nabc', funcs.execute('call luaeval("print(\'abc\')")'))
|
||||
write_file(fname, 'print("abc")')
|
||||
eq('\nabc', funcs.execute('luafile ' .. fname))
|
||||
|
||||
eq('\nabc', redir_exec('lua print("abc")'))
|
||||
eq('\nabc', redir_exec('luado print("abc")'))
|
||||
eq('\nabc', redir_exec('call luaeval("print(\'abc\')")'))
|
||||
write_file(fname, 'print("abc")')
|
||||
eq('\nabc', redir_exec('luafile ' .. fname))
|
||||
end)
|
||||
it('handles errors in __tostring', function()
|
||||
write_file(fname, [[
|
||||
local meta_nilerr = { __tostring = function() error(nil) end }
|
||||
local meta_abcerr = { __tostring = function() error("abc") end }
|
||||
local meta_tblout = { __tostring = function() return {"TEST"} end }
|
||||
v_nilerr = setmetatable({}, meta_nilerr)
|
||||
v_abcerr = setmetatable({}, meta_abcerr)
|
||||
v_tblout = setmetatable({}, meta_tblout)
|
||||
]])
|
||||
eq('', redir_exec('luafile ' .. fname))
|
||||
eq('\nE5114: Error while converting print argument #2: [NULL]',
|
||||
redir_exec('lua print("foo", v_nilerr, "bar")'))
|
||||
eq('\nE5114: Error while converting print argument #2: Xtest-functional-lua-overrides-luafile:2: abc',
|
||||
redir_exec('lua print("foo", v_abcerr, "bar")'))
|
||||
eq('\nE5114: 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()
|
||||
meths.set_option('more', true)
|
||||
eq('\nabc ^@ def\nghi^@^@^@jkl\nTEST\n\n\nT\n',
|
||||
redir_exec([[lua print("abc \0 def\nghi\0\0\0jkl\nTEST\n\n\nT\n")]]))
|
||||
eq('\nabc ^@ def\nghi^@^@^@jkl\nTEST\n\n\nT^@',
|
||||
redir_exec([[lua print("abc \0 def\nghi\0\0\0jkl\nTEST\n\n\nT\0")]]))
|
||||
eq('\nT^@', redir_exec([[lua print("T\0")]]))
|
||||
eq('\nT\n', redir_exec([[lua print("T\n")]]))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('debug.debug', function()
|
||||
before_each(function()
|
||||
screen = Screen.new()
|
||||
screen:attach()
|
||||
screen:set_default_attr_ids({
|
||||
[0] = {bold=true, foreground=255},
|
||||
E = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
|
||||
cr = {bold = true, foreground = Screen.colors.SeaGreen4},
|
||||
})
|
||||
end)
|
||||
it('works', function()
|
||||
command([[lua
|
||||
function Test(a)
|
||||
print(a)
|
||||
debug.debug()
|
||||
print(a * 100)
|
||||
end
|
||||
]])
|
||||
feed(':lua Test()\n')
|
||||
screen:expect([[
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
nil |
|
||||
lua_debug> ^ |
|
||||
]])
|
||||
feed('print("TEST")\n')
|
||||
screen:expect([[
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
nil |
|
||||
lua_debug> print("TEST") |
|
||||
TEST |
|
||||
lua_debug> ^ |
|
||||
]])
|
||||
feed('<C-c>')
|
||||
screen:expect([[
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
nil |
|
||||
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)} |
|
||||
Interrupt: {cr:Press ENTER or type command to continue}^ |
|
||||
]])
|
||||
feed('<C-l>:lua Test()\n')
|
||||
screen:expect([[
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
nil |
|
||||
lua_debug> ^ |
|
||||
]])
|
||||
feed('\n')
|
||||
screen:expect([[
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{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)} |
|
||||
{cr:Press ENTER or type command to continue}^ |
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
@@ -263,6 +263,14 @@ local function which(exe)
|
||||
end
|
||||
end
|
||||
|
||||
local function shallowcopy(orig)
|
||||
local copy = {}
|
||||
for orig_key, orig_value in pairs(orig) do
|
||||
copy[orig_key] = orig_value
|
||||
end
|
||||
return copy
|
||||
end
|
||||
|
||||
local function concat_tables(...)
|
||||
local ret = {}
|
||||
for i = 1, select('#', ...) do
|
||||
@@ -311,6 +319,7 @@ return {
|
||||
check_cores = check_cores,
|
||||
hasenv = hasenv,
|
||||
which = which,
|
||||
shallowcopy = shallowcopy,
|
||||
concat_tables = concat_tables,
|
||||
dedent = dedent,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user