diff options
-rw-r--r-- | src/nvim/ex_cmds.lua | 2 | ||||
-rw-r--r-- | src/nvim/viml/executor/executor.c | 37 | ||||
-rw-r--r-- | test/functional/lua/commands_spec.lua | 28 |
3 files changed, 65 insertions, 2 deletions
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index 25e74ebf9b..ad2fb642d4 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -1554,7 +1554,7 @@ return { command='luafile', flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN), addr_type=ADDR_LINES, - func='ex_ni', + func='ex_luafile', }, { command='lvimgrep', diff --git a/src/nvim/viml/executor/executor.c b/src/nvim/viml/executor/executor.c index df63667102..a01bf9966d 100644 --- a/src/nvim/viml/executor/executor.c +++ b/src/nvim/viml/executor/executor.c @@ -161,7 +161,7 @@ static int nlua_exec_luado_string(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL { const String *const str = (const String *)lua_touserdata(lstate, 1); const linenr_T *const range = (const linenr_T *)lua_touserdata(lstate, 2); - lua_pop(lstate, 1); + lua_pop(lstate, 2); #define DOSTART "return function(line, linenr) " #define DOEND " end" @@ -225,6 +225,26 @@ static int nlua_exec_luado_string(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL return 0; } +/// Evaluate lua file +/// +/// Expects one value on the stack: file to evaluate. Always returns nothing +/// (from the lua point of view). +static int nlua_exec_lua_file(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + const char *const filename = (const char *)lua_touserdata(lstate, 1); + lua_pop(lstate, 1); + + if (luaL_loadfile(lstate, filename)) { + nlua_error(lstate, _("E5112: Error while creating lua chunk: %.*s")); + return 0; + } + if (lua_pcall(lstate, 0, 0, 0)) { + nlua_error(lstate, _("E5113: Error while calling lua chunk: %.*s")); + return 0; + } + return 0; +} + /// Initialize lua interpreter state /// /// Called by lua interpreter itself to initialize state. @@ -402,3 +422,18 @@ void ex_luado(exarg_T *const eap) NLUA_CALL_C_FUNCTION_2(global_lstate, nlua_exec_luado_string, 0, (void *)&cmd, (void *)range); } + +/// Run lua file +/// +/// Used for :luafile. +/// +/// @param eap VimL command being run. +void ex_luafile(exarg_T *const eap) + FUNC_ATTR_NONNULL_ALL +{ + if (global_lstate == NULL) { + global_lstate = init_lua(); + } + NLUA_CALL_C_FUNCTION_1(global_lstate, nlua_exec_lua_file, 0, + (void *)eap->arg); +} diff --git a/test/functional/lua/commands_spec.lua b/test/functional/lua/commands_spec.lua index 41a5a8d9e0..80fac07f8c 100644 --- a/test/functional/lua/commands_spec.lua +++ b/test/functional/lua/commands_spec.lua @@ -9,6 +9,7 @@ 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 @@ -121,3 +122,30 @@ describe(':luado command', function() 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) +end) |