mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
patch 8.2.0775: not easy to call a Vim function from Lua
Problem: Not easy to call a Vim function from Lua. Solution: Add vim.call() and vim.fn(). (Prabir Shrestha, closes #6063)
This commit is contained in:
77
src/if_lua.c
77
src/if_lua.c
@@ -568,8 +568,21 @@ luaV_totypval(lua_State *L, int pos, typval_T *tv)
|
||||
break;
|
||||
case LUA_TNUMBER:
|
||||
#ifdef FEAT_FLOAT
|
||||
tv->v_type = VAR_FLOAT;
|
||||
tv->vval.v_float = (float_T) lua_tonumber(L, pos);
|
||||
{
|
||||
const lua_Number n = lua_tonumber(L, pos);
|
||||
|
||||
if (n > (lua_Number)INT64_MAX || n < (lua_Number)INT64_MIN
|
||||
|| ((lua_Number)((varnumber_T)n)) != n)
|
||||
{
|
||||
tv->v_type = VAR_FLOAT;
|
||||
tv->vval.v_float = (float_T)n;
|
||||
}
|
||||
else
|
||||
{
|
||||
tv->v_type = VAR_NUMBER;
|
||||
tv->vval.v_number = (varnumber_T)n;
|
||||
}
|
||||
}
|
||||
#else
|
||||
tv->v_type = VAR_NUMBER;
|
||||
tv->vval.v_number = (varnumber_T) lua_tointeger(L, pos);
|
||||
@@ -1903,6 +1916,52 @@ luaV_type(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
luaV_call(lua_State *L)
|
||||
{
|
||||
int argc = lua_gettop(L) - 1;
|
||||
size_t funcname_len;
|
||||
char_u *funcname;
|
||||
char *error = NULL;
|
||||
typval_T rettv;
|
||||
typval_T argv[MAX_FUNC_ARGS + 1];
|
||||
int i = 0;
|
||||
|
||||
if (argc > MAX_FUNC_ARGS)
|
||||
return luaL_error(L, "Function called with too many arguments");
|
||||
|
||||
funcname = (char_u *)luaL_checklstring(L, 1, &funcname_len);
|
||||
|
||||
for (; i < argc; i++)
|
||||
{
|
||||
if (luaV_totypval(L, i + 2, &argv[i]) == FAIL)
|
||||
{
|
||||
error = "lua: cannot convert value";
|
||||
goto free_vim_args;
|
||||
}
|
||||
}
|
||||
|
||||
argv[argc].v_type = VAR_UNKNOWN;
|
||||
|
||||
if (call_vim_function(funcname, argc, argv, &rettv) == FAIL)
|
||||
{
|
||||
error = "lua: call_vim_function failed";
|
||||
goto free_vim_args;
|
||||
}
|
||||
|
||||
luaV_pushtypval(L, &rettv);
|
||||
clear_tv(&rettv);
|
||||
|
||||
free_vim_args:
|
||||
while (i > 0)
|
||||
clear_tv(&argv[--i]);
|
||||
|
||||
if (error == NULL)
|
||||
return 1;
|
||||
else
|
||||
return luaL_error(L, error);
|
||||
}
|
||||
|
||||
static const luaL_Reg luaV_module[] = {
|
||||
{"command", luaV_command},
|
||||
{"eval", luaV_eval},
|
||||
@@ -1916,6 +1975,7 @@ static const luaL_Reg luaV_module[] = {
|
||||
{"window", luaV_window},
|
||||
{"open", luaV_open},
|
||||
{"type", luaV_type},
|
||||
{"call", luaV_call},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -1997,6 +2057,17 @@ luaV_setref(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define LUA_VIM_FN_CODE \
|
||||
"vim.fn = setmetatable({}, {"\
|
||||
" __index = function (t, key)"\
|
||||
" local function _fn(...)"\
|
||||
" return vim.call(key, ...)"\
|
||||
" end"\
|
||||
" t[key] = _fn"\
|
||||
" return _fn"\
|
||||
" end"\
|
||||
"})"
|
||||
|
||||
static int
|
||||
luaopen_vim(lua_State *L)
|
||||
{
|
||||
@@ -2052,6 +2123,8 @@ luaopen_vim(lua_State *L)
|
||||
lua_pushvalue(L, 1); // cache table
|
||||
luaV_openlib(L, luaV_module, 1);
|
||||
lua_setglobal(L, LUAVIM_NAME);
|
||||
// custom code
|
||||
luaL_dostring(L, LUA_VIM_FN_CODE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user