mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
api: execute lua directly from the remote api
This commit is contained in:
parent
12fb634fe6
commit
f424189093
@ -15,6 +15,7 @@
|
|||||||
#include "nvim/api/private/defs.h"
|
#include "nvim/api/private/defs.h"
|
||||||
#include "nvim/api/buffer.h"
|
#include "nvim/api/buffer.h"
|
||||||
#include "nvim/msgpack_rpc/channel.h"
|
#include "nvim/msgpack_rpc/channel.h"
|
||||||
|
#include "nvim/lua/executor.h"
|
||||||
#include "nvim/vim.h"
|
#include "nvim/vim.h"
|
||||||
#include "nvim/buffer.h"
|
#include "nvim/buffer.h"
|
||||||
#include "nvim/file_search.h"
|
#include "nvim/file_search.h"
|
||||||
@ -254,6 +255,25 @@ free_vim_args:
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Execute lua code. Parameters might be passed, they are available inside
|
||||||
|
/// the chunk as `...`. The chunk can return a value.
|
||||||
|
///
|
||||||
|
/// To evaluate an expression, it must be prefixed with "return ". For
|
||||||
|
/// instance, to call a lua function with arguments sent in and get its
|
||||||
|
/// return value back, use the code "return my_function(...)".
|
||||||
|
///
|
||||||
|
/// @param code lua code to execute
|
||||||
|
/// @param args Arguments to the code
|
||||||
|
/// @param[out] err Details of an error encountered while parsing
|
||||||
|
/// or executing the lua code.
|
||||||
|
///
|
||||||
|
/// @return Return value of lua code if present or NIL.
|
||||||
|
Object nvim_execute_lua(String code, Array args, Error *err)
|
||||||
|
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY
|
||||||
|
{
|
||||||
|
return executor_exec_lua_api(code, args, err);
|
||||||
|
}
|
||||||
|
|
||||||
/// Calculates the number of display cells occupied by `text`.
|
/// Calculates the number of display cells occupied by `text`.
|
||||||
/// <Tab> counts as one cell.
|
/// <Tab> counts as one cell.
|
||||||
///
|
///
|
||||||
|
@ -373,6 +373,46 @@ static int nlua_eval_lua_string(lua_State *const lstate)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Evaluate lua string
|
||||||
|
///
|
||||||
|
/// Expects four values on the stack: string to evaluate, pointer to args array,
|
||||||
|
/// and locations where result and error are saved, respectively. Always
|
||||||
|
/// returns nothing (from the lua point of view).
|
||||||
|
static int nlua_exec_lua_string_api(lua_State *const lstate)
|
||||||
|
FUNC_ATTR_NONNULL_ALL
|
||||||
|
{
|
||||||
|
const String *str = (const String *)lua_touserdata(lstate, 1);
|
||||||
|
const Array *args = (const Array *)lua_touserdata(lstate, 2);
|
||||||
|
Object *retval = (Object *)lua_touserdata(lstate, 3);
|
||||||
|
Error *err = (Error *)lua_touserdata(lstate, 4);
|
||||||
|
|
||||||
|
lua_pop(lstate, 4);
|
||||||
|
|
||||||
|
if (luaL_loadbuffer(lstate, str->data, str->size, "<nvim>")) {
|
||||||
|
size_t len;
|
||||||
|
const char *str = lua_tolstring(lstate, -1, &len);
|
||||||
|
api_set_error(err, kErrorTypeValidation,
|
||||||
|
"Error loading lua: %.*s", (int)len, str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < args->size; i++) {
|
||||||
|
nlua_push_Object(lstate, args->items[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lua_pcall(lstate, (int)args->size, 1, 0)) {
|
||||||
|
size_t len;
|
||||||
|
const char *str = lua_tolstring(lstate, -1, &len);
|
||||||
|
api_set_error(err, kErrorTypeException,
|
||||||
|
"Error executing lua: %.*s", (int)len, str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*retval = nlua_pop_Object(lstate, err);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// Print as a Vim message
|
/// Print as a Vim message
|
||||||
///
|
///
|
||||||
/// @param lstate Lua interpreter state.
|
/// @param lstate Lua interpreter state.
|
||||||
@ -516,6 +556,28 @@ void executor_eval_lua(const String str, typval_T *const arg,
|
|||||||
(void *)&str, arg, ret_tv);
|
(void *)&str, arg, ret_tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Execute lua string
|
||||||
|
///
|
||||||
|
/// Used for nvim_execute_lua().
|
||||||
|
///
|
||||||
|
/// @param[in] str String to execute.
|
||||||
|
/// @param[in] args array of ... args
|
||||||
|
/// @param[out] err Location where error will be saved.
|
||||||
|
///
|
||||||
|
/// @return Return value of the execution.
|
||||||
|
Object executor_exec_lua_api(const String str, const Array args, Error *err)
|
||||||
|
{
|
||||||
|
if (global_lstate == NULL) {
|
||||||
|
global_lstate = init_lua();
|
||||||
|
}
|
||||||
|
|
||||||
|
Object retval = NIL;
|
||||||
|
NLUA_CALL_C_FUNCTION_4(global_lstate, nlua_exec_lua_string_api, 0,
|
||||||
|
(void *)&str, (void *)&args, &retval, err);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Run lua string
|
/// Run lua string
|
||||||
///
|
///
|
||||||
/// Used for :lua.
|
/// Used for :lua.
|
||||||
|
@ -81,6 +81,36 @@ describe('api', function()
|
|||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
describe('nvim_execute_lua', function()
|
||||||
|
it('works', function()
|
||||||
|
meths.execute_lua('vim.api.nvim_set_var("test", 3)', {})
|
||||||
|
eq(3, meths.get_var('test'))
|
||||||
|
|
||||||
|
eq(17, meths.execute_lua('a, b = ...\nreturn a + b', {10,7}))
|
||||||
|
|
||||||
|
eq(NIL, meths.execute_lua('function xx(a,b)\nreturn a..b\nend',{}))
|
||||||
|
eq("xy", meths.execute_lua('return xx(...)', {'x','y'}))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('reports errors', function()
|
||||||
|
eq({false, 'Error loading lua: [string "<nvim>"]:1: '..
|
||||||
|
"'=' expected near '+'"},
|
||||||
|
meth_pcall(meths.execute_lua, 'a+*b', {}))
|
||||||
|
|
||||||
|
eq({false, 'Error loading lua: [string "<nvim>"]:1: '..
|
||||||
|
"unexpected symbol near '1'"},
|
||||||
|
meth_pcall(meths.execute_lua, '1+2', {}))
|
||||||
|
|
||||||
|
eq({false, 'Error loading lua: [string "<nvim>"]:1: '..
|
||||||
|
"unexpected symbol"},
|
||||||
|
meth_pcall(meths.execute_lua, 'aa=bb\0', {}))
|
||||||
|
|
||||||
|
eq({false, 'Error executing lua: [string "<nvim>"]:1: '..
|
||||||
|
"attempt to call global 'bork' (a nil value)"},
|
||||||
|
meth_pcall(meths.execute_lua, 'bork()', {}))
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
describe('nvim_input', function()
|
describe('nvim_input', function()
|
||||||
it("VimL error: does NOT fail, updates v:errmsg", function()
|
it("VimL error: does NOT fail, updates v:errmsg", function()
|
||||||
local status, _ = pcall(nvim, "input", ":call bogus_fn()<CR>")
|
local status, _ = pcall(nvim, "input", ":call bogus_fn()<CR>")
|
||||||
|
Loading…
Reference in New Issue
Block a user