diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-05-17 14:32:35 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-05-17 14:32:35 +0200 |
commit | eb04f0893afe01faff272ef84c70d8cc16d8e80a (patch) | |
tree | c0397134cdeb9f9e4b9c47bc517a1d6175df64c2 /src/if_lua.c | |
parent | 26e86445bf06ab7e7587dfdf75f33f7c70632b46 (diff) | |
download | vim-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.c | 77 |
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; } |