summaryrefslogtreecommitdiff
path: root/src/if_lua.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-05-17 14:32:35 +0200
committerBram Moolenaar <Bram@vim.org>2020-05-17 14:32:35 +0200
commiteb04f0893afe01faff272ef84c70d8cc16d8e80a (patch)
treec0397134cdeb9f9e4b9c47bc517a1d6175df64c2 /src/if_lua.c
parent26e86445bf06ab7e7587dfdf75f33f7c70632b46 (diff)
downloadvim-git-eb04f0893afe01faff272ef84c70d8cc16d8e80a.tar.gz
patch 8.2.0775: not easy to call a Vim function from Luav8.2.0775
Problem: Not easy to call a Vim function from Lua. Solution: Add vim.call() and vim.fn(). (Prabir Shrestha, closes #6063)
Diffstat (limited to 'src/if_lua.c')
-rw-r--r--src/if_lua.c77
1 files changed, 75 insertions, 2 deletions
diff --git a/src/if_lua.c b/src/if_lua.c
index 19842912f..d4cc21f3d 100644
--- a/src/if_lua.c
+++ b/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;
}