diff options
Diffstat (limited to 'src/nvim/lua')
-rw-r--r-- | src/nvim/lua/converter.c | 26 | ||||
-rw-r--r-- | src/nvim/lua/executor.c | 49 | ||||
-rw-r--r-- | src/nvim/lua/executor.h | 1 |
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" |