aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/lua')
-rw-r--r--src/nvim/lua/converter.c26
-rw-r--r--src/nvim/lua/executor.c49
-rw-r--r--src/nvim/lua/executor.h1
3 files changed, 70 insertions, 6 deletions
diff --git a/src/nvim/lua/converter.c b/src/nvim/lua/converter.c
index 5da6d2c0a0..3729e42b99 100644
--- a/src/nvim/lua/converter.c
+++ b/src/nvim/lua/converter.c
@@ -706,6 +706,10 @@ void nlua_push_Object(lua_State *lstate, const Object obj)
lua_pushnil(lstate);
break;
}
+ case kObjectTypeLuaRef: {
+ nlua_pushref(lstate, obj.data.luaref);
+ break;
+ }
#define ADD_TYPE(type, data_key) \
case kObjectType##type: { \
nlua_push_##type(lstate, obj.data.data_key); \
@@ -862,7 +866,7 @@ static Array nlua_pop_Array_unchecked(lua_State *const lstate,
lua_rawgeti(lstate, -1, (int)i);
- val = nlua_pop_Object(lstate, err);
+ val = nlua_pop_Object(lstate, false, err);
if (ERROR_SET(err)) {
ret.size = i - 1;
lua_pop(lstate, 1);
@@ -900,6 +904,7 @@ Array nlua_pop_Array(lua_State *lstate, Error *err)
/// @param[out] err Location where error will be saved.
static Dictionary nlua_pop_Dictionary_unchecked(lua_State *lstate,
const LuaTableProps table_props,
+ bool ref,
Error *err)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
@@ -923,7 +928,7 @@ static Dictionary nlua_pop_Dictionary_unchecked(lua_State *lstate,
// stack: dict, key, value
if (!ERROR_SET(err)) {
- ret.items[i].value = nlua_pop_Object(lstate, err);
+ ret.items[i].value = nlua_pop_Object(lstate, ref, err);
// stack: dict, key
} else {
lua_pop(lstate, 1);
@@ -951,7 +956,7 @@ static Dictionary nlua_pop_Dictionary_unchecked(lua_State *lstate,
/// Convert lua table to dictionary
///
/// Always pops one value from the stack.
-Dictionary nlua_pop_Dictionary(lua_State *lstate, Error *err)
+Dictionary nlua_pop_Dictionary(lua_State *lstate, bool ref, Error *err)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
const LuaTableProps table_props = nlua_check_type(lstate, err,
@@ -961,7 +966,7 @@ Dictionary nlua_pop_Dictionary(lua_State *lstate, Error *err)
return (Dictionary) { .size = 0, .items = NULL };
}
- return nlua_pop_Dictionary_unchecked(lstate, table_props, err);
+ return nlua_pop_Dictionary_unchecked(lstate, table_props, ref, err);
}
/// Helper structure for nlua_pop_Object
@@ -973,7 +978,7 @@ typedef struct {
/// Convert lua table to object
///
/// Always pops one value from the stack.
-Object nlua_pop_Object(lua_State *const lstate, Error *const err)
+Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
{
Object ret = NIL;
const int initial_size = lua_gettop(lstate);
@@ -1122,7 +1127,18 @@ Object nlua_pop_Object(lua_State *const lstate, Error *const err)
}
break;
}
+
+ case LUA_TFUNCTION: {
+ if (ref) {
+ *cur.obj = LUAREF_OBJ(nlua_ref(lstate, -1));
+ } else {
+ goto type_error;
+ }
+ break;
+ }
+
default: {
+type_error:
api_set_error(err, kErrorTypeValidation,
"Cannot convert given lua type");
break;
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 4e94c10283..fa8a67ff39 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -363,6 +363,33 @@ static int nlua_getenv(lua_State *lstate)
}
#endif
+/// add the value to the registry
+LuaRef nlua_ref(lua_State *lstate, int index)
+{
+ lua_pushvalue(lstate, index);
+ return luaL_ref(lstate, LUA_REGISTRYINDEX);
+}
+
+/// remove the value from the registry
+void nlua_unref(lua_State *lstate, LuaRef ref)
+{
+ if (ref > 0) {
+ luaL_unref(lstate, LUA_REGISTRYINDEX, ref);
+ }
+}
+
+void executor_free_luaref(LuaRef ref)
+{
+ lua_State *const lstate = nlua_enter();
+ nlua_unref(lstate, ref);
+}
+
+/// push a value referenced in the regirstry
+void nlua_pushref(lua_State *lstate, LuaRef ref)
+{
+ lua_rawgeti(lstate, LUA_REGISTRYINDEX, ref);
+}
+
/// Evaluate lua string
///
/// Used for luaeval().
@@ -451,9 +478,29 @@ Object executor_exec_lua_api(const String str, const Array args, Error *err)
return NIL;
}
- return nlua_pop_Object(lstate, err);
+ return nlua_pop_Object(lstate, false, err);
}
+Object executor_exec_lua_cb(LuaRef ref, const char *name, Array args)
+{
+ lua_State *const lstate = nlua_enter();
+ nlua_pushref(lstate, ref);
+ lua_pushstring(lstate, name);
+ for (size_t i = 0; i < args.size; i++) {
+ nlua_push_Object(lstate, args.items[i]);
+ }
+
+ if (lua_pcall(lstate, (int)args.size+1, 1, 0)) {
+ // TODO(bfredl): callbacks:s might not always be msg-safe, for instance
+ // lua callbacks for redraw events. Later on let the caller deal with the
+ // error instead.
+ nlua_error(lstate, _("Error executing lua callback: %.*s"));
+ return NIL;
+ }
+ Error err = ERROR_INIT;
+
+ return nlua_pop_Object(lstate, false, &err);
+}
/// Run lua string
///
diff --git a/src/nvim/lua/executor.h b/src/nvim/lua/executor.h
index 0cbf290f64..8d356a5600 100644
--- a/src/nvim/lua/executor.h
+++ b/src/nvim/lua/executor.h
@@ -2,6 +2,7 @@
#define NVIM_LUA_EXECUTOR_H
#include <lua.h>
+#include <lauxlib.h>
#include "nvim/api/private/defs.h"
#include "nvim/func_attr.h"