mirror of
https://github.com/neovim/neovim.git
synced 2025-09-30 23:18:33 +00:00
api: allow nvim_buf_attach from lua using callbacks
This commit is contained in:
@@ -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;
|
||||
|
@@ -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
|
||||
///
|
||||
|
@@ -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"
|
||||
|
Reference in New Issue
Block a user