xref: /vim-8.2.3635/src/if_lua.c (revision 965d2edb)
11dced572SBram Moolenaar /* vi:set ts=8 sts=4 sw=4 noet:
20ba04296SBram Moolenaar  *
30ba04296SBram Moolenaar  * VIM - Vi IMproved	by Bram Moolenaar
40ba04296SBram Moolenaar  *
50ba04296SBram Moolenaar  * Lua interface by Luis Carvalho
60ba04296SBram Moolenaar  *
70ba04296SBram Moolenaar  * Do ":help uganda"  in Vim to read copying and usage conditions.
80ba04296SBram Moolenaar  * Do ":help credits" in Vim to see a list of people who contributed.
90ba04296SBram Moolenaar  * See README.txt for an overview of the Vim source code.
100ba04296SBram Moolenaar  */
110ba04296SBram Moolenaar 
12e2793357SBram Moolenaar #include "vim.h"
1311328bc7SYegappan Lakshmanan #include "version.h"
14e2793357SBram Moolenaar 
150ba04296SBram Moolenaar #include <lua.h>
160ba04296SBram Moolenaar #include <lualib.h>
170ba04296SBram Moolenaar #include <lauxlib.h>
180ba04296SBram Moolenaar 
192ab2e860SBram Moolenaar // Only do the following when the feature is enabled.  Needed for "make
202ab2e860SBram Moolenaar // depend".
210ba04296SBram Moolenaar #if defined(FEAT_LUA) || defined(PROTO)
220ba04296SBram Moolenaar 
230ba04296SBram Moolenaar #define LUAVIM_CHUNKNAME "vim chunk"
240ba04296SBram Moolenaar #define LUAVIM_NAME "vim"
251dced572SBram Moolenaar #define LUAVIM_EVALNAME "luaeval"
261dced572SBram Moolenaar #define LUAVIM_EVALHEADER "local _A=select(1,...) return "
270ba04296SBram Moolenaar 
28125ed274SBram Moolenaar #ifdef LUA_RELEASE
29125ed274SBram Moolenaar # define LUAVIM_VERSION LUA_RELEASE
30125ed274SBram Moolenaar #else
31125ed274SBram Moolenaar # define LUAVIM_VERSION LUA_VERSION
32125ed274SBram Moolenaar #endif
33125ed274SBram Moolenaar 
340ba04296SBram Moolenaar typedef buf_T *luaV_Buffer;
350ba04296SBram Moolenaar typedef win_T *luaV_Window;
361dced572SBram Moolenaar typedef dict_T *luaV_Dict;
371dced572SBram Moolenaar typedef list_T *luaV_List;
38b7828690SBram Moolenaar typedef blob_T *luaV_Blob;
39ca06da92SBram Moolenaar typedef struct {
404eefe47eSBram Moolenaar     char_u	*name;	// funcref
41ca06da92SBram Moolenaar     dict_T	*self;	// selfdict
42ca06da92SBram Moolenaar } luaV_Funcref;
43c8970b94SBram Moolenaar typedef int (*msgfunc_T)(char *);
440ba04296SBram Moolenaar 
45801ab069SBram Moolenaar typedef struct {
46801ab069SBram Moolenaar     int lua_funcref;    // ref to a lua func
47801ab069SBram Moolenaar     int lua_tableref;   // ref to a lua table if metatable else LUA_NOREF. used
48801ab069SBram Moolenaar 			// for __call
49801ab069SBram Moolenaar     lua_State *L;
50801ab069SBram Moolenaar } luaV_CFuncState;
51801ab069SBram Moolenaar 
521dced572SBram Moolenaar static const char LUAVIM_DICT[] = "dict";
531dced572SBram Moolenaar static const char LUAVIM_LIST[] = "list";
54b7828690SBram Moolenaar static const char LUAVIM_BLOB[] = "blob";
55ca06da92SBram Moolenaar static const char LUAVIM_FUNCREF[] = "funcref";
560ba04296SBram Moolenaar static const char LUAVIM_BUFFER[] = "buffer";
570ba04296SBram Moolenaar static const char LUAVIM_WINDOW[] = "window";
580ba04296SBram Moolenaar static const char LUAVIM_FREE[] = "luaV_free";
591dced572SBram Moolenaar static const char LUAVIM_LUAEVAL[] = "luaV_luaeval";
601dced572SBram Moolenaar static const char LUAVIM_SETREF[] = "luaV_setref";
610ba04296SBram Moolenaar 
62801ab069SBram Moolenaar static const char LUA___CALL[] = "__call";
63801ab069SBram Moolenaar 
642ab2e860SBram Moolenaar // most functions are closures with a cache table as first upvalue;
652ab2e860SBram Moolenaar // get/setudata manage references to vim userdata in cache table through
662ab2e860SBram Moolenaar // object pointers (light userdata)
671dced572SBram Moolenaar #define luaV_getudata(L, v) \
681dced572SBram Moolenaar     lua_pushlightuserdata((L), (void *) (v)); \
691dced572SBram Moolenaar     lua_rawget((L), lua_upvalueindex(1))
701dced572SBram Moolenaar #define luaV_setudata(L, v) \
711dced572SBram Moolenaar     lua_pushlightuserdata((L), (void *) (v)); \
721dced572SBram Moolenaar     lua_pushvalue((L), -2); \
731dced572SBram Moolenaar     lua_rawset((L), lua_upvalueindex(1))
740ba04296SBram Moolenaar #define luaV_getfield(L, s) \
750ba04296SBram Moolenaar     lua_pushlightuserdata((L), (void *)(s)); \
760ba04296SBram Moolenaar     lua_rawget((L), LUA_REGISTRYINDEX)
770ba04296SBram Moolenaar #define luaV_checksandbox(L) \
780ba04296SBram Moolenaar     if (sandbox) luaL_error((L), "not allowed in sandbox")
790ba04296SBram Moolenaar #define luaV_msg(L) luaV_msgfunc((L), (msgfunc_T) msg)
800ba04296SBram Moolenaar #define luaV_emsg(L) luaV_msgfunc((L), (msgfunc_T) emsg)
81ca06da92SBram Moolenaar #define luaV_checktypval(L, a, v, msg) \
82ca06da92SBram Moolenaar     do { \
83ca06da92SBram Moolenaar 	if (luaV_totypval(L, a, v) == FAIL) \
84ca06da92SBram Moolenaar 	    luaL_error(L, msg ": cannot convert value"); \
85ca06da92SBram Moolenaar     } while (0)
860ba04296SBram Moolenaar 
871dced572SBram Moolenaar static luaV_List *luaV_pushlist(lua_State *L, list_T *lis);
881dced572SBram Moolenaar static luaV_Dict *luaV_pushdict(lua_State *L, dict_T *dic);
89b7828690SBram Moolenaar static luaV_Blob *luaV_pushblob(lua_State *L, blob_T *blo);
904eefe47eSBram Moolenaar static luaV_Funcref *luaV_pushfuncref(lua_State *L, char_u *name);
91801ab069SBram Moolenaar static int luaV_call_lua_func(int argcount, typval_T *argvars, typval_T *rettv, void *state);
92801ab069SBram Moolenaar static void luaV_call_lua_func_free(void *state);
931dced572SBram Moolenaar 
941dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501
951dced572SBram Moolenaar #define luaV_openlib(L, l, n) luaL_openlib(L, NULL, l, n)
961dced572SBram Moolenaar #define luaL_typeerror luaL_typerror
971dced572SBram Moolenaar #else
981dced572SBram Moolenaar #define luaV_openlib luaL_setfuncs
991dced572SBram Moolenaar #endif
1000ba04296SBram Moolenaar 
1010ba04296SBram Moolenaar #ifdef DYNAMIC_LUA
1022334b6d5SBram Moolenaar 
1034f97475dSBram Moolenaar #ifndef MSWIN
1042334b6d5SBram Moolenaar # include <dlfcn.h>
1052334b6d5SBram Moolenaar # define HANDLE void*
1062334b6d5SBram Moolenaar # define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL)
1072334b6d5SBram Moolenaar # define symbol_from_dll dlsym
1082334b6d5SBram Moolenaar # define close_dll dlclose
1091a3e5747SMartin Tournoij # define load_dll_error dlerror
1102334b6d5SBram Moolenaar #else
111ebbcb824SBram Moolenaar # define load_dll vimLoadLib
1122334b6d5SBram Moolenaar # define symbol_from_dll GetProcAddress
1132334b6d5SBram Moolenaar # define close_dll FreeLibrary
1141a3e5747SMartin Tournoij # define load_dll_error GetWin32Error
1152334b6d5SBram Moolenaar #endif
1162334b6d5SBram Moolenaar 
1172ab2e860SBram Moolenaar // lauxlib
1181dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501
1190ba04296SBram Moolenaar #define luaL_register dll_luaL_register
1201dced572SBram Moolenaar #define luaL_prepbuffer dll_luaL_prepbuffer
1211dced572SBram Moolenaar #define luaL_openlib dll_luaL_openlib
1220ba04296SBram Moolenaar #define luaL_typerror dll_luaL_typerror
1231dced572SBram Moolenaar #define luaL_loadfile dll_luaL_loadfile
1241dced572SBram Moolenaar #define luaL_loadbuffer dll_luaL_loadbuffer
1251dced572SBram Moolenaar #else
1261dced572SBram Moolenaar #define luaL_prepbuffsize dll_luaL_prepbuffsize
1271dced572SBram Moolenaar #define luaL_setfuncs dll_luaL_setfuncs
1281dced572SBram Moolenaar #define luaL_loadfilex dll_luaL_loadfilex
1291dced572SBram Moolenaar #define luaL_loadbufferx dll_luaL_loadbufferx
1301dced572SBram Moolenaar #define luaL_argerror dll_luaL_argerror
1311dced572SBram Moolenaar #endif
1325551b131SBram Moolenaar #if LUA_VERSION_NUM >= 504
1335551b131SBram Moolenaar #define luaL_typeerror dll_luaL_typeerror
1345551b131SBram Moolenaar #endif
135bd2f3c3eSBram Moolenaar #define luaL_checkany dll_luaL_checkany
1360ba04296SBram Moolenaar #define luaL_checklstring dll_luaL_checklstring
1370ba04296SBram Moolenaar #define luaL_checkinteger dll_luaL_checkinteger
1380ba04296SBram Moolenaar #define luaL_optinteger dll_luaL_optinteger
1390ba04296SBram Moolenaar #define luaL_checktype dll_luaL_checktype
1400ba04296SBram Moolenaar #define luaL_error dll_luaL_error
1410ba04296SBram Moolenaar #define luaL_newstate dll_luaL_newstate
1420ba04296SBram Moolenaar #define luaL_buffinit dll_luaL_buffinit
1430ba04296SBram Moolenaar #define luaL_addlstring dll_luaL_addlstring
1440ba04296SBram Moolenaar #define luaL_pushresult dll_luaL_pushresult
145df1643a6SBram Moolenaar #define luaL_loadstring dll_luaL_loadstring
1461e4c7d0eSBram Moolenaar #define luaL_ref dll_luaL_ref
1471e4c7d0eSBram Moolenaar #define luaL_unref dll_luaL_unref
1482ab2e860SBram Moolenaar // lua
1491dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501
1501dced572SBram Moolenaar #define lua_tonumber dll_lua_tonumber
1511dced572SBram Moolenaar #define lua_tointeger dll_lua_tointeger
1521dced572SBram Moolenaar #define lua_call dll_lua_call
1531dced572SBram Moolenaar #define lua_pcall dll_lua_pcall
1541dced572SBram Moolenaar #else
1551dced572SBram Moolenaar #define lua_tonumberx dll_lua_tonumberx
1561dced572SBram Moolenaar #define lua_tointegerx dll_lua_tointegerx
1571dced572SBram Moolenaar #define lua_callk dll_lua_callk
1581dced572SBram Moolenaar #define lua_pcallk dll_lua_pcallk
1591dced572SBram Moolenaar #define lua_getglobal dll_lua_getglobal
1601dced572SBram Moolenaar #define lua_setglobal dll_lua_setglobal
1611dced572SBram Moolenaar #endif
1621f860d85SBram Moolenaar #if LUA_VERSION_NUM <= 502
1631f860d85SBram Moolenaar #define lua_replace dll_lua_replace
1641f860d85SBram Moolenaar #define lua_remove dll_lua_remove
1651f860d85SBram Moolenaar #endif
1661f860d85SBram Moolenaar #if LUA_VERSION_NUM >= 503
1671f860d85SBram Moolenaar #define lua_rotate dll_lua_rotate
1681f860d85SBram Moolenaar #define lua_copy dll_lua_copy
1691f860d85SBram Moolenaar #endif
170bd2f3c3eSBram Moolenaar #define lua_typename dll_lua_typename
1710ba04296SBram Moolenaar #define lua_close dll_lua_close
1720ba04296SBram Moolenaar #define lua_gettop dll_lua_gettop
1730ba04296SBram Moolenaar #define lua_settop dll_lua_settop
1740ba04296SBram Moolenaar #define lua_pushvalue dll_lua_pushvalue
1750ba04296SBram Moolenaar #define lua_isnumber dll_lua_isnumber
1760ba04296SBram Moolenaar #define lua_isstring dll_lua_isstring
1770ba04296SBram Moolenaar #define lua_type dll_lua_type
1780ba04296SBram Moolenaar #define lua_rawequal dll_lua_rawequal
1790ba04296SBram Moolenaar #define lua_toboolean dll_lua_toboolean
1800ba04296SBram Moolenaar #define lua_tolstring dll_lua_tolstring
1810ba04296SBram Moolenaar #define lua_touserdata dll_lua_touserdata
1820ba04296SBram Moolenaar #define lua_pushnil dll_lua_pushnil
1830ba04296SBram Moolenaar #define lua_pushnumber dll_lua_pushnumber
1840ba04296SBram Moolenaar #define lua_pushinteger dll_lua_pushinteger
1850ba04296SBram Moolenaar #define lua_pushlstring dll_lua_pushlstring
1860ba04296SBram Moolenaar #define lua_pushstring dll_lua_pushstring
1870ba04296SBram Moolenaar #define lua_pushfstring dll_lua_pushfstring
1880ba04296SBram Moolenaar #define lua_pushcclosure dll_lua_pushcclosure
1890ba04296SBram Moolenaar #define lua_pushboolean dll_lua_pushboolean
1900ba04296SBram Moolenaar #define lua_pushlightuserdata dll_lua_pushlightuserdata
1910ba04296SBram Moolenaar #define lua_getfield dll_lua_getfield
1920ba04296SBram Moolenaar #define lua_rawget dll_lua_rawget
1931dced572SBram Moolenaar #define lua_rawgeti dll_lua_rawgeti
1940ba04296SBram Moolenaar #define lua_createtable dll_lua_createtable
19511328bc7SYegappan Lakshmanan #define lua_settable dll_lua_settable
196830e3583SBram Moolenaar #if LUA_VERSION_NUM >= 504
197830e3583SBram Moolenaar  #define lua_newuserdatauv dll_lua_newuserdatauv
198830e3583SBram Moolenaar #else
1990ba04296SBram Moolenaar  #define lua_newuserdata dll_lua_newuserdata
200830e3583SBram Moolenaar #endif
2010ba04296SBram Moolenaar #define lua_getmetatable dll_lua_getmetatable
2020ba04296SBram Moolenaar #define lua_setfield dll_lua_setfield
2030ba04296SBram Moolenaar #define lua_rawset dll_lua_rawset
2040ba04296SBram Moolenaar #define lua_rawseti dll_lua_rawseti
2050ba04296SBram Moolenaar #define lua_setmetatable dll_lua_setmetatable
206bd2f3c3eSBram Moolenaar #define lua_next dll_lua_next
2072ab2e860SBram Moolenaar // libs
2080ba04296SBram Moolenaar #define luaopen_base dll_luaopen_base
2090ba04296SBram Moolenaar #define luaopen_table dll_luaopen_table
2100ba04296SBram Moolenaar #define luaopen_string dll_luaopen_string
2110ba04296SBram Moolenaar #define luaopen_math dll_luaopen_math
21216c98f9cSBram Moolenaar #define luaopen_io dll_luaopen_io
2130ba04296SBram Moolenaar #define luaopen_os dll_luaopen_os
2140ba04296SBram Moolenaar #define luaopen_package dll_luaopen_package
2150ba04296SBram Moolenaar #define luaopen_debug dll_luaopen_debug
21616c98f9cSBram Moolenaar #define luaL_openlibs dll_luaL_openlibs
2170ba04296SBram Moolenaar 
2182ab2e860SBram Moolenaar // lauxlib
2191dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501
2200ba04296SBram Moolenaar void (*dll_luaL_register) (lua_State *L, const char *libname, const luaL_Reg *l);
2211dced572SBram Moolenaar char *(*dll_luaL_prepbuffer) (luaL_Buffer *B);
2221dced572SBram Moolenaar void (*dll_luaL_openlib) (lua_State *L, const char *libname, const luaL_Reg *l, int nup);
2230ba04296SBram Moolenaar int (*dll_luaL_typerror) (lua_State *L, int narg, const char *tname);
2241dced572SBram Moolenaar int (*dll_luaL_loadfile) (lua_State *L, const char *filename);
2251dced572SBram Moolenaar int (*dll_luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, const char *name);
2261dced572SBram Moolenaar #else
2271dced572SBram Moolenaar char *(*dll_luaL_prepbuffsize) (luaL_Buffer *B, size_t sz);
2281dced572SBram Moolenaar void (*dll_luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
2291dced572SBram Moolenaar int (*dll_luaL_loadfilex) (lua_State *L, const char *filename, const char *mode);
2301dced572SBram Moolenaar int (*dll_luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode);
2311dced572SBram Moolenaar int (*dll_luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
2321dced572SBram Moolenaar #endif
2335551b131SBram Moolenaar #if LUA_VERSION_NUM >= 504
2345551b131SBram Moolenaar int (*dll_luaL_typeerror) (lua_State *L, int narg, const char *tname);
2355551b131SBram Moolenaar #endif
236bd2f3c3eSBram Moolenaar void (*dll_luaL_checkany) (lua_State *L, int narg);
2370ba04296SBram Moolenaar const char *(*dll_luaL_checklstring) (lua_State *L, int numArg, size_t *l);
2380ba04296SBram Moolenaar lua_Integer (*dll_luaL_checkinteger) (lua_State *L, int numArg);
2390ba04296SBram Moolenaar lua_Integer (*dll_luaL_optinteger) (lua_State *L, int nArg, lua_Integer def);
2400ba04296SBram Moolenaar void (*dll_luaL_checktype) (lua_State *L, int narg, int t);
2410ba04296SBram Moolenaar int (*dll_luaL_error) (lua_State *L, const char *fmt, ...);
2420ba04296SBram Moolenaar lua_State *(*dll_luaL_newstate) (void);
2430ba04296SBram Moolenaar void (*dll_luaL_buffinit) (lua_State *L, luaL_Buffer *B);
2440ba04296SBram Moolenaar void (*dll_luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
2450ba04296SBram Moolenaar void (*dll_luaL_pushresult) (luaL_Buffer *B);
246df1643a6SBram Moolenaar int (*dll_luaL_loadstring) (lua_State *L, const char *s);
2471e4c7d0eSBram Moolenaar int (*dll_luaL_ref) (lua_State *L, int idx);
2481e4c7d0eSBram Moolenaar #if LUA_VERSION_NUM <= 502
2491e4c7d0eSBram Moolenaar void (*dll_luaL_unref) (lua_State *L, int idx, int n);
2501e4c7d0eSBram Moolenaar #else
2511e4c7d0eSBram Moolenaar void (*dll_luaL_unref) (lua_State *L, int idx, lua_Integer n);
2521e4c7d0eSBram Moolenaar #endif
2532ab2e860SBram Moolenaar // lua
2541dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501
2551dced572SBram Moolenaar lua_Number (*dll_lua_tonumber) (lua_State *L, int idx);
2561dced572SBram Moolenaar lua_Integer (*dll_lua_tointeger) (lua_State *L, int idx);
2571dced572SBram Moolenaar void (*dll_lua_call) (lua_State *L, int nargs, int nresults);
2581dced572SBram Moolenaar int (*dll_lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
2591dced572SBram Moolenaar #else
2601dced572SBram Moolenaar lua_Number (*dll_lua_tonumberx) (lua_State *L, int idx, int *isnum);
2611dced572SBram Moolenaar lua_Integer (*dll_lua_tointegerx) (lua_State *L, int idx, int *isnum);
2621dced572SBram Moolenaar void (*dll_lua_callk) (lua_State *L, int nargs, int nresults, int ctx,
2631dced572SBram Moolenaar 	lua_CFunction k);
2641dced572SBram Moolenaar int (*dll_lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc,
2651dced572SBram Moolenaar 	int ctx, lua_CFunction k);
2661dced572SBram Moolenaar void (*dll_lua_getglobal) (lua_State *L, const char *var);
2671dced572SBram Moolenaar void (*dll_lua_setglobal) (lua_State *L, const char *var);
2681f860d85SBram Moolenaar #endif
2691f860d85SBram Moolenaar #if LUA_VERSION_NUM <= 502
2701f860d85SBram Moolenaar void (*dll_lua_replace) (lua_State *L, int idx);
2711f860d85SBram Moolenaar void (*dll_lua_remove) (lua_State *L, int idx);
2721f860d85SBram Moolenaar #endif
2731f860d85SBram Moolenaar #if LUA_VERSION_NUM >= 503
2741f860d85SBram Moolenaar void  (*dll_lua_rotate) (lua_State *L, int idx, int n);
2759514b1f9SBram Moolenaar void (*dll_lua_copy) (lua_State *L, int fromidx, int toidx);
2761dced572SBram Moolenaar #endif
277bd2f3c3eSBram Moolenaar const char *(*dll_lua_typename) (lua_State *L, int tp);
2780ba04296SBram Moolenaar void       (*dll_lua_close) (lua_State *L);
2790ba04296SBram Moolenaar int (*dll_lua_gettop) (lua_State *L);
2800ba04296SBram Moolenaar void (*dll_lua_settop) (lua_State *L, int idx);
2810ba04296SBram Moolenaar void (*dll_lua_pushvalue) (lua_State *L, int idx);
2820ba04296SBram Moolenaar int (*dll_lua_isnumber) (lua_State *L, int idx);
2830ba04296SBram Moolenaar int (*dll_lua_isstring) (lua_State *L, int idx);
2840ba04296SBram Moolenaar int (*dll_lua_type) (lua_State *L, int idx);
2850ba04296SBram Moolenaar int (*dll_lua_rawequal) (lua_State *L, int idx1, int idx2);
2860ba04296SBram Moolenaar int (*dll_lua_toboolean) (lua_State *L, int idx);
2870ba04296SBram Moolenaar const char *(*dll_lua_tolstring) (lua_State *L, int idx, size_t *len);
2880ba04296SBram Moolenaar void *(*dll_lua_touserdata) (lua_State *L, int idx);
2890ba04296SBram Moolenaar void (*dll_lua_pushnil) (lua_State *L);
2900ba04296SBram Moolenaar void (*dll_lua_pushnumber) (lua_State *L, lua_Number n);
2910ba04296SBram Moolenaar void (*dll_lua_pushinteger) (lua_State *L, lua_Integer n);
2920ba04296SBram Moolenaar void (*dll_lua_pushlstring) (lua_State *L, const char *s, size_t l);
2930ba04296SBram Moolenaar void (*dll_lua_pushstring) (lua_State *L, const char *s);
2940ba04296SBram Moolenaar const char *(*dll_lua_pushfstring) (lua_State *L, const char *fmt, ...);
2950ba04296SBram Moolenaar void (*dll_lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
2960ba04296SBram Moolenaar void (*dll_lua_pushboolean) (lua_State *L, int b);
2970ba04296SBram Moolenaar void (*dll_lua_pushlightuserdata) (lua_State *L, void *p);
2980ba04296SBram Moolenaar void (*dll_lua_getfield) (lua_State *L, int idx, const char *k);
29917413671SBram Moolenaar #if LUA_VERSION_NUM <= 502
3000ba04296SBram Moolenaar void (*dll_lua_rawget) (lua_State *L, int idx);
3011dced572SBram Moolenaar void (*dll_lua_rawgeti) (lua_State *L, int idx, int n);
30217413671SBram Moolenaar #else
30317413671SBram Moolenaar int (*dll_lua_rawget) (lua_State *L, int idx);
30417413671SBram Moolenaar int (*dll_lua_rawgeti) (lua_State *L, int idx, lua_Integer n);
30517413671SBram Moolenaar #endif
3060ba04296SBram Moolenaar void (*dll_lua_createtable) (lua_State *L, int narr, int nrec);
30711328bc7SYegappan Lakshmanan void (*dll_lua_settable) (lua_State *L, int idx);
308830e3583SBram Moolenaar #if LUA_VERSION_NUM >= 504
309830e3583SBram Moolenaar void *(*dll_lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue);
310830e3583SBram Moolenaar #else
3110ba04296SBram Moolenaar void *(*dll_lua_newuserdata) (lua_State *L, size_t sz);
312830e3583SBram Moolenaar #endif
3130ba04296SBram Moolenaar int (*dll_lua_getmetatable) (lua_State *L, int objindex);
3140ba04296SBram Moolenaar void (*dll_lua_setfield) (lua_State *L, int idx, const char *k);
3150ba04296SBram Moolenaar void (*dll_lua_rawset) (lua_State *L, int idx);
31617413671SBram Moolenaar #if LUA_VERSION_NUM <= 502
3170ba04296SBram Moolenaar void (*dll_lua_rawseti) (lua_State *L, int idx, int n);
31817413671SBram Moolenaar #else
31917413671SBram Moolenaar void (*dll_lua_rawseti) (lua_State *L, int idx, lua_Integer n);
32017413671SBram Moolenaar #endif
3210ba04296SBram Moolenaar int (*dll_lua_setmetatable) (lua_State *L, int objindex);
322bd2f3c3eSBram Moolenaar int (*dll_lua_next) (lua_State *L, int idx);
3232ab2e860SBram Moolenaar // libs
3240ba04296SBram Moolenaar int (*dll_luaopen_base) (lua_State *L);
3250ba04296SBram Moolenaar int (*dll_luaopen_table) (lua_State *L);
3260ba04296SBram Moolenaar int (*dll_luaopen_string) (lua_State *L);
3270ba04296SBram Moolenaar int (*dll_luaopen_math) (lua_State *L);
32816c98f9cSBram Moolenaar int (*dll_luaopen_io) (lua_State *L);
3290ba04296SBram Moolenaar int (*dll_luaopen_os) (lua_State *L);
3300ba04296SBram Moolenaar int (*dll_luaopen_package) (lua_State *L);
3310ba04296SBram Moolenaar int (*dll_luaopen_debug) (lua_State *L);
33216c98f9cSBram Moolenaar void (*dll_luaL_openlibs) (lua_State *L);
3330ba04296SBram Moolenaar 
3340ba04296SBram Moolenaar typedef void **luaV_function;
3350ba04296SBram Moolenaar typedef struct {
3360ba04296SBram Moolenaar     const char *name;
3370ba04296SBram Moolenaar     luaV_function func;
3380ba04296SBram Moolenaar } luaV_Reg;
3390ba04296SBram Moolenaar 
3400ba04296SBram Moolenaar static const luaV_Reg luaV_dll[] = {
3412ab2e860SBram Moolenaar     // lauxlib
3421dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501
3430ba04296SBram Moolenaar     {"luaL_register", (luaV_function) &dll_luaL_register},
3441dced572SBram Moolenaar     {"luaL_prepbuffer", (luaV_function) &dll_luaL_prepbuffer},
3451dced572SBram Moolenaar     {"luaL_openlib", (luaV_function) &dll_luaL_openlib},
3460ba04296SBram Moolenaar     {"luaL_typerror", (luaV_function) &dll_luaL_typerror},
3471dced572SBram Moolenaar     {"luaL_loadfile", (luaV_function) &dll_luaL_loadfile},
3481dced572SBram Moolenaar     {"luaL_loadbuffer", (luaV_function) &dll_luaL_loadbuffer},
3491dced572SBram Moolenaar #else
3501dced572SBram Moolenaar     {"luaL_prepbuffsize", (luaV_function) &dll_luaL_prepbuffsize},
3511dced572SBram Moolenaar     {"luaL_setfuncs", (luaV_function) &dll_luaL_setfuncs},
3521dced572SBram Moolenaar     {"luaL_loadfilex", (luaV_function) &dll_luaL_loadfilex},
3531dced572SBram Moolenaar     {"luaL_loadbufferx", (luaV_function) &dll_luaL_loadbufferx},
3541dced572SBram Moolenaar     {"luaL_argerror", (luaV_function) &dll_luaL_argerror},
3551dced572SBram Moolenaar #endif
3565551b131SBram Moolenaar #if LUA_VERSION_NUM >= 504
3575551b131SBram Moolenaar     {"luaL_typeerror", (luaV_function) &dll_luaL_typeerror},
3585551b131SBram Moolenaar #endif
359bd2f3c3eSBram Moolenaar     {"luaL_checkany", (luaV_function) &dll_luaL_checkany},
3600ba04296SBram Moolenaar     {"luaL_checklstring", (luaV_function) &dll_luaL_checklstring},
3610ba04296SBram Moolenaar     {"luaL_checkinteger", (luaV_function) &dll_luaL_checkinteger},
3620ba04296SBram Moolenaar     {"luaL_optinteger", (luaV_function) &dll_luaL_optinteger},
3630ba04296SBram Moolenaar     {"luaL_checktype", (luaV_function) &dll_luaL_checktype},
3640ba04296SBram Moolenaar     {"luaL_error", (luaV_function) &dll_luaL_error},
3650ba04296SBram Moolenaar     {"luaL_newstate", (luaV_function) &dll_luaL_newstate},
3660ba04296SBram Moolenaar     {"luaL_buffinit", (luaV_function) &dll_luaL_buffinit},
3670ba04296SBram Moolenaar     {"luaL_addlstring", (luaV_function) &dll_luaL_addlstring},
3680ba04296SBram Moolenaar     {"luaL_pushresult", (luaV_function) &dll_luaL_pushresult},
369df1643a6SBram Moolenaar     {"luaL_loadstring", (luaV_function) &dll_luaL_loadstring},
3701e4c7d0eSBram Moolenaar     {"luaL_ref", (luaV_function) &dll_luaL_ref},
3711e4c7d0eSBram Moolenaar     {"luaL_unref", (luaV_function) &dll_luaL_unref},
3722ab2e860SBram Moolenaar     // lua
3731dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501
3741dced572SBram Moolenaar     {"lua_tonumber", (luaV_function) &dll_lua_tonumber},
3751dced572SBram Moolenaar     {"lua_tointeger", (luaV_function) &dll_lua_tointeger},
3761dced572SBram Moolenaar     {"lua_call", (luaV_function) &dll_lua_call},
3771dced572SBram Moolenaar     {"lua_pcall", (luaV_function) &dll_lua_pcall},
3781dced572SBram Moolenaar #else
3791dced572SBram Moolenaar     {"lua_tonumberx", (luaV_function) &dll_lua_tonumberx},
3801dced572SBram Moolenaar     {"lua_tointegerx", (luaV_function) &dll_lua_tointegerx},
3811dced572SBram Moolenaar     {"lua_callk", (luaV_function) &dll_lua_callk},
3821dced572SBram Moolenaar     {"lua_pcallk", (luaV_function) &dll_lua_pcallk},
3831dced572SBram Moolenaar     {"lua_getglobal", (luaV_function) &dll_lua_getglobal},
3841dced572SBram Moolenaar     {"lua_setglobal", (luaV_function) &dll_lua_setglobal},
3851dced572SBram Moolenaar #endif
3861f860d85SBram Moolenaar #if LUA_VERSION_NUM <= 502
3871f860d85SBram Moolenaar     {"lua_replace", (luaV_function) &dll_lua_replace},
3881f860d85SBram Moolenaar     {"lua_remove", (luaV_function) &dll_lua_remove},
3891f860d85SBram Moolenaar #endif
3901f860d85SBram Moolenaar #if LUA_VERSION_NUM >= 503
3911f860d85SBram Moolenaar     {"lua_rotate", (luaV_function) &dll_lua_rotate},
3921f860d85SBram Moolenaar     {"lua_copy", (luaV_function) &dll_lua_copy},
3931f860d85SBram Moolenaar #endif
394bd2f3c3eSBram Moolenaar     {"lua_typename", (luaV_function) &dll_lua_typename},
3950ba04296SBram Moolenaar     {"lua_close", (luaV_function) &dll_lua_close},
3960ba04296SBram Moolenaar     {"lua_gettop", (luaV_function) &dll_lua_gettop},
3970ba04296SBram Moolenaar     {"lua_settop", (luaV_function) &dll_lua_settop},
3980ba04296SBram Moolenaar     {"lua_pushvalue", (luaV_function) &dll_lua_pushvalue},
3990ba04296SBram Moolenaar     {"lua_isnumber", (luaV_function) &dll_lua_isnumber},
4000ba04296SBram Moolenaar     {"lua_isstring", (luaV_function) &dll_lua_isstring},
4010ba04296SBram Moolenaar     {"lua_type", (luaV_function) &dll_lua_type},
4020ba04296SBram Moolenaar     {"lua_rawequal", (luaV_function) &dll_lua_rawequal},
4030ba04296SBram Moolenaar     {"lua_toboolean", (luaV_function) &dll_lua_toboolean},
4040ba04296SBram Moolenaar     {"lua_tolstring", (luaV_function) &dll_lua_tolstring},
4050ba04296SBram Moolenaar     {"lua_touserdata", (luaV_function) &dll_lua_touserdata},
4060ba04296SBram Moolenaar     {"lua_pushnil", (luaV_function) &dll_lua_pushnil},
4070ba04296SBram Moolenaar     {"lua_pushnumber", (luaV_function) &dll_lua_pushnumber},
4080ba04296SBram Moolenaar     {"lua_pushinteger", (luaV_function) &dll_lua_pushinteger},
4090ba04296SBram Moolenaar     {"lua_pushlstring", (luaV_function) &dll_lua_pushlstring},
4100ba04296SBram Moolenaar     {"lua_pushstring", (luaV_function) &dll_lua_pushstring},
4110ba04296SBram Moolenaar     {"lua_pushfstring", (luaV_function) &dll_lua_pushfstring},
4120ba04296SBram Moolenaar     {"lua_pushcclosure", (luaV_function) &dll_lua_pushcclosure},
4130ba04296SBram Moolenaar     {"lua_pushboolean", (luaV_function) &dll_lua_pushboolean},
4140ba04296SBram Moolenaar     {"lua_pushlightuserdata", (luaV_function) &dll_lua_pushlightuserdata},
4150ba04296SBram Moolenaar     {"lua_getfield", (luaV_function) &dll_lua_getfield},
4160ba04296SBram Moolenaar     {"lua_rawget", (luaV_function) &dll_lua_rawget},
4171dced572SBram Moolenaar     {"lua_rawgeti", (luaV_function) &dll_lua_rawgeti},
4180ba04296SBram Moolenaar     {"lua_createtable", (luaV_function) &dll_lua_createtable},
41911328bc7SYegappan Lakshmanan     {"lua_settable", (luaV_function) &dll_lua_settable},
420830e3583SBram Moolenaar #if LUA_VERSION_NUM >= 504
421830e3583SBram Moolenaar     {"lua_newuserdatauv", (luaV_function) &dll_lua_newuserdatauv},
422830e3583SBram Moolenaar #else
4230ba04296SBram Moolenaar     {"lua_newuserdata", (luaV_function) &dll_lua_newuserdata},
424830e3583SBram Moolenaar #endif
4250ba04296SBram Moolenaar     {"lua_getmetatable", (luaV_function) &dll_lua_getmetatable},
4260ba04296SBram Moolenaar     {"lua_setfield", (luaV_function) &dll_lua_setfield},
4270ba04296SBram Moolenaar     {"lua_rawset", (luaV_function) &dll_lua_rawset},
4280ba04296SBram Moolenaar     {"lua_rawseti", (luaV_function) &dll_lua_rawseti},
4290ba04296SBram Moolenaar     {"lua_setmetatable", (luaV_function) &dll_lua_setmetatable},
430bd2f3c3eSBram Moolenaar     {"lua_next", (luaV_function) &dll_lua_next},
4312ab2e860SBram Moolenaar     // libs
4320ba04296SBram Moolenaar     {"luaopen_base", (luaV_function) &dll_luaopen_base},
4330ba04296SBram Moolenaar     {"luaopen_table", (luaV_function) &dll_luaopen_table},
4340ba04296SBram Moolenaar     {"luaopen_string", (luaV_function) &dll_luaopen_string},
4350ba04296SBram Moolenaar     {"luaopen_math", (luaV_function) &dll_luaopen_math},
43616c98f9cSBram Moolenaar     {"luaopen_io", (luaV_function) &dll_luaopen_io},
4370ba04296SBram Moolenaar     {"luaopen_os", (luaV_function) &dll_luaopen_os},
4380ba04296SBram Moolenaar     {"luaopen_package", (luaV_function) &dll_luaopen_package},
4390ba04296SBram Moolenaar     {"luaopen_debug", (luaV_function) &dll_luaopen_debug},
44016c98f9cSBram Moolenaar     {"luaL_openlibs", (luaV_function) &dll_luaL_openlibs},
4410ba04296SBram Moolenaar     {NULL, NULL}
4420ba04296SBram Moolenaar };
4430ba04296SBram Moolenaar 
4442334b6d5SBram Moolenaar static HANDLE hinstLua = NULL;
4450ba04296SBram Moolenaar 
44655d5c034SBram Moolenaar     static int
lua_link_init(char * libname,int verbose)44755d5c034SBram Moolenaar lua_link_init(char *libname, int verbose)
44855d5c034SBram Moolenaar {
4490ba04296SBram Moolenaar     const luaV_Reg *reg;
4500ba04296SBram Moolenaar     if (hinstLua) return OK;
4512334b6d5SBram Moolenaar     hinstLua = load_dll(libname);
45255d5c034SBram Moolenaar     if (!hinstLua)
45355d5c034SBram Moolenaar     {
45455d5c034SBram Moolenaar 	if (verbose)
4551a3e5747SMartin Tournoij 	    semsg(_(e_loadlib), libname, load_dll_error());
4560ba04296SBram Moolenaar 	return FAIL;
4570ba04296SBram Moolenaar     }
45855d5c034SBram Moolenaar     for (reg = luaV_dll; reg->func; reg++)
45955d5c034SBram Moolenaar     {
4602334b6d5SBram Moolenaar 	if ((*reg->func = symbol_from_dll(hinstLua, reg->name)) == NULL)
4612334b6d5SBram Moolenaar 	{
4622334b6d5SBram Moolenaar 	    close_dll(hinstLua);
4630ba04296SBram Moolenaar 	    hinstLua = 0;
46455d5c034SBram Moolenaar 	    if (verbose)
465f9e3e09fSBram Moolenaar 		semsg(_(e_loadfunc), reg->name);
4660ba04296SBram Moolenaar 	    return FAIL;
4670ba04296SBram Moolenaar 	}
4680ba04296SBram Moolenaar     }
4690ba04296SBram Moolenaar     return OK;
4700ba04296SBram Moolenaar }
4712ab2e860SBram Moolenaar #endif // DYNAMIC_LUA
4720ba04296SBram Moolenaar 
473d90b6c02SBram Moolenaar #if defined(DYNAMIC_LUA) || defined(PROTO)
47455d5c034SBram Moolenaar     int
lua_enabled(int verbose)47555d5c034SBram Moolenaar lua_enabled(int verbose)
47655d5c034SBram Moolenaar {
47725e4fcdeSBram Moolenaar     return lua_link_init((char *)p_luadll, verbose) == OK;
4780ba04296SBram Moolenaar }
479d90b6c02SBram Moolenaar #endif
4800ba04296SBram Moolenaar 
4815551b131SBram Moolenaar #if LUA_VERSION_NUM > 501 && LUA_VERSION_NUM < 504
4821dced572SBram Moolenaar     static int
luaL_typeerror(lua_State * L,int narg,const char * tname)4831dced572SBram Moolenaar luaL_typeerror(lua_State *L, int narg, const char *tname)
4841dced572SBram Moolenaar {
4851dced572SBram Moolenaar     const char *msg = lua_pushfstring(L, "%s expected, got %s",
4861dced572SBram Moolenaar 	    tname, luaL_typename(L, narg));
4871dced572SBram Moolenaar     return luaL_argerror(L, narg, msg);
4881dced572SBram Moolenaar }
4891dced572SBram Moolenaar #endif
4901dced572SBram Moolenaar 
4910ba04296SBram Moolenaar 
4922ab2e860SBram Moolenaar // =======   Internal   =======
4930ba04296SBram Moolenaar 
49455d5c034SBram Moolenaar     static void
luaV_newmetatable(lua_State * L,const char * tname)49555d5c034SBram Moolenaar luaV_newmetatable(lua_State *L, const char *tname)
49655d5c034SBram Moolenaar {
4970ba04296SBram Moolenaar     lua_newtable(L);
4980ba04296SBram Moolenaar     lua_pushlightuserdata(L, (void *) tname);
4990ba04296SBram Moolenaar     lua_pushvalue(L, -2);
5000ba04296SBram Moolenaar     lua_rawset(L, LUA_REGISTRYINDEX);
5010ba04296SBram Moolenaar }
5020ba04296SBram Moolenaar 
50355d5c034SBram Moolenaar     static void *
luaV_toudata(lua_State * L,int ud,const char * tname)50455d5c034SBram Moolenaar luaV_toudata(lua_State *L, int ud, const char *tname)
50555d5c034SBram Moolenaar {
5060ba04296SBram Moolenaar     void *p = lua_touserdata(L, ud);
50755d5c034SBram Moolenaar 
5082ab2e860SBram Moolenaar     if (p != NULL) // value is userdata?
50955d5c034SBram Moolenaar     {
5102ab2e860SBram Moolenaar 	if (lua_getmetatable(L, ud)) // does it have a metatable?
51155d5c034SBram Moolenaar 	{
5122ab2e860SBram Moolenaar 	    luaV_getfield(L, tname); // get metatable
5132ab2e860SBram Moolenaar 	    if (lua_rawequal(L, -1, -2)) // MTs match?
51455d5c034SBram Moolenaar 	    {
5152ab2e860SBram Moolenaar 		lua_pop(L, 2); // MTs
5160ba04296SBram Moolenaar 		return p;
5170ba04296SBram Moolenaar 	    }
5180ba04296SBram Moolenaar 	}
5190ba04296SBram Moolenaar     }
5200ba04296SBram Moolenaar     return NULL;
5210ba04296SBram Moolenaar }
5220ba04296SBram Moolenaar 
52355d5c034SBram Moolenaar     static void *
luaV_checkcache(lua_State * L,void * p)5241dced572SBram Moolenaar luaV_checkcache(lua_State *L, void *p)
5251dced572SBram Moolenaar {
5261dced572SBram Moolenaar     luaV_getudata(L, p);
5271dced572SBram Moolenaar     if (lua_isnil(L, -1)) luaL_error(L, "invalid object");
5281dced572SBram Moolenaar     lua_pop(L, 1);
5291dced572SBram Moolenaar     return p;
5301dced572SBram Moolenaar }
5311dced572SBram Moolenaar 
5321dced572SBram Moolenaar #define luaV_unbox(L,luatyp,ud) (*((luatyp *) lua_touserdata((L),(ud))))
5331dced572SBram Moolenaar 
5341dced572SBram Moolenaar #define luaV_checkvalid(L,luatyp,ud) \
5351dced572SBram Moolenaar     luaV_checkcache((L), (void *) luaV_unbox((L),luatyp,(ud)))
5361dced572SBram Moolenaar 
5371dced572SBram Moolenaar     static void *
luaV_checkudata(lua_State * L,int ud,const char * tname)53855d5c034SBram Moolenaar luaV_checkudata(lua_State *L, int ud, const char *tname)
53955d5c034SBram Moolenaar {
5400ba04296SBram Moolenaar     void *p = luaV_toudata(L, ud, tname);
5411dced572SBram Moolenaar     if (p == NULL) luaL_typeerror(L, ud, tname);
5420ba04296SBram Moolenaar     return p;
5430ba04296SBram Moolenaar }
5440ba04296SBram Moolenaar 
54555d5c034SBram Moolenaar     static void
luaV_pushtypval(lua_State * L,typval_T * tv)54655d5c034SBram Moolenaar luaV_pushtypval(lua_State *L, typval_T *tv)
54755d5c034SBram Moolenaar {
5481dced572SBram Moolenaar     if (tv == NULL)
5491dced572SBram Moolenaar     {
5501dced572SBram Moolenaar 	lua_pushnil(L);
5511dced572SBram Moolenaar 	return;
5521dced572SBram Moolenaar     }
55355d5c034SBram Moolenaar     switch (tv->v_type)
55455d5c034SBram Moolenaar     {
5550ba04296SBram Moolenaar 	case VAR_STRING:
556d04da7cbSBram Moolenaar 	    lua_pushstring(L, tv->vval.v_string == NULL
557d04da7cbSBram Moolenaar 					    ? "" : (char *)tv->vval.v_string);
5580ba04296SBram Moolenaar 	    break;
5590ba04296SBram Moolenaar 	case VAR_NUMBER:
5600ba04296SBram Moolenaar 	    lua_pushinteger(L, (int) tv->vval.v_number);
5610ba04296SBram Moolenaar 	    break;
5620ba04296SBram Moolenaar #ifdef FEAT_FLOAT
5630ba04296SBram Moolenaar 	case VAR_FLOAT:
5640ba04296SBram Moolenaar 	    lua_pushnumber(L, (lua_Number) tv->vval.v_float);
5650ba04296SBram Moolenaar 	    break;
5660ba04296SBram Moolenaar #endif
5671dced572SBram Moolenaar 	case VAR_LIST:
5681dced572SBram Moolenaar 	    luaV_pushlist(L, tv->vval.v_list);
5690ba04296SBram Moolenaar 	    break;
5701dced572SBram Moolenaar 	case VAR_DICT:
5711dced572SBram Moolenaar 	    luaV_pushdict(L, tv->vval.v_dict);
5721dced572SBram Moolenaar 	    break;
5739b4a15d5SBram Moolenaar 	case VAR_BOOL:
574520e1e41SBram Moolenaar 	case VAR_SPECIAL:
575520e1e41SBram Moolenaar 	    if (tv->vval.v_number <= VVAL_TRUE)
576520e1e41SBram Moolenaar 		lua_pushinteger(L, (int) tv->vval.v_number);
577520e1e41SBram Moolenaar 	    else
578520e1e41SBram Moolenaar 		lua_pushnil(L);
579520e1e41SBram Moolenaar 	    break;
580ca06da92SBram Moolenaar 	case VAR_FUNC:
5814eefe47eSBram Moolenaar 	    luaV_pushfuncref(L, tv->vval.v_string);
582ca06da92SBram Moolenaar 	    break;
58386c3a216SBram Moolenaar 	case VAR_PARTIAL:
58486c3a216SBram Moolenaar 	    // TODO: handle partial arguments
58586c3a216SBram Moolenaar 	    luaV_pushfuncref(L, partial_name(tv->vval.v_partial));
58686c3a216SBram Moolenaar 	    break;
58786c3a216SBram Moolenaar 
588b7828690SBram Moolenaar 	case VAR_BLOB:
589b7828690SBram Moolenaar 	    luaV_pushblob(L, tv->vval.v_blob);
590b7828690SBram Moolenaar 	    break;
5911dced572SBram Moolenaar 	default:
5921dced572SBram Moolenaar 	    lua_pushnil(L);
5930ba04296SBram Moolenaar     }
5941dced572SBram Moolenaar }
59555d5c034SBram Moolenaar 
596ca06da92SBram Moolenaar /*
597ca06da92SBram Moolenaar  * Converts lua value at 'pos' to typval 'tv'.
598ca06da92SBram Moolenaar  * Returns OK or FAIL.
599ca06da92SBram Moolenaar  */
600ca06da92SBram Moolenaar     static int
luaV_totypval(lua_State * L,int pos,typval_T * tv)6011dced572SBram Moolenaar luaV_totypval(lua_State *L, int pos, typval_T *tv)
60255d5c034SBram Moolenaar {
603ca06da92SBram Moolenaar     int status = OK;
604ca06da92SBram Moolenaar 
605a9a8e5f0SBram Moolenaar     tv->v_lock = 0;
606a9a8e5f0SBram Moolenaar 
607ca06da92SBram Moolenaar     switch (lua_type(L, pos))
608ca06da92SBram Moolenaar     {
6091dced572SBram Moolenaar 	case LUA_TBOOLEAN:
6109b4a15d5SBram Moolenaar 	    tv->v_type = VAR_BOOL;
6111dced572SBram Moolenaar 	    tv->vval.v_number = (varnumber_T) lua_toboolean(L, pos);
6121dced572SBram Moolenaar 	    break;
6139067cd6cSBram Moolenaar 	case LUA_TNIL:
6149067cd6cSBram Moolenaar 	    tv->v_type = VAR_SPECIAL;
6159067cd6cSBram Moolenaar 	    tv->vval.v_number = VVAL_NULL;
6169067cd6cSBram Moolenaar 	    break;
6171dced572SBram Moolenaar 	case LUA_TSTRING:
6181dced572SBram Moolenaar 	    tv->v_type = VAR_STRING;
6191dced572SBram Moolenaar 	    tv->vval.v_string = vim_strsave((char_u *) lua_tostring(L, pos));
6201dced572SBram Moolenaar 	    break;
6211dced572SBram Moolenaar 	case LUA_TNUMBER:
6221dced572SBram Moolenaar #ifdef FEAT_FLOAT
623eb04f089SBram Moolenaar 	{
624eb04f089SBram Moolenaar 	    const lua_Number n = lua_tonumber(L, pos);
625eb04f089SBram Moolenaar 
626eb04f089SBram Moolenaar 	    if (n > (lua_Number)INT64_MAX || n < (lua_Number)INT64_MIN
627eb04f089SBram Moolenaar 		    || ((lua_Number)((varnumber_T)n)) != n)
628eb04f089SBram Moolenaar 	    {
6291dced572SBram Moolenaar 		tv->v_type = VAR_FLOAT;
630eb04f089SBram Moolenaar 		tv->vval.v_float = (float_T)n;
631eb04f089SBram Moolenaar 	    }
632eb04f089SBram Moolenaar 	    else
633eb04f089SBram Moolenaar 	    {
634eb04f089SBram Moolenaar 		tv->v_type = VAR_NUMBER;
635eb04f089SBram Moolenaar 		tv->vval.v_number = (varnumber_T)n;
636eb04f089SBram Moolenaar 	    }
637eb04f089SBram Moolenaar 	}
6381dced572SBram Moolenaar #else
6391dced572SBram Moolenaar 	    tv->v_type = VAR_NUMBER;
6401dced572SBram Moolenaar 	    tv->vval.v_number = (varnumber_T) lua_tointeger(L, pos);
6411dced572SBram Moolenaar #endif
6421dced572SBram Moolenaar 	    break;
643801ab069SBram Moolenaar 	case LUA_TFUNCTION:
644801ab069SBram Moolenaar 	{
645801ab069SBram Moolenaar 	    char_u *name;
646066e7da3SBram Moolenaar 	    luaV_CFuncState *state;
647066e7da3SBram Moolenaar 
648801ab069SBram Moolenaar 	    lua_pushvalue(L, pos);
649066e7da3SBram Moolenaar 	    state = ALLOC_CLEAR_ONE(luaV_CFuncState);
650801ab069SBram Moolenaar 	    state->lua_funcref = luaL_ref(L, LUA_REGISTRYINDEX);
651801ab069SBram Moolenaar 	    state->L = L;
652801ab069SBram Moolenaar 	    state->lua_tableref = LUA_NOREF;
653801ab069SBram Moolenaar 	    name = register_cfunc(&luaV_call_lua_func,
654801ab069SBram Moolenaar 					      &luaV_call_lua_func_free, state);
655801ab069SBram Moolenaar 	    tv->v_type = VAR_FUNC;
656801ab069SBram Moolenaar 	    tv->vval.v_string = vim_strsave(name);
657801ab069SBram Moolenaar 	    break;
658801ab069SBram Moolenaar 	}
659801ab069SBram Moolenaar 	case LUA_TTABLE:
660801ab069SBram Moolenaar 	{
661066e7da3SBram Moolenaar 	    int lua_tableref;
662066e7da3SBram Moolenaar 
663801ab069SBram Moolenaar 	    lua_pushvalue(L, pos);
664066e7da3SBram Moolenaar 	    lua_tableref = luaL_ref(L, LUA_REGISTRYINDEX);
665801ab069SBram Moolenaar 	    if (lua_getmetatable(L, pos)) {
666801ab069SBram Moolenaar 		lua_getfield(L, -1, LUA___CALL);
667801ab069SBram Moolenaar 		if (lua_isfunction(L, -1)) {
668801ab069SBram Moolenaar 		    char_u *name;
669801ab069SBram Moolenaar 		    int lua_funcref = luaL_ref(L, LUA_REGISTRYINDEX);
670801ab069SBram Moolenaar 		    luaV_CFuncState *state = ALLOC_CLEAR_ONE(luaV_CFuncState);
671066e7da3SBram Moolenaar 
672801ab069SBram Moolenaar 		    state->lua_funcref = lua_funcref;
673801ab069SBram Moolenaar 		    state->L = L;
674801ab069SBram Moolenaar 		    state->lua_tableref = lua_tableref;
675801ab069SBram Moolenaar 		    name = register_cfunc(&luaV_call_lua_func,
676801ab069SBram Moolenaar 					      &luaV_call_lua_func_free, state);
677801ab069SBram Moolenaar 		    tv->v_type = VAR_FUNC;
678801ab069SBram Moolenaar 		    tv->vval.v_string = vim_strsave(name);
679801ab069SBram Moolenaar 		    break;
680801ab069SBram Moolenaar 		}
681801ab069SBram Moolenaar 	    }
682801ab069SBram Moolenaar 	    tv->v_type = VAR_NUMBER;
683801ab069SBram Moolenaar 	    tv->vval.v_number = 0;
684801ab069SBram Moolenaar 	    status = FAIL;
685801ab069SBram Moolenaar 	    break;
686801ab069SBram Moolenaar 	}
687ca06da92SBram Moolenaar 	case LUA_TUSERDATA:
688ca06da92SBram Moolenaar 	{
6891dced572SBram Moolenaar 	    void *p = lua_touserdata(L, pos);
690ca06da92SBram Moolenaar 
691b7828690SBram Moolenaar 	    if (lua_getmetatable(L, pos)) // has metatable?
6922334b6d5SBram Moolenaar 	    {
693b7828690SBram Moolenaar 		// check list
6941dced572SBram Moolenaar 		luaV_getfield(L, LUAVIM_LIST);
6951dced572SBram Moolenaar 		if (lua_rawequal(L, -1, -2))
69655d5c034SBram Moolenaar 		{
6971dced572SBram Moolenaar 		    tv->v_type = VAR_LIST;
6981dced572SBram Moolenaar 		    tv->vval.v_list = *((luaV_List *) p);
6991dced572SBram Moolenaar 		    ++tv->vval.v_list->lv_refcount;
700b7828690SBram Moolenaar 		    lua_pop(L, 2); // MTs
701ca06da92SBram Moolenaar 		    break;
7021dced572SBram Moolenaar 		}
703b7828690SBram Moolenaar 		// check dict
7041dced572SBram Moolenaar 		luaV_getfield(L, LUAVIM_DICT);
7051dced572SBram Moolenaar 		if (lua_rawequal(L, -1, -3))
70655d5c034SBram Moolenaar 		{
7071dced572SBram Moolenaar 		    tv->v_type = VAR_DICT;
7081dced572SBram Moolenaar 		    tv->vval.v_dict = *((luaV_Dict *) p);
7091dced572SBram Moolenaar 		    ++tv->vval.v_dict->dv_refcount;
710b7828690SBram Moolenaar 		    lua_pop(L, 3); // MTs
7110ba04296SBram Moolenaar 		    break;
7120ba04296SBram Moolenaar 		}
713b7828690SBram Moolenaar 		// check blob
714b7828690SBram Moolenaar 		luaV_getfield(L, LUAVIM_BLOB);
715ca06da92SBram Moolenaar 		if (lua_rawequal(L, -1, -4))
716ca06da92SBram Moolenaar 		{
717b7828690SBram Moolenaar 		    tv->v_type = VAR_BLOB;
718b7828690SBram Moolenaar 		    tv->vval.v_blob = *((luaV_Blob *) p);
719b7828690SBram Moolenaar 		    ++tv->vval.v_blob->bv_refcount;
720b7828690SBram Moolenaar 		    lua_pop(L, 4); // MTs
721b7828690SBram Moolenaar 		    break;
722b7828690SBram Moolenaar 		}
723b7828690SBram Moolenaar 		// check funcref
724b7828690SBram Moolenaar 		luaV_getfield(L, LUAVIM_FUNCREF);
725b7828690SBram Moolenaar 		if (lua_rawequal(L, -1, -5))
726b7828690SBram Moolenaar 		{
727ca06da92SBram Moolenaar 		    luaV_Funcref *f = (luaV_Funcref *) p;
728066e7da3SBram Moolenaar 
7294eefe47eSBram Moolenaar 		    func_ref(f->name);
7304eefe47eSBram Moolenaar 		    tv->v_type = VAR_FUNC;
7314eefe47eSBram Moolenaar 		    tv->vval.v_string = vim_strsave(f->name);
732b7828690SBram Moolenaar 		    lua_pop(L, 5); // MTs
733ca06da92SBram Moolenaar 		    break;
734ca06da92SBram Moolenaar 		}
735b7828690SBram Moolenaar 		lua_pop(L, 4); // MTs
736ca06da92SBram Moolenaar 	    }
737ca06da92SBram Moolenaar 	}
738b7828690SBram Moolenaar 	// FALLTHROUGH
7390ba04296SBram Moolenaar 	default:
7401dced572SBram Moolenaar 	    tv->v_type = VAR_NUMBER;
7411dced572SBram Moolenaar 	    tv->vval.v_number = 0;
742ca06da92SBram Moolenaar 	    status = FAIL;
7430ba04296SBram Moolenaar     }
744ca06da92SBram Moolenaar     return status;
7450ba04296SBram Moolenaar }
7460ba04296SBram Moolenaar 
7472ab2e860SBram Moolenaar /*
7482ab2e860SBram Moolenaar  * similar to luaL_addlstring, but replaces \0 with \n if toline and
7492ab2e860SBram Moolenaar  * \n with \0 otherwise
7502ab2e860SBram Moolenaar  */
75155d5c034SBram Moolenaar     static void
luaV_addlstring(luaL_Buffer * b,const char * s,size_t l,int toline)75255d5c034SBram Moolenaar luaV_addlstring(luaL_Buffer *b, const char *s, size_t l, int toline)
75355d5c034SBram Moolenaar {
75455d5c034SBram Moolenaar     while (l--)
75555d5c034SBram Moolenaar     {
75655d5c034SBram Moolenaar 	if (*s == '\0' && toline)
75755d5c034SBram Moolenaar 	    luaL_addchar(b, '\n');
75855d5c034SBram Moolenaar 	else if (*s == '\n' && !toline)
75955d5c034SBram Moolenaar 	    luaL_addchar(b, '\0');
76055d5c034SBram Moolenaar 	else
76155d5c034SBram Moolenaar 	    luaL_addchar(b, *s);
7620ba04296SBram Moolenaar 	s++;
7630ba04296SBram Moolenaar     }
7640ba04296SBram Moolenaar }
7650ba04296SBram Moolenaar 
76655d5c034SBram Moolenaar     static void
luaV_pushline(lua_State * L,buf_T * buf,linenr_T n)76755d5c034SBram Moolenaar luaV_pushline(lua_State *L, buf_T *buf, linenr_T n)
76855d5c034SBram Moolenaar {
7690ba04296SBram Moolenaar     const char *s = (const char *) ml_get_buf(buf, n, FALSE);
7700ba04296SBram Moolenaar     luaL_Buffer b;
7710ba04296SBram Moolenaar     luaL_buffinit(L, &b);
7720ba04296SBram Moolenaar     luaV_addlstring(&b, s, strlen(s), 0);
7730ba04296SBram Moolenaar     luaL_pushresult(&b);
7740ba04296SBram Moolenaar }
7750ba04296SBram Moolenaar 
77655d5c034SBram Moolenaar     static char_u *
luaV_toline(lua_State * L,int pos)77755d5c034SBram Moolenaar luaV_toline(lua_State *L, int pos)
77855d5c034SBram Moolenaar {
7790ba04296SBram Moolenaar     size_t l;
7800ba04296SBram Moolenaar     const char *s = lua_tolstring(L, pos, &l);
78155d5c034SBram Moolenaar 
7820ba04296SBram Moolenaar     luaL_Buffer b;
7830ba04296SBram Moolenaar     luaL_buffinit(L, &b);
7840ba04296SBram Moolenaar     luaV_addlstring(&b, s, l, 1);
7850ba04296SBram Moolenaar     luaL_pushresult(&b);
7860ba04296SBram Moolenaar     return (char_u *) lua_tostring(L, -1);
7870ba04296SBram Moolenaar }
7880ba04296SBram Moolenaar 
7892ab2e860SBram Moolenaar /*
7902ab2e860SBram Moolenaar  * pops a string s from the top of the stack and calls mf(t) for pieces t of
7912ab2e860SBram Moolenaar  * s separated by newlines
7922ab2e860SBram Moolenaar  */
79355d5c034SBram Moolenaar     static void
luaV_msgfunc(lua_State * L,msgfunc_T mf)79455d5c034SBram Moolenaar luaV_msgfunc(lua_State *L, msgfunc_T mf)
79555d5c034SBram Moolenaar {
7960ba04296SBram Moolenaar     luaL_Buffer b;
7970ba04296SBram Moolenaar     size_t l;
7980ba04296SBram Moolenaar     const char *p, *s = lua_tolstring(L, -1, &l);
7990ba04296SBram Moolenaar     luaL_buffinit(L, &b);
8000ba04296SBram Moolenaar     luaV_addlstring(&b, s, l, 0);
8010ba04296SBram Moolenaar     luaL_pushresult(&b);
8022ab2e860SBram Moolenaar     // break string
8030ba04296SBram Moolenaar     p = s = lua_tolstring(L, -1, &l);
80455d5c034SBram Moolenaar     while (l--)
80555d5c034SBram Moolenaar     {
8062ab2e860SBram Moolenaar 	if (*p++ == '\0') // break?
80755d5c034SBram Moolenaar 	{
808c8970b94SBram Moolenaar 	    mf((char *)s);
8090ba04296SBram Moolenaar 	    s = p;
8100ba04296SBram Moolenaar 	}
8110ba04296SBram Moolenaar     }
812c8970b94SBram Moolenaar     mf((char *)s);
8132ab2e860SBram Moolenaar     lua_pop(L, 2); // original and modified strings
8140ba04296SBram Moolenaar }
8150ba04296SBram Moolenaar 
8161dced572SBram Moolenaar #define luaV_newtype(typ,tname,luatyp,luatname) \
8171dced572SBram Moolenaar 	static luatyp * \
8181dced572SBram Moolenaar     luaV_new##tname(lua_State *L, typ *obj) \
8191dced572SBram Moolenaar     { \
8201dced572SBram Moolenaar 	luatyp *o = (luatyp *) lua_newuserdata(L, sizeof(luatyp)); \
8211dced572SBram Moolenaar 	*o = obj; \
8221dced572SBram Moolenaar 	luaV_setudata(L, obj); /* cache[obj] = udata */ \
8231dced572SBram Moolenaar 	luaV_getfield(L, luatname); \
8241dced572SBram Moolenaar 	lua_setmetatable(L, -2); \
8251dced572SBram Moolenaar 	return o; \
8260ba04296SBram Moolenaar     }
8270ba04296SBram Moolenaar 
8281dced572SBram Moolenaar #define luaV_pushtype(typ,tname,luatyp) \
8291dced572SBram Moolenaar 	static luatyp * \
8301dced572SBram Moolenaar     luaV_push##tname(lua_State *L, typ *obj) \
8311dced572SBram Moolenaar     { \
8321dced572SBram Moolenaar 	luatyp *o = NULL; \
8331dced572SBram Moolenaar 	if (obj == NULL) \
8341dced572SBram Moolenaar 	    lua_pushnil(L); \
8351dced572SBram Moolenaar 	else { \
8361dced572SBram Moolenaar 	    luaV_getudata(L, obj); \
8371dced572SBram Moolenaar 	    if (lua_isnil(L, -1)) /* not interned? */ \
8381dced572SBram Moolenaar 	    { \
8391dced572SBram Moolenaar 		lua_pop(L, 1); \
8401dced572SBram Moolenaar 		o = luaV_new##tname(L, obj); \
8411dced572SBram Moolenaar 	    } \
8421dced572SBram Moolenaar 	    else \
8431dced572SBram Moolenaar 		o = (luatyp *) lua_touserdata(L, -1); \
8441dced572SBram Moolenaar 	} \
8451dced572SBram Moolenaar 	return o; \
8460ba04296SBram Moolenaar     }
8471dced572SBram Moolenaar 
8481dced572SBram Moolenaar #define luaV_type_tostring(tname,luatname) \
8491dced572SBram Moolenaar 	static int \
8501dced572SBram Moolenaar     luaV_##tname##_tostring(lua_State *L) \
8511dced572SBram Moolenaar     { \
8521dced572SBram Moolenaar 	lua_pushfstring(L, "%s: %p", luatname, lua_touserdata(L, 1)); \
8531dced572SBram Moolenaar 	return 1; \
8541dced572SBram Moolenaar     }
8551dced572SBram Moolenaar 
8562ab2e860SBram Moolenaar // =======   List type   =======
8571dced572SBram Moolenaar 
8581dced572SBram Moolenaar     static luaV_List *
luaV_newlist(lua_State * L,list_T * lis)8591dced572SBram Moolenaar luaV_newlist(lua_State *L, list_T *lis)
8601dced572SBram Moolenaar {
8611dced572SBram Moolenaar     luaV_List *l = (luaV_List *) lua_newuserdata(L, sizeof(luaV_List));
8621dced572SBram Moolenaar     *l = lis;
8632ab2e860SBram Moolenaar     lis->lv_refcount++; // reference in Lua
8642ab2e860SBram Moolenaar     luaV_setudata(L, lis); // cache[lis] = udata
8651dced572SBram Moolenaar     luaV_getfield(L, LUAVIM_LIST);
8661dced572SBram Moolenaar     lua_setmetatable(L, -2);
8671dced572SBram Moolenaar     return l;
8681dced572SBram Moolenaar }
8691dced572SBram Moolenaar 
luaV_pushtype(list_T,list,luaV_List)8701dced572SBram Moolenaar luaV_pushtype(list_T, list, luaV_List)
8711dced572SBram Moolenaar luaV_type_tostring(list, LUAVIM_LIST)
8721dced572SBram Moolenaar 
8731dced572SBram Moolenaar     static int
8741dced572SBram Moolenaar luaV_list_len(lua_State *L)
8751dced572SBram Moolenaar {
8761dced572SBram Moolenaar     list_T *l = luaV_unbox(L, luaV_List, 1);
877b7828690SBram Moolenaar     lua_pushinteger(L, (int) list_len(l));
8780ba04296SBram Moolenaar     return 1;
8790ba04296SBram Moolenaar }
8800ba04296SBram Moolenaar 
88155d5c034SBram Moolenaar     static int
luaV_list_iter(lua_State * L)8821dced572SBram Moolenaar luaV_list_iter(lua_State *L)
8831dced572SBram Moolenaar {
8841dced572SBram Moolenaar     listitem_T *li = (listitem_T *) lua_touserdata(L, lua_upvalueindex(2));
8851dced572SBram Moolenaar     if (li == NULL) return 0;
8861dced572SBram Moolenaar     luaV_pushtypval(L, &li->li_tv);
8871dced572SBram Moolenaar     lua_pushlightuserdata(L, (void *) li->li_next);
8881dced572SBram Moolenaar     lua_replace(L, lua_upvalueindex(2));
8891dced572SBram Moolenaar     return 1;
8901dced572SBram Moolenaar }
8911dced572SBram Moolenaar 
8921dced572SBram Moolenaar     static int
luaV_list_call(lua_State * L)8931dced572SBram Moolenaar luaV_list_call(lua_State *L)
8941dced572SBram Moolenaar {
8951dced572SBram Moolenaar     list_T *l = luaV_unbox(L, luaV_List, 1);
8962ab2e860SBram Moolenaar     lua_pushvalue(L, lua_upvalueindex(1)); // pass cache table along
8971dced572SBram Moolenaar     lua_pushlightuserdata(L, (void *) l->lv_first);
8981dced572SBram Moolenaar     lua_pushcclosure(L, luaV_list_iter, 2);
8991dced572SBram Moolenaar     return 1;
9001dced572SBram Moolenaar }
9011dced572SBram Moolenaar 
9021dced572SBram Moolenaar     static int
luaV_list_index(lua_State * L)9031dced572SBram Moolenaar luaV_list_index(lua_State *L)
9041dced572SBram Moolenaar {
9051dced572SBram Moolenaar     list_T *l = luaV_unbox(L, luaV_List, 1);
9062ab2e860SBram Moolenaar     if (lua_isnumber(L, 2)) // list item?
9071dced572SBram Moolenaar     {
908bd84617dSBram Moolenaar 	long n = (long) luaL_checkinteger(L, 2);
909bd84617dSBram Moolenaar 	listitem_T *li;
910bd84617dSBram Moolenaar 
911bd84617dSBram Moolenaar 	// Lua array index starts with 1 while Vim uses 0, subtract 1 to
912bd84617dSBram Moolenaar 	// normalize.
913bd84617dSBram Moolenaar 	n -= 1;
914bd84617dSBram Moolenaar 	li = list_find(l, n);
9151dced572SBram Moolenaar 	if (li == NULL)
9161dced572SBram Moolenaar 	    lua_pushnil(L);
9171dced572SBram Moolenaar 	else
9181dced572SBram Moolenaar 	    luaV_pushtypval(L, &li->li_tv);
9191dced572SBram Moolenaar     }
9202ab2e860SBram Moolenaar     else if (lua_isstring(L, 2)) // method?
9211dced572SBram Moolenaar     {
9221dced572SBram Moolenaar 	const char *s = lua_tostring(L, 2);
9231dced572SBram Moolenaar 	if (strncmp(s, "add", 3) == 0
924b376647bSBram Moolenaar 		|| strncmp(s, "insert", 6) == 0)
9251dced572SBram Moolenaar 	{
9261dced572SBram Moolenaar 	    lua_getmetatable(L, 1);
9271dced572SBram Moolenaar 	    lua_getfield(L, -1, s);
9281dced572SBram Moolenaar 	}
9291dced572SBram Moolenaar 	else
9301dced572SBram Moolenaar 	    lua_pushnil(L);
9311dced572SBram Moolenaar     }
9321dced572SBram Moolenaar     else
9331dced572SBram Moolenaar 	lua_pushnil(L);
9341dced572SBram Moolenaar     return 1;
9351dced572SBram Moolenaar }
9361dced572SBram Moolenaar 
9371dced572SBram Moolenaar     static int
luaV_list_newindex(lua_State * L)9381dced572SBram Moolenaar luaV_list_newindex(lua_State *L)
9391dced572SBram Moolenaar {
9401dced572SBram Moolenaar     list_T *l = luaV_unbox(L, luaV_List, 1);
9411dced572SBram Moolenaar     long n = (long) luaL_checkinteger(L, 2);
9421dced572SBram Moolenaar     listitem_T *li;
943bd84617dSBram Moolenaar 
944bd84617dSBram Moolenaar     // Lua array index starts with 1 while Vim uses 0, subtract 1 to normalize.
945bd84617dSBram Moolenaar     n -= 1;
946bd84617dSBram Moolenaar 
9471dced572SBram Moolenaar     if (l->lv_lock)
9481dced572SBram Moolenaar 	luaL_error(L, "list is locked");
9491dced572SBram Moolenaar     li = list_find(l, n);
950a1f9f866SBram Moolenaar     if (li == NULL)
951a1f9f866SBram Moolenaar     {
952a1f9f866SBram Moolenaar         if (!lua_isnil(L, 3))
953a1f9f866SBram Moolenaar         {
954a1f9f866SBram Moolenaar 	   typval_T v;
955a1f9f866SBram Moolenaar 	   luaV_checktypval(L, 3, &v, "inserting list item");
956a1f9f866SBram Moolenaar 	   if (list_insert_tv(l, &v, li) == FAIL)
957a1f9f866SBram Moolenaar 	        luaL_error(L, "failed to add item to list");
958a1f9f866SBram Moolenaar 	   clear_tv(&v);
959a1f9f866SBram Moolenaar         }
960a1f9f866SBram Moolenaar     }
961a1f9f866SBram Moolenaar     else
962a1f9f866SBram Moolenaar     {
9632ab2e860SBram Moolenaar         if (lua_isnil(L, 3)) // remove?
9641dced572SBram Moolenaar         {
9653ec7f4e4SBram Moolenaar 	    vimlist_remove(l, li, li);
9668a7d6542SBram Moolenaar 	    listitem_free(l, li);
9671dced572SBram Moolenaar         }
9681dced572SBram Moolenaar         else
9691dced572SBram Moolenaar         {
9701dced572SBram Moolenaar 	    typval_T v;
971ca06da92SBram Moolenaar 	    luaV_checktypval(L, 3, &v, "setting list item");
9721dced572SBram Moolenaar 	    clear_tv(&li->li_tv);
973e49b8e8dSBram Moolenaar 	    li->li_tv = v;
9741dced572SBram Moolenaar         }
975a1f9f866SBram Moolenaar     }
9761dced572SBram Moolenaar     return 0;
9771dced572SBram Moolenaar }
9781dced572SBram Moolenaar 
9791dced572SBram Moolenaar     static int
luaV_list_add(lua_State * L)9801dced572SBram Moolenaar luaV_list_add(lua_State *L)
9811dced572SBram Moolenaar {
9821dced572SBram Moolenaar     luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST);
9831dced572SBram Moolenaar     list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis);
984b376647bSBram Moolenaar     typval_T v;
9851dced572SBram Moolenaar     if (l->lv_lock)
9861dced572SBram Moolenaar 	luaL_error(L, "list is locked");
9871dced572SBram Moolenaar     lua_settop(L, 2);
988ca06da92SBram Moolenaar     luaV_checktypval(L, 2, &v, "adding list item");
989b376647bSBram Moolenaar     if (list_append_tv(l, &v) == FAIL)
990ca06da92SBram Moolenaar 	luaL_error(L, "failed to add item to list");
991b376647bSBram Moolenaar     clear_tv(&v);
9921dced572SBram Moolenaar     lua_settop(L, 1);
9931dced572SBram Moolenaar     return 1;
9941dced572SBram Moolenaar }
9951dced572SBram Moolenaar 
9961dced572SBram Moolenaar     static int
luaV_list_insert(lua_State * L)9971dced572SBram Moolenaar luaV_list_insert(lua_State *L)
9981dced572SBram Moolenaar {
9991dced572SBram Moolenaar     luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST);
10001dced572SBram Moolenaar     list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis);
100146538ee4SBram Moolenaar     long pos = (long) luaL_optinteger(L, 3, 0);
10021dced572SBram Moolenaar     listitem_T *li = NULL;
10031dced572SBram Moolenaar     typval_T v;
10041dced572SBram Moolenaar     if (l->lv_lock)
10051dced572SBram Moolenaar 	luaL_error(L, "list is locked");
10061dced572SBram Moolenaar     if (pos < l->lv_len)
10071dced572SBram Moolenaar     {
10081dced572SBram Moolenaar 	li = list_find(l, pos);
10091dced572SBram Moolenaar 	if (li == NULL)
10101dced572SBram Moolenaar 	    luaL_error(L, "invalid position");
10111dced572SBram Moolenaar     }
10121dced572SBram Moolenaar     lua_settop(L, 2);
1013ca06da92SBram Moolenaar     luaV_checktypval(L, 2, &v, "inserting list item");
1014b376647bSBram Moolenaar     if (list_insert_tv(l, &v, li) == FAIL)
1015ca06da92SBram Moolenaar 	luaL_error(L, "failed to add item to list");
1016b376647bSBram Moolenaar     clear_tv(&v);
10171dced572SBram Moolenaar     lua_settop(L, 1);
10181dced572SBram Moolenaar     return 1;
10191dced572SBram Moolenaar }
10201dced572SBram Moolenaar 
10211dced572SBram Moolenaar static const luaL_Reg luaV_List_mt[] = {
10221dced572SBram Moolenaar     {"__tostring", luaV_list_tostring},
10231dced572SBram Moolenaar     {"__len", luaV_list_len},
10241dced572SBram Moolenaar     {"__call", luaV_list_call},
10251dced572SBram Moolenaar     {"__index", luaV_list_index},
10261dced572SBram Moolenaar     {"__newindex", luaV_list_newindex},
10271dced572SBram Moolenaar     {"add", luaV_list_add},
10281dced572SBram Moolenaar     {"insert", luaV_list_insert},
10291dced572SBram Moolenaar     {NULL, NULL}
10301dced572SBram Moolenaar };
10311dced572SBram Moolenaar 
10321dced572SBram Moolenaar 
10332ab2e860SBram Moolenaar // =======   Dict type   =======
10341dced572SBram Moolenaar 
10351dced572SBram Moolenaar     static luaV_Dict *
luaV_newdict(lua_State * L,dict_T * dic)10361dced572SBram Moolenaar luaV_newdict(lua_State *L, dict_T *dic)
10371dced572SBram Moolenaar {
10381dced572SBram Moolenaar     luaV_Dict *d = (luaV_Dict *) lua_newuserdata(L, sizeof(luaV_Dict));
10391dced572SBram Moolenaar     *d = dic;
10402ab2e860SBram Moolenaar     dic->dv_refcount++; // reference in Lua
10412ab2e860SBram Moolenaar     luaV_setudata(L, dic); // cache[dic] = udata
10421dced572SBram Moolenaar     luaV_getfield(L, LUAVIM_DICT);
10431dced572SBram Moolenaar     lua_setmetatable(L, -2);
10441dced572SBram Moolenaar     return d;
10451dced572SBram Moolenaar }
10461dced572SBram Moolenaar 
luaV_pushtype(dict_T,dict,luaV_Dict)10471dced572SBram Moolenaar luaV_pushtype(dict_T, dict, luaV_Dict)
10481dced572SBram Moolenaar luaV_type_tostring(dict, LUAVIM_DICT)
10491dced572SBram Moolenaar 
10501dced572SBram Moolenaar     static int
10511dced572SBram Moolenaar luaV_dict_len(lua_State *L)
10521dced572SBram Moolenaar {
10531dced572SBram Moolenaar     dict_T *d = luaV_unbox(L, luaV_Dict, 1);
1054b7828690SBram Moolenaar     lua_pushinteger(L, (int) dict_len(d));
10551dced572SBram Moolenaar     return 1;
10561dced572SBram Moolenaar }
10571dced572SBram Moolenaar 
10581dced572SBram Moolenaar     static int
luaV_dict_iter(lua_State * L UNUSED)1059feeaa688SBram Moolenaar luaV_dict_iter(lua_State *L UNUSED)
10601dced572SBram Moolenaar {
1061feeaa688SBram Moolenaar #ifdef FEAT_EVAL
10621dced572SBram Moolenaar     hashitem_T *hi = (hashitem_T *) lua_touserdata(L, lua_upvalueindex(2));
10631dced572SBram Moolenaar     int n = lua_tointeger(L, lua_upvalueindex(3));
10641dced572SBram Moolenaar     dictitem_T *di;
10651dced572SBram Moolenaar     if (n <= 0) return 0;
10661dced572SBram Moolenaar     while (HASHITEM_EMPTY(hi)) hi++;
10671dced572SBram Moolenaar     di = dict_lookup(hi);
10681dced572SBram Moolenaar     lua_pushstring(L, (char *) hi->hi_key);
10691dced572SBram Moolenaar     luaV_pushtypval(L, &di->di_tv);
10701dced572SBram Moolenaar     lua_pushlightuserdata(L, (void *) (hi + 1));
10711dced572SBram Moolenaar     lua_replace(L, lua_upvalueindex(2));
10721dced572SBram Moolenaar     lua_pushinteger(L, n - 1);
10731dced572SBram Moolenaar     lua_replace(L, lua_upvalueindex(3));
10741dced572SBram Moolenaar     return 2;
1075feeaa688SBram Moolenaar #else
1076feeaa688SBram Moolenaar     return 0;
1077feeaa688SBram Moolenaar #endif
10781dced572SBram Moolenaar }
10791dced572SBram Moolenaar 
10801dced572SBram Moolenaar     static int
luaV_dict_call(lua_State * L)10811dced572SBram Moolenaar luaV_dict_call(lua_State *L)
10821dced572SBram Moolenaar {
10831dced572SBram Moolenaar     dict_T *d = luaV_unbox(L, luaV_Dict, 1);
10841dced572SBram Moolenaar     hashtab_T *ht = &d->dv_hashtab;
10852ab2e860SBram Moolenaar     lua_pushvalue(L, lua_upvalueindex(1)); // pass cache table along
10861dced572SBram Moolenaar     lua_pushlightuserdata(L, (void *) ht->ht_array);
10872ab2e860SBram Moolenaar     lua_pushinteger(L, ht->ht_used); // # remaining items
10881dced572SBram Moolenaar     lua_pushcclosure(L, luaV_dict_iter, 3);
10891dced572SBram Moolenaar     return 1;
10901dced572SBram Moolenaar }
10911dced572SBram Moolenaar 
10921dced572SBram Moolenaar     static int
luaV_dict_index(lua_State * L)10931dced572SBram Moolenaar luaV_dict_index(lua_State *L)
10941dced572SBram Moolenaar {
10951dced572SBram Moolenaar     dict_T *d = luaV_unbox(L, luaV_Dict, 1);
10961dced572SBram Moolenaar     char_u *key = (char_u *) luaL_checkstring(L, 2);
10971dced572SBram Moolenaar     dictitem_T *di = dict_find(d, key, -1);
1098ca06da92SBram Moolenaar 
10991dced572SBram Moolenaar     if (di == NULL)
11001dced572SBram Moolenaar 	lua_pushnil(L);
11011dced572SBram Moolenaar     else
1102ca06da92SBram Moolenaar     {
11031dced572SBram Moolenaar 	luaV_pushtypval(L, &di->di_tv);
11042ab2e860SBram Moolenaar 	if (di->di_tv.v_type == VAR_FUNC) // funcref?
1105ca06da92SBram Moolenaar 	{
1106ca06da92SBram Moolenaar 	    luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, -1);
11072ab2e860SBram Moolenaar 	    f->self = d; // keep "self" reference
1108ca06da92SBram Moolenaar 	    d->dv_refcount++;
1109ca06da92SBram Moolenaar 	}
1110ca06da92SBram Moolenaar     }
11111dced572SBram Moolenaar     return 1;
11121dced572SBram Moolenaar }
11131dced572SBram Moolenaar 
11141dced572SBram Moolenaar     static int
luaV_dict_newindex(lua_State * L)11151dced572SBram Moolenaar luaV_dict_newindex(lua_State *L)
11161dced572SBram Moolenaar {
11171dced572SBram Moolenaar     dict_T *d = luaV_unbox(L, luaV_Dict, 1);
11181dced572SBram Moolenaar     char_u *key = (char_u *) luaL_checkstring(L, 2);
11191dced572SBram Moolenaar     dictitem_T *di;
1120e49b8e8dSBram Moolenaar     typval_T tv;
1121713bf9e9SBram Moolenaar 
11221dced572SBram Moolenaar     if (d->dv_lock)
11231dced572SBram Moolenaar 	luaL_error(L, "dict is locked");
1124d6ef5f9bSBram Moolenaar     if (key == NULL)
1125d6ef5f9bSBram Moolenaar 	return 0;
1126d6ef5f9bSBram Moolenaar     if (*key == NUL)
1127ca06da92SBram Moolenaar 	luaL_error(L, "empty key");
11282ab2e860SBram Moolenaar     if (!lua_isnil(L, 3)) // read value?
112917413671SBram Moolenaar     {
1130e49b8e8dSBram Moolenaar 	luaV_checktypval(L, 3, &tv, "setting dict item");
1131e49b8e8dSBram Moolenaar 	if (d->dv_scope == VAR_DEF_SCOPE && tv.v_type == VAR_FUNC)
1132e49b8e8dSBram Moolenaar 	{
1133e49b8e8dSBram Moolenaar 	    clear_tv(&tv);
1134ca06da92SBram Moolenaar 	    luaL_error(L, "cannot assign funcref to builtin scope");
1135ca06da92SBram Moolenaar 	}
1136e49b8e8dSBram Moolenaar     }
11371dced572SBram Moolenaar     di = dict_find(d, key, -1);
11382ab2e860SBram Moolenaar     if (di == NULL) // non-existing key?
11391dced572SBram Moolenaar     {
1140d6ef5f9bSBram Moolenaar 	if (lua_isnil(L, 3))
1141d6ef5f9bSBram Moolenaar 	    return 0;
11421dced572SBram Moolenaar 	di = dictitem_alloc(key);
1143d6ef5f9bSBram Moolenaar 	if (di == NULL)
1144e49b8e8dSBram Moolenaar 	{
1145e49b8e8dSBram Moolenaar 	    clear_tv(&tv);
1146d6ef5f9bSBram Moolenaar 	    return 0;
1147e49b8e8dSBram Moolenaar 	}
11481dced572SBram Moolenaar 	if (dict_add(d, di) == FAIL)
11491dced572SBram Moolenaar 	{
11501dced572SBram Moolenaar 	    vim_free(di);
1151e49b8e8dSBram Moolenaar 	    clear_tv(&tv);
11521dced572SBram Moolenaar 	    return 0;
11531dced572SBram Moolenaar 	}
11541dced572SBram Moolenaar     }
11551dced572SBram Moolenaar     else
11561dced572SBram Moolenaar 	clear_tv(&di->di_tv);
11572ab2e860SBram Moolenaar     if (lua_isnil(L, 3)) // remove?
11581dced572SBram Moolenaar     {
11591dced572SBram Moolenaar 	hashitem_T *hi = hash_find(&d->dv_hashtab, di->di_key);
11601dced572SBram Moolenaar 	hash_remove(&d->dv_hashtab, hi);
11611dced572SBram Moolenaar 	dictitem_free(di);
11621dced572SBram Moolenaar     }
1163ca06da92SBram Moolenaar     else
1164e49b8e8dSBram Moolenaar 	di->di_tv = tv;
11651dced572SBram Moolenaar     return 0;
11661dced572SBram Moolenaar }
11671dced572SBram Moolenaar 
11681dced572SBram Moolenaar static const luaL_Reg luaV_Dict_mt[] = {
11691dced572SBram Moolenaar     {"__tostring", luaV_dict_tostring},
11701dced572SBram Moolenaar     {"__len", luaV_dict_len},
11711dced572SBram Moolenaar     {"__call", luaV_dict_call},
11721dced572SBram Moolenaar     {"__index", luaV_dict_index},
11731dced572SBram Moolenaar     {"__newindex", luaV_dict_newindex},
11741dced572SBram Moolenaar     {NULL, NULL}
11751dced572SBram Moolenaar };
11761dced572SBram Moolenaar 
11771dced572SBram Moolenaar 
11782ab2e860SBram Moolenaar // =======   Blob type   =======
1179b7828690SBram Moolenaar 
1180b7828690SBram Moolenaar     static luaV_Blob *
luaV_newblob(lua_State * L,blob_T * blo)1181b7828690SBram Moolenaar luaV_newblob(lua_State *L, blob_T *blo)
1182b7828690SBram Moolenaar {
1183b7828690SBram Moolenaar     luaV_Blob *b = (luaV_Blob *) lua_newuserdata(L, sizeof(luaV_Blob));
1184b7828690SBram Moolenaar     *b = blo;
11852ab2e860SBram Moolenaar     blo->bv_refcount++; // reference in Lua
11862ab2e860SBram Moolenaar     luaV_setudata(L, blo); // cache[blo] = udata
1187b7828690SBram Moolenaar     luaV_getfield(L, LUAVIM_BLOB);
1188b7828690SBram Moolenaar     lua_setmetatable(L, -2);
1189b7828690SBram Moolenaar     return b;
1190b7828690SBram Moolenaar }
1191b7828690SBram Moolenaar 
luaV_pushtype(blob_T,blob,luaV_Blob)1192b7828690SBram Moolenaar luaV_pushtype(blob_T, blob, luaV_Blob)
1193b7828690SBram Moolenaar luaV_type_tostring(blob, LUAVIM_BLOB)
1194b7828690SBram Moolenaar 
1195b7828690SBram Moolenaar     static int
1196b7828690SBram Moolenaar luaV_blob_gc(lua_State *L)
1197b7828690SBram Moolenaar {
1198b7828690SBram Moolenaar     blob_T *b = luaV_unbox(L, luaV_Blob, 1);
1199b7828690SBram Moolenaar     blob_unref(b);
1200b7828690SBram Moolenaar     return 0;
1201b7828690SBram Moolenaar }
1202b7828690SBram Moolenaar 
1203b7828690SBram Moolenaar     static int
luaV_blob_len(lua_State * L)1204b7828690SBram Moolenaar luaV_blob_len(lua_State *L)
1205b7828690SBram Moolenaar {
1206b7828690SBram Moolenaar     blob_T *b = luaV_unbox(L, luaV_Blob, 1);
1207b7828690SBram Moolenaar     lua_pushinteger(L, (int) blob_len(b));
1208b7828690SBram Moolenaar     return 1;
1209b7828690SBram Moolenaar }
1210b7828690SBram Moolenaar 
1211b7828690SBram Moolenaar     static int
luaV_blob_index(lua_State * L)1212b7828690SBram Moolenaar luaV_blob_index(lua_State *L)
1213b7828690SBram Moolenaar {
1214b7828690SBram Moolenaar     blob_T *b = luaV_unbox(L, luaV_Blob, 1);
1215b7828690SBram Moolenaar     if (lua_isnumber(L, 2))
1216b7828690SBram Moolenaar     {
1217b7828690SBram Moolenaar 	int idx = luaL_checkinteger(L, 2);
1218b7828690SBram Moolenaar 	if (idx < blob_len(b))
1219b7828690SBram Moolenaar 	    lua_pushnumber(L, (lua_Number) blob_get(b, idx));
1220b7828690SBram Moolenaar 	else
1221b7828690SBram Moolenaar 	    lua_pushnil(L);
1222b7828690SBram Moolenaar     }
1223b7828690SBram Moolenaar     else if (lua_isstring(L, 2))
1224b7828690SBram Moolenaar     {
1225b7828690SBram Moolenaar 	const char *s = lua_tostring(L, 2);
1226b7828690SBram Moolenaar 	if (strncmp(s, "add", 3) == 0)
1227b7828690SBram Moolenaar 	{
1228b7828690SBram Moolenaar 	    lua_getmetatable(L, 1);
1229b7828690SBram Moolenaar 	    lua_getfield(L, -1, s);
1230b7828690SBram Moolenaar 	}
1231b7828690SBram Moolenaar 	else
1232b7828690SBram Moolenaar 	    lua_pushnil(L);
1233b7828690SBram Moolenaar     }
1234b7828690SBram Moolenaar     else
1235b7828690SBram Moolenaar 	lua_pushnil(L);
1236b7828690SBram Moolenaar     return 1;
1237b7828690SBram Moolenaar }
1238b7828690SBram Moolenaar 
1239b7828690SBram Moolenaar     static int
luaV_blob_newindex(lua_State * L)1240b7828690SBram Moolenaar luaV_blob_newindex(lua_State *L)
1241b7828690SBram Moolenaar {
1242b7828690SBram Moolenaar     blob_T *b = luaV_unbox(L, luaV_Blob, 1);
1243b7828690SBram Moolenaar     if (b->bv_lock)
1244b7828690SBram Moolenaar 	luaL_error(L, "blob is locked");
1245b7828690SBram Moolenaar     if (lua_isnumber(L, 2))
1246b7828690SBram Moolenaar     {
1247b7828690SBram Moolenaar 	long len = blob_len(b);
1248b7828690SBram Moolenaar 	int idx = luaL_checkinteger(L, 2);
1249b7828690SBram Moolenaar 	int val = luaL_checkinteger(L, 3);
1250b7828690SBram Moolenaar 	if (idx < len || (idx == len && ga_grow(&b->bv_ga, 1) == OK))
1251b7828690SBram Moolenaar 	{
1252b7828690SBram Moolenaar 	    blob_set(b, idx, (char_u) val);
1253b7828690SBram Moolenaar 	    if (idx == len)
1254b7828690SBram Moolenaar 		++b->bv_ga.ga_len;
1255b7828690SBram Moolenaar 	}
1256b7828690SBram Moolenaar 	else
1257b7828690SBram Moolenaar 	    luaL_error(L, "index out of range");
1258b7828690SBram Moolenaar     }
1259b7828690SBram Moolenaar     return 0;
1260b7828690SBram Moolenaar }
1261b7828690SBram Moolenaar 
1262b7828690SBram Moolenaar     static int
luaV_blob_add(lua_State * L)1263b7828690SBram Moolenaar luaV_blob_add(lua_State *L)
1264b7828690SBram Moolenaar {
1265b7828690SBram Moolenaar     luaV_Blob *blo = luaV_checkudata(L, 1, LUAVIM_BLOB);
1266b7828690SBram Moolenaar     blob_T *b = (blob_T *) luaV_checkcache(L, (void *) *blo);
1267b7828690SBram Moolenaar     if (b->bv_lock)
1268b7828690SBram Moolenaar 	luaL_error(L, "blob is locked");
1269b7828690SBram Moolenaar     lua_settop(L, 2);
1270b7828690SBram Moolenaar     if (!lua_isstring(L, 2))
1271b7828690SBram Moolenaar 	luaL_error(L, "string expected, got %s", luaL_typename(L, 2));
1272b7828690SBram Moolenaar     else
1273b7828690SBram Moolenaar     {
1274b7828690SBram Moolenaar 	size_t i, l = 0;
1275b7828690SBram Moolenaar 	const char *s = lua_tolstring(L, 2, &l);
1276b7828690SBram Moolenaar 
12775f1d3ae8SBram Moolenaar 	if (ga_grow(&b->bv_ga, (int)l) == OK)
1278b7828690SBram Moolenaar 	    for (i = 0; i < l; ++i)
1279b7828690SBram Moolenaar 		ga_append(&b->bv_ga, s[i]);
1280b7828690SBram Moolenaar     }
1281b7828690SBram Moolenaar     lua_settop(L, 1);
1282b7828690SBram Moolenaar     return 1;
1283b7828690SBram Moolenaar }
1284b7828690SBram Moolenaar 
1285b7828690SBram Moolenaar static const luaL_Reg luaV_Blob_mt[] = {
1286b7828690SBram Moolenaar     {"__tostring", luaV_blob_tostring},
1287b7828690SBram Moolenaar     {"__gc", luaV_blob_gc},
1288b7828690SBram Moolenaar     {"__len", luaV_blob_len},
1289b7828690SBram Moolenaar     {"__index", luaV_blob_index},
1290b7828690SBram Moolenaar     {"__newindex", luaV_blob_newindex},
1291b7828690SBram Moolenaar     {"add", luaV_blob_add},
1292b7828690SBram Moolenaar     {NULL, NULL}
1293b7828690SBram Moolenaar };
1294b7828690SBram Moolenaar 
1295b7828690SBram Moolenaar 
12962ab2e860SBram Moolenaar // =======   Funcref type   =======
1297ca06da92SBram Moolenaar 
1298ca06da92SBram Moolenaar     static luaV_Funcref *
luaV_newfuncref(lua_State * L,char_u * name)1299ca06da92SBram Moolenaar luaV_newfuncref(lua_State *L, char_u *name)
1300ca06da92SBram Moolenaar {
1301ca06da92SBram Moolenaar     luaV_Funcref *f = (luaV_Funcref *)lua_newuserdata(L, sizeof(luaV_Funcref));
1302ca06da92SBram Moolenaar 
1303ca06da92SBram Moolenaar     if (name != NULL)
1304ca06da92SBram Moolenaar     {
13054eefe47eSBram Moolenaar 	func_ref(name);
13064eefe47eSBram Moolenaar 	f->name = vim_strsave(name);
1307ca06da92SBram Moolenaar     }
1308ca06da92SBram Moolenaar     f->self = NULL;
1309ca06da92SBram Moolenaar     luaV_getfield(L, LUAVIM_FUNCREF);
1310ca06da92SBram Moolenaar     lua_setmetatable(L, -2);
1311ca06da92SBram Moolenaar     return f;
1312ca06da92SBram Moolenaar }
1313ca06da92SBram Moolenaar 
1314ca06da92SBram Moolenaar     static luaV_Funcref *
luaV_pushfuncref(lua_State * L,char_u * name)13154eefe47eSBram Moolenaar luaV_pushfuncref(lua_State *L, char_u *name)
1316ca06da92SBram Moolenaar {
13174eefe47eSBram Moolenaar     return luaV_newfuncref(L, name);
1318ca06da92SBram Moolenaar }
1319ca06da92SBram Moolenaar 
1320ca06da92SBram Moolenaar 
luaV_type_tostring(funcref,LUAVIM_FUNCREF)1321ca06da92SBram Moolenaar luaV_type_tostring(funcref, LUAVIM_FUNCREF)
1322ca06da92SBram Moolenaar 
1323ca06da92SBram Moolenaar     static int
1324ca06da92SBram Moolenaar luaV_funcref_gc(lua_State *L)
1325ca06da92SBram Moolenaar {
1326ca06da92SBram Moolenaar     luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
1327ca06da92SBram Moolenaar 
13284eefe47eSBram Moolenaar     func_unref(f->name);
13294eefe47eSBram Moolenaar     vim_free(f->name);
13304eefe47eSBram Moolenaar     // NOTE: Don't call "dict_unref(f->self)", because the dict of "f->self"
13314eefe47eSBram Moolenaar     // will be (or has been already) freed by Vim's garbage collection.
1332ca06da92SBram Moolenaar     return 0;
1333ca06da92SBram Moolenaar }
1334ca06da92SBram Moolenaar 
13352ab2e860SBram Moolenaar // equivalent to string(funcref)
1336ca06da92SBram Moolenaar     static int
luaV_funcref_len(lua_State * L)1337ca06da92SBram Moolenaar luaV_funcref_len(lua_State *L)
1338ca06da92SBram Moolenaar {
1339ca06da92SBram Moolenaar     luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
1340ca06da92SBram Moolenaar 
13414eefe47eSBram Moolenaar     lua_pushstring(L, (const char *) f->name);
1342ca06da92SBram Moolenaar     return 1;
1343ca06da92SBram Moolenaar }
1344ca06da92SBram Moolenaar 
1345ca06da92SBram Moolenaar     static int
luaV_funcref_call(lua_State * L)1346ca06da92SBram Moolenaar luaV_funcref_call(lua_State *L)
1347ca06da92SBram Moolenaar {
1348ca06da92SBram Moolenaar     luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
13494eefe47eSBram Moolenaar     int i, n = lua_gettop(L) - 1; // #args
13504eefe47eSBram Moolenaar     int status = FAIL;
13514eefe47eSBram Moolenaar     typval_T args;
13524eefe47eSBram Moolenaar     typval_T rettv;
1353ca06da92SBram Moolenaar 
13544eefe47eSBram Moolenaar     args.v_type = VAR_LIST;
13554eefe47eSBram Moolenaar     args.vval.v_list = list_alloc();
13564eefe47eSBram Moolenaar     rettv.v_type = VAR_UNKNOWN; // as in clear_tv
13574eefe47eSBram Moolenaar     if (args.vval.v_list != NULL)
1358d6ef5f9bSBram Moolenaar     {
13594eefe47eSBram Moolenaar 	typval_T v;
13604eefe47eSBram Moolenaar 
136117413671SBram Moolenaar 	for (i = 0; i < n; i++)
136217413671SBram Moolenaar 	{
1363ca06da92SBram Moolenaar 	    luaV_checktypval(L, i + 2, &v, "calling funcref");
13644eefe47eSBram Moolenaar 	    list_append_tv(args.vval.v_list, &v);
1365713bf9e9SBram Moolenaar 	    clear_tv(&v);
1366ca06da92SBram Moolenaar 	}
13674eefe47eSBram Moolenaar 	status = func_call(f->name, &args, NULL, f->self, &rettv);
1368ca06da92SBram Moolenaar 	if (status == OK)
1369ca06da92SBram Moolenaar 	    luaV_pushtypval(L, &rettv);
13704eefe47eSBram Moolenaar 	clear_tv(&args);
1371ca06da92SBram Moolenaar 	clear_tv(&rettv);
1372d6ef5f9bSBram Moolenaar     }
1373ca06da92SBram Moolenaar     if (status != OK)
1374ca06da92SBram Moolenaar 	luaL_error(L, "cannot call funcref");
1375ca06da92SBram Moolenaar     return 1;
1376ca06da92SBram Moolenaar }
1377ca06da92SBram Moolenaar 
1378ca06da92SBram Moolenaar static const luaL_Reg luaV_Funcref_mt[] = {
1379ca06da92SBram Moolenaar     {"__tostring", luaV_funcref_tostring},
1380ca06da92SBram Moolenaar     {"__gc", luaV_funcref_gc},
1381ca06da92SBram Moolenaar     {"__len", luaV_funcref_len},
1382ca06da92SBram Moolenaar     {"__call", luaV_funcref_call},
1383ca06da92SBram Moolenaar     {NULL, NULL}
1384ca06da92SBram Moolenaar };
1385ca06da92SBram Moolenaar 
1386ca06da92SBram Moolenaar 
13872ab2e860SBram Moolenaar // =======   Buffer type   =======
13881dced572SBram Moolenaar 
luaV_newtype(buf_T,buffer,luaV_Buffer,LUAVIM_BUFFER)13891dced572SBram Moolenaar luaV_newtype(buf_T, buffer, luaV_Buffer, LUAVIM_BUFFER)
13901dced572SBram Moolenaar luaV_pushtype(buf_T, buffer, luaV_Buffer)
13911dced572SBram Moolenaar luaV_type_tostring(buffer, LUAVIM_BUFFER)
13921dced572SBram Moolenaar 
13931dced572SBram Moolenaar     static int
139455d5c034SBram Moolenaar luaV_buffer_len(lua_State *L)
139555d5c034SBram Moolenaar {
13961dced572SBram Moolenaar     buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
13971dced572SBram Moolenaar     lua_pushinteger(L, b->b_ml.ml_line_count);
13980ba04296SBram Moolenaar     return 1;
13990ba04296SBram Moolenaar }
14000ba04296SBram Moolenaar 
140155d5c034SBram Moolenaar     static int
luaV_buffer_call(lua_State * L)140255d5c034SBram Moolenaar luaV_buffer_call(lua_State *L)
140355d5c034SBram Moolenaar {
14041dced572SBram Moolenaar     buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
14050ba04296SBram Moolenaar     lua_settop(L, 1);
14061dced572SBram Moolenaar     set_curbuf(b, DOBUF_SPLIT);
14070ba04296SBram Moolenaar     return 1;
14080ba04296SBram Moolenaar }
14090ba04296SBram Moolenaar 
141055d5c034SBram Moolenaar     static int
luaV_buffer_index(lua_State * L)141155d5c034SBram Moolenaar luaV_buffer_index(lua_State *L)
141255d5c034SBram Moolenaar {
14131dced572SBram Moolenaar     buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
14140ba04296SBram Moolenaar     linenr_T n = (linenr_T) lua_tointeger(L, 2);
14151dced572SBram Moolenaar     if (n > 0 && n <= b->b_ml.ml_line_count)
14161dced572SBram Moolenaar 	luaV_pushline(L, b, n);
141755d5c034SBram Moolenaar     else if (lua_isstring(L, 2))
141855d5c034SBram Moolenaar     {
14190ba04296SBram Moolenaar 	const char *s = lua_tostring(L, 2);
14200ba04296SBram Moolenaar 	if (strncmp(s, "name", 4) == 0)
1421fe08df45SBram Moolenaar 	    lua_pushstring(L, (b->b_sfname == NULL)
1422fe08df45SBram Moolenaar 					? "" : (char *) b->b_sfname);
14230ba04296SBram Moolenaar 	else if (strncmp(s, "fname", 5) == 0)
1424fe08df45SBram Moolenaar 	    lua_pushstring(L, (b->b_ffname == NULL)
1425fe08df45SBram Moolenaar 					? "" : (char *) b->b_ffname);
14260ba04296SBram Moolenaar 	else if (strncmp(s, "number", 6) == 0)
14271dced572SBram Moolenaar 	    lua_pushinteger(L, b->b_fnum);
14282ab2e860SBram Moolenaar 	// methods
14290ba04296SBram Moolenaar 	else if (strncmp(s,   "insert", 6) == 0
14300ba04296SBram Moolenaar 		|| strncmp(s, "next", 4) == 0
14310ba04296SBram Moolenaar 		|| strncmp(s, "previous", 8) == 0
143255d5c034SBram Moolenaar 		|| strncmp(s, "isvalid", 7) == 0)
143355d5c034SBram Moolenaar 	{
14340ba04296SBram Moolenaar 	    lua_getmetatable(L, 1);
14350ba04296SBram Moolenaar 	    lua_getfield(L, -1, s);
14360ba04296SBram Moolenaar 	}
143755d5c034SBram Moolenaar 	else
143855d5c034SBram Moolenaar 	    lua_pushnil(L);
14390ba04296SBram Moolenaar     }
144055d5c034SBram Moolenaar     else
144155d5c034SBram Moolenaar 	lua_pushnil(L);
14420ba04296SBram Moolenaar     return 1;
14430ba04296SBram Moolenaar }
14440ba04296SBram Moolenaar 
144555d5c034SBram Moolenaar     static int
luaV_buffer_newindex(lua_State * L)144655d5c034SBram Moolenaar luaV_buffer_newindex(lua_State *L)
144755d5c034SBram Moolenaar {
14481dced572SBram Moolenaar     buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
14490ba04296SBram Moolenaar     linenr_T n = (linenr_T) luaL_checkinteger(L, 2);
14500ba04296SBram Moolenaar #ifdef HAVE_SANDBOX
14510ba04296SBram Moolenaar     luaV_checksandbox(L);
14520ba04296SBram Moolenaar #endif
14531dced572SBram Moolenaar     if (n < 1 || n > b->b_ml.ml_line_count)
14540ba04296SBram Moolenaar 	luaL_error(L, "invalid line number");
14552ab2e860SBram Moolenaar     if (lua_isnil(L, 3)) // delete line
145655d5c034SBram Moolenaar     {
14570ba04296SBram Moolenaar 	buf_T *buf = curbuf;
14581dced572SBram Moolenaar 	curbuf = b;
145955d5c034SBram Moolenaar 	if (u_savedel(n, 1L) == FAIL)
146055d5c034SBram Moolenaar 	{
14610ba04296SBram Moolenaar 	    curbuf = buf;
14620ba04296SBram Moolenaar 	    luaL_error(L, "cannot save undo information");
14630ba04296SBram Moolenaar 	}
1464ca70c07bSBram Moolenaar 	else if (ml_delete(n) == FAIL)
146555d5c034SBram Moolenaar 	{
14660ba04296SBram Moolenaar 	    curbuf = buf;
14670ba04296SBram Moolenaar 	    luaL_error(L, "cannot delete line");
14680ba04296SBram Moolenaar 	}
1469ca06da92SBram Moolenaar 	else
1470ca06da92SBram Moolenaar 	{
14710ba04296SBram Moolenaar 	    deleted_lines_mark(n, 1L);
14722ab2e860SBram Moolenaar 	    if (b == curwin->w_buffer) // fix cursor in current window?
147355d5c034SBram Moolenaar 	    {
147455d5c034SBram Moolenaar 		if (curwin->w_cursor.lnum >= n)
147555d5c034SBram Moolenaar 		{
147655d5c034SBram Moolenaar 		    if (curwin->w_cursor.lnum > n)
147755d5c034SBram Moolenaar 		    {
14780ba04296SBram Moolenaar 			curwin->w_cursor.lnum -= 1;
14790ba04296SBram Moolenaar 			check_cursor_col();
14800ba04296SBram Moolenaar 		    }
1481e49b8e8dSBram Moolenaar 		    else
1482e49b8e8dSBram Moolenaar 			check_cursor();
14830ba04296SBram Moolenaar 		    changed_cline_bef_curs();
14840ba04296SBram Moolenaar 		}
14850ba04296SBram Moolenaar 		invalidate_botline();
14860ba04296SBram Moolenaar 	    }
14870ba04296SBram Moolenaar 	}
14880ba04296SBram Moolenaar 	curbuf = buf;
14890ba04296SBram Moolenaar     }
14902ab2e860SBram Moolenaar     else if (lua_isstring(L, 3)) // update line
149155d5c034SBram Moolenaar     {
14920ba04296SBram Moolenaar 	buf_T *buf = curbuf;
14931dced572SBram Moolenaar 	curbuf = b;
149455d5c034SBram Moolenaar 	if (u_savesub(n) == FAIL)
149555d5c034SBram Moolenaar 	{
14960ba04296SBram Moolenaar 	    curbuf = buf;
14970ba04296SBram Moolenaar 	    luaL_error(L, "cannot save undo information");
14980ba04296SBram Moolenaar 	}
149955d5c034SBram Moolenaar 	else if (ml_replace(n, luaV_toline(L, 3), TRUE) == FAIL)
150055d5c034SBram Moolenaar 	{
15010ba04296SBram Moolenaar 	    curbuf = buf;
15020ba04296SBram Moolenaar 	    luaL_error(L, "cannot replace line");
15030ba04296SBram Moolenaar 	}
15040ba04296SBram Moolenaar 	else changed_bytes(n, 0);
15050ba04296SBram Moolenaar 	curbuf = buf;
15061dced572SBram Moolenaar 	if (b == curwin->w_buffer)
15070ba04296SBram Moolenaar 	    check_cursor_col();
15080ba04296SBram Moolenaar     }
15090ba04296SBram Moolenaar     else
15100ba04296SBram Moolenaar 	luaL_error(L, "wrong argument to change line");
15110ba04296SBram Moolenaar     return 0;
15120ba04296SBram Moolenaar }
15130ba04296SBram Moolenaar 
151455d5c034SBram Moolenaar     static int
luaV_buffer_insert(lua_State * L)151555d5c034SBram Moolenaar luaV_buffer_insert(lua_State *L)
151655d5c034SBram Moolenaar {
15171dced572SBram Moolenaar     luaV_Buffer *lb = luaV_checkudata(L, 1, LUAVIM_BUFFER);
15181dced572SBram Moolenaar     buf_T *b = (buf_T *) luaV_checkcache(L, (void *) *lb);
15191dced572SBram Moolenaar     linenr_T last = b->b_ml.ml_line_count;
15200ba04296SBram Moolenaar     linenr_T n = (linenr_T) luaL_optinteger(L, 3, last);
15210ba04296SBram Moolenaar     buf_T *buf;
15220ba04296SBram Moolenaar     luaL_checktype(L, 2, LUA_TSTRING);
15230ba04296SBram Moolenaar #ifdef HAVE_SANDBOX
15240ba04296SBram Moolenaar     luaV_checksandbox(L);
15250ba04296SBram Moolenaar #endif
15262ab2e860SBram Moolenaar     // fix insertion line
15270ba04296SBram Moolenaar     if (n < 0) n = 0;
15280ba04296SBram Moolenaar     if (n > last) n = last;
15292ab2e860SBram Moolenaar     // insert
15300ba04296SBram Moolenaar     buf = curbuf;
15311dced572SBram Moolenaar     curbuf = b;
153255d5c034SBram Moolenaar     if (u_save(n, n + 1) == FAIL)
153355d5c034SBram Moolenaar     {
15340ba04296SBram Moolenaar 	curbuf = buf;
15350ba04296SBram Moolenaar 	luaL_error(L, "cannot save undo information");
15360ba04296SBram Moolenaar     }
153755d5c034SBram Moolenaar     else if (ml_append(n, luaV_toline(L, 2), 0, FALSE) == FAIL)
153855d5c034SBram Moolenaar     {
15390ba04296SBram Moolenaar 	curbuf = buf;
15400ba04296SBram Moolenaar 	luaL_error(L, "cannot insert line");
15410ba04296SBram Moolenaar     }
15420ba04296SBram Moolenaar     else
15430ba04296SBram Moolenaar 	appended_lines_mark(n, 1L);
15440ba04296SBram Moolenaar     curbuf = buf;
15450ba04296SBram Moolenaar     update_screen(VALID);
15460ba04296SBram Moolenaar     return 0;
15470ba04296SBram Moolenaar }
15480ba04296SBram Moolenaar 
154955d5c034SBram Moolenaar     static int
luaV_buffer_next(lua_State * L)155055d5c034SBram Moolenaar luaV_buffer_next(lua_State *L)
155155d5c034SBram Moolenaar {
15520ba04296SBram Moolenaar     luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
15531dced572SBram Moolenaar     buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b);
15541dced572SBram Moolenaar     luaV_pushbuffer(L, buf->b_next);
15550ba04296SBram Moolenaar     return 1;
15560ba04296SBram Moolenaar }
15570ba04296SBram Moolenaar 
155855d5c034SBram Moolenaar     static int
luaV_buffer_previous(lua_State * L)155955d5c034SBram Moolenaar luaV_buffer_previous(lua_State *L)
156055d5c034SBram Moolenaar {
15610ba04296SBram Moolenaar     luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
15621dced572SBram Moolenaar     buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b);
15631dced572SBram Moolenaar     luaV_pushbuffer(L, buf->b_prev);
15640ba04296SBram Moolenaar     return 1;
15650ba04296SBram Moolenaar }
15660ba04296SBram Moolenaar 
156755d5c034SBram Moolenaar     static int
luaV_buffer_isvalid(lua_State * L)156855d5c034SBram Moolenaar luaV_buffer_isvalid(lua_State *L)
156955d5c034SBram Moolenaar {
15700ba04296SBram Moolenaar     luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
15711dced572SBram Moolenaar     luaV_getudata(L, *b);
15720ba04296SBram Moolenaar     lua_pushboolean(L, !lua_isnil(L, -1));
15730ba04296SBram Moolenaar     return 1;
15740ba04296SBram Moolenaar }
15750ba04296SBram Moolenaar 
15760ba04296SBram Moolenaar static const luaL_Reg luaV_Buffer_mt[] = {
15770ba04296SBram Moolenaar     {"__tostring", luaV_buffer_tostring},
15780ba04296SBram Moolenaar     {"__len", luaV_buffer_len},
15790ba04296SBram Moolenaar     {"__call", luaV_buffer_call},
15800ba04296SBram Moolenaar     {"__index", luaV_buffer_index},
15810ba04296SBram Moolenaar     {"__newindex", luaV_buffer_newindex},
15820ba04296SBram Moolenaar     {"insert", luaV_buffer_insert},
15830ba04296SBram Moolenaar     {"next", luaV_buffer_next},
15840ba04296SBram Moolenaar     {"previous", luaV_buffer_previous},
15850ba04296SBram Moolenaar     {"isvalid", luaV_buffer_isvalid},
15860ba04296SBram Moolenaar     {NULL, NULL}
15870ba04296SBram Moolenaar };
15880ba04296SBram Moolenaar 
15890ba04296SBram Moolenaar 
15902ab2e860SBram Moolenaar // =======   Window type   =======
15910ba04296SBram Moolenaar 
luaV_newtype(win_T,window,luaV_Window,LUAVIM_WINDOW)15921dced572SBram Moolenaar luaV_newtype(win_T, window, luaV_Window, LUAVIM_WINDOW)
15931dced572SBram Moolenaar luaV_pushtype(win_T, window, luaV_Window)
15941dced572SBram Moolenaar luaV_type_tostring(window, LUAVIM_WINDOW)
15950ba04296SBram Moolenaar 
159655d5c034SBram Moolenaar     static int
159755d5c034SBram Moolenaar luaV_window_call(lua_State *L)
159855d5c034SBram Moolenaar {
15991dced572SBram Moolenaar     win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
16000ba04296SBram Moolenaar     lua_settop(L, 1);
16011dced572SBram Moolenaar     win_goto(w);
16020ba04296SBram Moolenaar     return 1;
16030ba04296SBram Moolenaar }
16040ba04296SBram Moolenaar 
160555d5c034SBram Moolenaar     static int
luaV_window_index(lua_State * L)160655d5c034SBram Moolenaar luaV_window_index(lua_State *L)
160755d5c034SBram Moolenaar {
16081dced572SBram Moolenaar     win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
16090ba04296SBram Moolenaar     const char *s = luaL_checkstring(L, 2);
16100ba04296SBram Moolenaar     if (strncmp(s, "buffer", 6) == 0)
16111dced572SBram Moolenaar 	luaV_pushbuffer(L, w->w_buffer);
16120ba04296SBram Moolenaar     else if (strncmp(s, "line", 4) == 0)
16131dced572SBram Moolenaar 	lua_pushinteger(L, w->w_cursor.lnum);
16140ba04296SBram Moolenaar     else if (strncmp(s, "col", 3) == 0)
16151dced572SBram Moolenaar 	lua_pushinteger(L, w->w_cursor.col + 1);
16160ba04296SBram Moolenaar     else if (strncmp(s, "width", 5) == 0)
16170263146bSBram Moolenaar 	lua_pushinteger(L, w->w_width);
16180ba04296SBram Moolenaar     else if (strncmp(s, "height", 6) == 0)
16191dced572SBram Moolenaar 	lua_pushinteger(L, w->w_height);
16202ab2e860SBram Moolenaar     // methods
16210ba04296SBram Moolenaar     else if (strncmp(s,   "next", 4) == 0
16220ba04296SBram Moolenaar 	    || strncmp(s, "previous", 8) == 0
162355d5c034SBram Moolenaar 	    || strncmp(s, "isvalid", 7) == 0)
162455d5c034SBram Moolenaar     {
16250ba04296SBram Moolenaar 	lua_getmetatable(L, 1);
16260ba04296SBram Moolenaar 	lua_getfield(L, -1, s);
16270ba04296SBram Moolenaar     }
16280ba04296SBram Moolenaar     else
16290ba04296SBram Moolenaar 	lua_pushnil(L);
16300ba04296SBram Moolenaar     return 1;
16310ba04296SBram Moolenaar }
16320ba04296SBram Moolenaar 
163355d5c034SBram Moolenaar     static int
luaV_window_newindex(lua_State * L)163455d5c034SBram Moolenaar luaV_window_newindex(lua_State *L)
163555d5c034SBram Moolenaar {
16361dced572SBram Moolenaar     win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
16370ba04296SBram Moolenaar     const char *s = luaL_checkstring(L, 2);
16380ba04296SBram Moolenaar     int v = luaL_checkinteger(L, 3);
163955d5c034SBram Moolenaar     if (strncmp(s, "line", 4) == 0)
164055d5c034SBram Moolenaar     {
16410ba04296SBram Moolenaar #ifdef HAVE_SANDBOX
16420ba04296SBram Moolenaar 	luaV_checksandbox(L);
16430ba04296SBram Moolenaar #endif
16441dced572SBram Moolenaar 	if (v < 1 || v > w->w_buffer->b_ml.ml_line_count)
16450ba04296SBram Moolenaar 	    luaL_error(L, "line out of range");
16461dced572SBram Moolenaar 	w->w_cursor.lnum = v;
16470ba04296SBram Moolenaar 	update_screen(VALID);
16480ba04296SBram Moolenaar     }
164955d5c034SBram Moolenaar     else if (strncmp(s, "col", 3) == 0)
165055d5c034SBram Moolenaar     {
16510ba04296SBram Moolenaar #ifdef HAVE_SANDBOX
16520ba04296SBram Moolenaar 	luaV_checksandbox(L);
16530ba04296SBram Moolenaar #endif
16541dced572SBram Moolenaar 	w->w_cursor.col = v - 1;
165553901442SBram Moolenaar 	w->w_set_curswant = TRUE;
16560ba04296SBram Moolenaar 	update_screen(VALID);
16570ba04296SBram Moolenaar     }
165855d5c034SBram Moolenaar     else if (strncmp(s, "width", 5) == 0)
165955d5c034SBram Moolenaar     {
16600ba04296SBram Moolenaar 	win_T *win = curwin;
16610ba04296SBram Moolenaar #ifdef FEAT_GUI
16620ba04296SBram Moolenaar 	need_mouse_correct = TRUE;
16630ba04296SBram Moolenaar #endif
16641dced572SBram Moolenaar 	curwin = w;
16650ba04296SBram Moolenaar 	win_setwidth(v);
16660ba04296SBram Moolenaar 	curwin = win;
16670ba04296SBram Moolenaar     }
166855d5c034SBram Moolenaar     else if (strncmp(s, "height", 6) == 0)
166955d5c034SBram Moolenaar     {
16700ba04296SBram Moolenaar 	win_T *win = curwin;
16710ba04296SBram Moolenaar #ifdef FEAT_GUI
16720ba04296SBram Moolenaar 	need_mouse_correct = TRUE;
16730ba04296SBram Moolenaar #endif
16741dced572SBram Moolenaar 	curwin = w;
16750ba04296SBram Moolenaar 	win_setheight(v);
16760ba04296SBram Moolenaar 	curwin = win;
16770ba04296SBram Moolenaar     }
16780ba04296SBram Moolenaar     else
16790ba04296SBram Moolenaar 	luaL_error(L, "invalid window property: `%s'", s);
16800ba04296SBram Moolenaar     return 0;
16810ba04296SBram Moolenaar }
16820ba04296SBram Moolenaar 
168355d5c034SBram Moolenaar     static int
luaV_window_next(lua_State * L)168455d5c034SBram Moolenaar luaV_window_next(lua_State *L)
168555d5c034SBram Moolenaar {
16860ba04296SBram Moolenaar     luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
16871dced572SBram Moolenaar     win_T *win = (win_T *) luaV_checkcache(L, (void *) *w);
16881dced572SBram Moolenaar     luaV_pushwindow(L, win->w_next);
16890ba04296SBram Moolenaar     return 1;
16900ba04296SBram Moolenaar }
16910ba04296SBram Moolenaar 
169255d5c034SBram Moolenaar     static int
luaV_window_previous(lua_State * L)169355d5c034SBram Moolenaar luaV_window_previous(lua_State *L)
169455d5c034SBram Moolenaar {
16950ba04296SBram Moolenaar     luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
16961dced572SBram Moolenaar     win_T *win = (win_T *) luaV_checkcache(L, (void *) *w);
16971dced572SBram Moolenaar     luaV_pushwindow(L, win->w_prev);
16980ba04296SBram Moolenaar     return 1;
16990ba04296SBram Moolenaar }
17000ba04296SBram Moolenaar 
170155d5c034SBram Moolenaar     static int
luaV_window_isvalid(lua_State * L)170255d5c034SBram Moolenaar luaV_window_isvalid(lua_State *L)
170355d5c034SBram Moolenaar {
17040ba04296SBram Moolenaar     luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
17051dced572SBram Moolenaar     luaV_getudata(L, *w);
17060ba04296SBram Moolenaar     lua_pushboolean(L, !lua_isnil(L, -1));
17070ba04296SBram Moolenaar     return 1;
17080ba04296SBram Moolenaar }
17090ba04296SBram Moolenaar 
17100ba04296SBram Moolenaar static const luaL_Reg luaV_Window_mt[] = {
17110ba04296SBram Moolenaar     {"__tostring", luaV_window_tostring},
17120ba04296SBram Moolenaar     {"__call", luaV_window_call},
17130ba04296SBram Moolenaar     {"__index", luaV_window_index},
17140ba04296SBram Moolenaar     {"__newindex", luaV_window_newindex},
17150ba04296SBram Moolenaar     {"next", luaV_window_next},
17160ba04296SBram Moolenaar     {"previous", luaV_window_previous},
17170ba04296SBram Moolenaar     {"isvalid", luaV_window_isvalid},
17180ba04296SBram Moolenaar     {NULL, NULL}
17190ba04296SBram Moolenaar };
17200ba04296SBram Moolenaar 
17210ba04296SBram Moolenaar 
17222ab2e860SBram Moolenaar // =======   Vim module   =======
17230ba04296SBram Moolenaar 
172455d5c034SBram Moolenaar     static int
luaV_print(lua_State * L)172555d5c034SBram Moolenaar luaV_print(lua_State *L)
172655d5c034SBram Moolenaar {
17272ab2e860SBram Moolenaar     int		i, n = lua_gettop(L); // nargs
17280ba04296SBram Moolenaar     const char	*s;
17290ba04296SBram Moolenaar     size_t	l;
173041114a2aSYegappan Lakshmanan     garray_T	msg_ga;
173141114a2aSYegappan Lakshmanan 
173241114a2aSYegappan Lakshmanan     ga_init2(&msg_ga, 1, 128);
17330ba04296SBram Moolenaar     lua_getglobal(L, "tostring");
173455d5c034SBram Moolenaar     for (i = 1; i <= n; i++)
173555d5c034SBram Moolenaar     {
17362ab2e860SBram Moolenaar 	lua_pushvalue(L, -1); // tostring
17372ab2e860SBram Moolenaar 	lua_pushvalue(L, i); // arg
17380ba04296SBram Moolenaar 	lua_call(L, 1, 1);
17390ba04296SBram Moolenaar 	s = lua_tolstring(L, -1, &l);
17400ba04296SBram Moolenaar 	if (s == NULL)
17410ba04296SBram Moolenaar 	    return luaL_error(L, "cannot convert to string");
174278e006b9SBram Moolenaar 	if (i > 1)
174341114a2aSYegappan Lakshmanan 	    ga_append(&msg_ga, ' '); // use space instead of tab
174441114a2aSYegappan Lakshmanan 	ga_concat_len(&msg_ga, (char_u *)s, l);
17452a4bd00cSBram Moolenaar 	lua_pop(L, 1);
17460ba04296SBram Moolenaar     }
174741114a2aSYegappan Lakshmanan     // Replace any "\n" with "\0"
174841114a2aSYegappan Lakshmanan     for (i = 0; i < msg_ga.ga_len; i++)
174941114a2aSYegappan Lakshmanan 	if (((char *)msg_ga.ga_data)[i] == '\n')
175041114a2aSYegappan Lakshmanan 	    ((char *)msg_ga.ga_data)[i] = '\0';
175141114a2aSYegappan Lakshmanan     lua_pushlstring(L, msg_ga.ga_data, msg_ga.ga_len);
1752b98678a9SBram Moolenaar     if (!got_int)
17530ba04296SBram Moolenaar 	luaV_msg(L);
175441114a2aSYegappan Lakshmanan 
175541114a2aSYegappan Lakshmanan     ga_clear(&msg_ga);
17560ba04296SBram Moolenaar     return 0;
17570ba04296SBram Moolenaar }
17580ba04296SBram Moolenaar 
175955d5c034SBram Moolenaar     static int
luaV_debug(lua_State * L)176038e2b063SBram Moolenaar luaV_debug(lua_State *L)
176138e2b063SBram Moolenaar {
176238e2b063SBram Moolenaar     lua_settop(L, 0);
176338e2b063SBram Moolenaar     lua_getglobal(L, "vim");
176438e2b063SBram Moolenaar     lua_getfield(L, -1, "eval");
17652ab2e860SBram Moolenaar     lua_remove(L, -2); // vim.eval at position 1
176638e2b063SBram Moolenaar     for (;;)
176738e2b063SBram Moolenaar     {
176838e2b063SBram Moolenaar 	const char *input;
176938e2b063SBram Moolenaar 	size_t l;
17702ab2e860SBram Moolenaar 	lua_pushvalue(L, 1); // vim.eval
177138e2b063SBram Moolenaar 	lua_pushliteral(L, "input('lua_debug> ')");
17722ab2e860SBram Moolenaar 	lua_call(L, 1, 1); // return string
177338e2b063SBram Moolenaar 	input = lua_tolstring(L, -1, &l);
177438e2b063SBram Moolenaar 	if (l == 0 || strcmp(input, "cont") == 0)
177538e2b063SBram Moolenaar 	    return 0;
17762ab2e860SBram Moolenaar 	msg_putchar('\n'); // avoid outputting on input line
177738e2b063SBram Moolenaar 	if (luaL_loadbuffer(L, input, l, "=(debug command)")
177838e2b063SBram Moolenaar 		|| lua_pcall(L, 0, 0, 0))
177938e2b063SBram Moolenaar 	    luaV_emsg(L);
17802ab2e860SBram Moolenaar 	lua_settop(L, 1); // remove eventual returns, but keep vim.eval
178138e2b063SBram Moolenaar     }
178238e2b063SBram Moolenaar }
178338e2b063SBram Moolenaar 
17849dc4bef8SYegappan Lakshmanan     static dict_T *
luaV_get_var_scope(lua_State * L)17859dc4bef8SYegappan Lakshmanan luaV_get_var_scope(lua_State *L)
17869dc4bef8SYegappan Lakshmanan {
17879dc4bef8SYegappan Lakshmanan     const char	*scope = luaL_checkstring(L, 1);
17889dc4bef8SYegappan Lakshmanan     dict_T	*dict = NULL;
17899dc4bef8SYegappan Lakshmanan 
17909dc4bef8SYegappan Lakshmanan     if (STRICMP((char *)scope, "g") == 0)
17919dc4bef8SYegappan Lakshmanan 	dict = get_globvar_dict();
17929dc4bef8SYegappan Lakshmanan     else if (STRICMP((char *)scope, "v") == 0)
17939dc4bef8SYegappan Lakshmanan 	dict = get_vimvar_dict();
17949dc4bef8SYegappan Lakshmanan     else if (STRICMP((char *)scope, "b") == 0)
17959dc4bef8SYegappan Lakshmanan 	dict = curbuf->b_vars;
17969dc4bef8SYegappan Lakshmanan     else if (STRICMP((char *)scope, "w") == 0)
17979dc4bef8SYegappan Lakshmanan 	dict = curwin->w_vars;
17989dc4bef8SYegappan Lakshmanan     else if (STRICMP((char *)scope, "t") == 0)
17999dc4bef8SYegappan Lakshmanan 	dict = curtab->tp_vars;
18009dc4bef8SYegappan Lakshmanan     else
18019dc4bef8SYegappan Lakshmanan     {
18029dc4bef8SYegappan Lakshmanan 	luaL_error(L, "invalid scope %s", scope);
18039dc4bef8SYegappan Lakshmanan 	return NULL;
18049dc4bef8SYegappan Lakshmanan     }
18059dc4bef8SYegappan Lakshmanan 
18069dc4bef8SYegappan Lakshmanan     return dict;
18079dc4bef8SYegappan Lakshmanan }
18089dc4bef8SYegappan Lakshmanan 
18099dc4bef8SYegappan Lakshmanan     static int
luaV_setvar(lua_State * L)18109dc4bef8SYegappan Lakshmanan luaV_setvar(lua_State *L)
18119dc4bef8SYegappan Lakshmanan {
18129dc4bef8SYegappan Lakshmanan     dict_T	*dict;
18139dc4bef8SYegappan Lakshmanan     dictitem_T	*di;
18149dc4bef8SYegappan Lakshmanan     size_t	len;
18159dc4bef8SYegappan Lakshmanan     char	*name;
18169dc4bef8SYegappan Lakshmanan     int		del;
18179dc4bef8SYegappan Lakshmanan     char	*error = NULL;
18189dc4bef8SYegappan Lakshmanan 
18199dc4bef8SYegappan Lakshmanan     name = (char *)luaL_checklstring(L, 3, &len);
18209dc4bef8SYegappan Lakshmanan     del = (lua_gettop(L) < 4) || lua_isnil(L, 4);
18219dc4bef8SYegappan Lakshmanan 
18229dc4bef8SYegappan Lakshmanan     dict = luaV_get_var_scope(L);
18239dc4bef8SYegappan Lakshmanan     if (dict == NULL)
18249dc4bef8SYegappan Lakshmanan 	return 0;
18259dc4bef8SYegappan Lakshmanan 
182611328bc7SYegappan Lakshmanan     di = dict_find(dict, (char_u *)name, (int)len);
18279dc4bef8SYegappan Lakshmanan     if (di != NULL)
18289dc4bef8SYegappan Lakshmanan     {
18299dc4bef8SYegappan Lakshmanan 	if (di->di_flags & DI_FLAGS_RO)
18309dc4bef8SYegappan Lakshmanan 	    error = "variable is read-only";
18319dc4bef8SYegappan Lakshmanan 	else if (di->di_flags & DI_FLAGS_LOCK)
18329dc4bef8SYegappan Lakshmanan 	    error = "variable is locked";
18339dc4bef8SYegappan Lakshmanan 	else if (del && di->di_flags & DI_FLAGS_FIX)
18349dc4bef8SYegappan Lakshmanan 	    error = "variable is fixed";
18359dc4bef8SYegappan Lakshmanan 	if (error != NULL)
18369dc4bef8SYegappan Lakshmanan 	    return luaL_error(L, error);
18379dc4bef8SYegappan Lakshmanan     }
18389dc4bef8SYegappan Lakshmanan     else if (dict->dv_lock)
18399dc4bef8SYegappan Lakshmanan 	return luaL_error(L, "Dictionary is locked");
18409dc4bef8SYegappan Lakshmanan 
18419dc4bef8SYegappan Lakshmanan     if (del)
18429dc4bef8SYegappan Lakshmanan     {
18439dc4bef8SYegappan Lakshmanan 	// Delete the key
18449dc4bef8SYegappan Lakshmanan 	if (di == NULL)
18459dc4bef8SYegappan Lakshmanan 	    // Doesn't exist, nothing to do
18469dc4bef8SYegappan Lakshmanan 	    return 0;
18479dc4bef8SYegappan Lakshmanan 	else
18489dc4bef8SYegappan Lakshmanan 	    // Delete the entry
18499dc4bef8SYegappan Lakshmanan 	    dictitem_remove(dict, di);
18509dc4bef8SYegappan Lakshmanan     }
18519dc4bef8SYegappan Lakshmanan     else
18529dc4bef8SYegappan Lakshmanan     {
18539dc4bef8SYegappan Lakshmanan 	// Update the key
18549dc4bef8SYegappan Lakshmanan 	typval_T	tv;
18559dc4bef8SYegappan Lakshmanan 
1856*965d2edbSh-east 	// Convert the lua value to a Vim script type in the temporary variable
18579dc4bef8SYegappan Lakshmanan 	lua_pushvalue(L, 4);
18589dc4bef8SYegappan Lakshmanan 	if (luaV_totypval(L, -1, &tv) == FAIL)
18599dc4bef8SYegappan Lakshmanan 	    return luaL_error(L, "Couldn't convert lua value");
18609dc4bef8SYegappan Lakshmanan 
18619dc4bef8SYegappan Lakshmanan 	if (di == NULL)
18629dc4bef8SYegappan Lakshmanan 	{
18639dc4bef8SYegappan Lakshmanan 	    // Need to create an entry
18649dc4bef8SYegappan Lakshmanan 	    di = dictitem_alloc((char_u *)name);
18659dc4bef8SYegappan Lakshmanan 	    if (di == NULL)
18661b6acf02SBram Moolenaar 	    {
18671b6acf02SBram Moolenaar 		clear_tv(&tv);
18689dc4bef8SYegappan Lakshmanan 		return 0;
18691b6acf02SBram Moolenaar 	    }
18709dc4bef8SYegappan Lakshmanan 	    // Update the value
18719dc4bef8SYegappan Lakshmanan 	    copy_tv(&tv, &di->di_tv);
18724a01159dSBram Moolenaar 	    if (dict_add(dict, di) == FAIL)
18731b6acf02SBram Moolenaar 	    {
18741b6acf02SBram Moolenaar 		dictitem_free(di);
18751b6acf02SBram Moolenaar 		clear_tv(&tv);
18764a01159dSBram Moolenaar 		return luaL_error(L, "Couldn't add to dictionary");
18771b6acf02SBram Moolenaar 	    }
18781b6acf02SBram Moolenaar 	}
18791b6acf02SBram Moolenaar 	else
18809dc4bef8SYegappan Lakshmanan 	{
18819dc4bef8SYegappan Lakshmanan 	    // Clear the old value
18829dc4bef8SYegappan Lakshmanan 	    clear_tv(&di->di_tv);
18839dc4bef8SYegappan Lakshmanan 	    // Update the value
18849dc4bef8SYegappan Lakshmanan 	    copy_tv(&tv, &di->di_tv);
18859dc4bef8SYegappan Lakshmanan 	}
18869dc4bef8SYegappan Lakshmanan 
18879dc4bef8SYegappan Lakshmanan 	// Clear the temporary variable
18889dc4bef8SYegappan Lakshmanan 	clear_tv(&tv);
18899dc4bef8SYegappan Lakshmanan     }
18909dc4bef8SYegappan Lakshmanan 
18919dc4bef8SYegappan Lakshmanan     return 0;
18929dc4bef8SYegappan Lakshmanan }
18939dc4bef8SYegappan Lakshmanan 
18949dc4bef8SYegappan Lakshmanan     static int
luaV_getvar(lua_State * L)18959dc4bef8SYegappan Lakshmanan luaV_getvar(lua_State *L)
18969dc4bef8SYegappan Lakshmanan {
18979dc4bef8SYegappan Lakshmanan     dict_T	*dict = luaV_get_var_scope(L);
18989dc4bef8SYegappan Lakshmanan     size_t	len;
18999dc4bef8SYegappan Lakshmanan     const char	*name = luaL_checklstring(L, 3, &len);
190011328bc7SYegappan Lakshmanan     dictitem_T	*di = dict_find(dict, (char_u *)name, (int)len);
19019dc4bef8SYegappan Lakshmanan 
19029dc4bef8SYegappan Lakshmanan     if (di == NULL)
19039dc4bef8SYegappan Lakshmanan 	return 0;  // nil
19049dc4bef8SYegappan Lakshmanan 
19059dc4bef8SYegappan Lakshmanan     luaV_pushtypval(L, &di->di_tv);
19069dc4bef8SYegappan Lakshmanan     return 1;
19079dc4bef8SYegappan Lakshmanan }
19089dc4bef8SYegappan Lakshmanan 
190938e2b063SBram Moolenaar     static int
luaV_command(lua_State * L)191055d5c034SBram Moolenaar luaV_command(lua_State *L)
191155d5c034SBram Moolenaar {
191211328bc7SYegappan Lakshmanan     char_u  *s = vim_strsave((char_u *)luaL_checkstring(L, 1));
191311328bc7SYegappan Lakshmanan 
191411328bc7SYegappan Lakshmanan     execute_cmds_from_string(s);
191511328bc7SYegappan Lakshmanan     vim_free(s);
19160ba04296SBram Moolenaar     update_screen(VALID);
19170ba04296SBram Moolenaar     return 0;
19180ba04296SBram Moolenaar }
19190ba04296SBram Moolenaar 
192055d5c034SBram Moolenaar     static int
luaV_eval(lua_State * L)192155d5c034SBram Moolenaar luaV_eval(lua_State *L)
192255d5c034SBram Moolenaar {
19230ba04296SBram Moolenaar     typval_T *tv = eval_expr((char_u *) luaL_checkstring(L, 1), NULL);
192411328bc7SYegappan Lakshmanan 
19250ba04296SBram Moolenaar     if (tv == NULL) luaL_error(L, "invalid expression");
19260ba04296SBram Moolenaar     luaV_pushtypval(L, tv);
1927b376647bSBram Moolenaar     free_tv(tv);
19280ba04296SBram Moolenaar     return 1;
19290ba04296SBram Moolenaar }
19300ba04296SBram Moolenaar 
193155d5c034SBram Moolenaar     static int
luaV_beep(lua_State * L UNUSED)19320d2e4fceSBram Moolenaar luaV_beep(lua_State *L UNUSED)
193355d5c034SBram Moolenaar {
1934165bc69dSBram Moolenaar     vim_beep(BO_LANG);
19350ba04296SBram Moolenaar     return 0;
19360ba04296SBram Moolenaar }
19370ba04296SBram Moolenaar 
193855d5c034SBram Moolenaar     static int
luaV_line(lua_State * L)193955d5c034SBram Moolenaar luaV_line(lua_State *L)
194055d5c034SBram Moolenaar {
19410ba04296SBram Moolenaar     luaV_pushline(L, curbuf, curwin->w_cursor.lnum);
19420ba04296SBram Moolenaar     return 1;
19430ba04296SBram Moolenaar }
19440ba04296SBram Moolenaar 
194555d5c034SBram Moolenaar     static int
luaV_list(lua_State * L)19461dced572SBram Moolenaar luaV_list(lua_State *L)
19471dced572SBram Moolenaar {
1948ca06da92SBram Moolenaar     list_T *l;
1949ca06da92SBram Moolenaar     int initarg = !lua_isnoneornil(L, 1);
1950ca06da92SBram Moolenaar 
1951ca06da92SBram Moolenaar     if (initarg && lua_type(L, 1) != LUA_TTABLE)
1952ca06da92SBram Moolenaar 	luaL_error(L, "table expected, got %s", luaL_typename(L, 1));
1953ca06da92SBram Moolenaar     l = list_alloc();
19541dced572SBram Moolenaar     if (l == NULL)
19551dced572SBram Moolenaar 	lua_pushnil(L);
19561dced572SBram Moolenaar     else
1957ca06da92SBram Moolenaar     {
19581dced572SBram Moolenaar 	luaV_newlist(L, l);
19592ab2e860SBram Moolenaar 	if (initarg) // traverse table to init list
196017413671SBram Moolenaar 	{
1961ca06da92SBram Moolenaar 	    int notnil, i = 0;
1962ca06da92SBram Moolenaar 	    typval_T v;
196317413671SBram Moolenaar 	    do
196417413671SBram Moolenaar 	    {
1965ca06da92SBram Moolenaar 		lua_rawgeti(L, 1, ++i);
1966ca06da92SBram Moolenaar 		notnil = !lua_isnil(L, -1);
196717413671SBram Moolenaar 		if (notnil)
196817413671SBram Moolenaar 		{
1969ca06da92SBram Moolenaar 		    luaV_checktypval(L, -1, &v, "vim.list");
1970ca06da92SBram Moolenaar 		    list_append_tv(l, &v);
1971713bf9e9SBram Moolenaar 		    clear_tv(&v);
1972ca06da92SBram Moolenaar 		}
19732ab2e860SBram Moolenaar 		lua_pop(L, 1); // value
1974ca06da92SBram Moolenaar 	    } while (notnil);
1975ca06da92SBram Moolenaar 	}
1976ca06da92SBram Moolenaar     }
19771dced572SBram Moolenaar     return 1;
19781dced572SBram Moolenaar }
19791dced572SBram Moolenaar 
19801dced572SBram Moolenaar     static int
luaV_dict(lua_State * L)19811dced572SBram Moolenaar luaV_dict(lua_State *L)
19821dced572SBram Moolenaar {
1983ca06da92SBram Moolenaar     dict_T *d;
1984ca06da92SBram Moolenaar     int initarg = !lua_isnoneornil(L, 1);
1985ca06da92SBram Moolenaar 
1986ca06da92SBram Moolenaar     if (initarg && lua_type(L, 1) != LUA_TTABLE)
1987ca06da92SBram Moolenaar 	luaL_error(L, "table expected, got %s", luaL_typename(L, 1));
1988ca06da92SBram Moolenaar     d = dict_alloc();
19891dced572SBram Moolenaar     if (d == NULL)
19901dced572SBram Moolenaar 	lua_pushnil(L);
19911dced572SBram Moolenaar     else
1992ca06da92SBram Moolenaar     {
19931dced572SBram Moolenaar 	luaV_newdict(L, d);
19942ab2e860SBram Moolenaar 	if (initarg) // traverse table to init dict
1995ca06da92SBram Moolenaar 	{
1996ca06da92SBram Moolenaar 	    lua_pushnil(L);
1997ca06da92SBram Moolenaar 	    while (lua_next(L, 1))
1998ca06da92SBram Moolenaar 	    {
1999ca06da92SBram Moolenaar 		char_u *key;
2000ca06da92SBram Moolenaar 		dictitem_T *di;
2001ca06da92SBram Moolenaar 		typval_T v;
2002d6ef5f9bSBram Moolenaar 
20032ab2e860SBram Moolenaar 		lua_pushvalue(L, -2); // dup key in case it's a number
2004ca06da92SBram Moolenaar 		key = (char_u *) lua_tostring(L, -1);
2005d6ef5f9bSBram Moolenaar 		if (key == NULL)
2006d6ef5f9bSBram Moolenaar 		{
2007d6ef5f9bSBram Moolenaar 		    lua_pushnil(L);
2008d6ef5f9bSBram Moolenaar 		    return 1;
2009d6ef5f9bSBram Moolenaar 		}
2010d6ef5f9bSBram Moolenaar 		if (*key == NUL)
2011ca06da92SBram Moolenaar 		    luaL_error(L, "table has empty key");
20122ab2e860SBram Moolenaar 		luaV_checktypval(L, -2, &v, "vim.dict"); // value
2013ca06da92SBram Moolenaar 		di = dictitem_alloc(key);
2014d6ef5f9bSBram Moolenaar 		if (di == NULL || dict_add(d, di) == FAIL)
2015d6ef5f9bSBram Moolenaar 		{
2016ca06da92SBram Moolenaar 		    vim_free(di);
2017ca06da92SBram Moolenaar 		    lua_pushnil(L);
2018ca06da92SBram Moolenaar 		    return 1;
2019ca06da92SBram Moolenaar 		}
2020e49b8e8dSBram Moolenaar 		di->di_tv = v;
20212ab2e860SBram Moolenaar 		lua_pop(L, 2); // key copy and value
2022ca06da92SBram Moolenaar 	    }
2023ca06da92SBram Moolenaar 	}
2024ca06da92SBram Moolenaar     }
2025ca06da92SBram Moolenaar     return 1;
2026ca06da92SBram Moolenaar }
2027ca06da92SBram Moolenaar 
2028ca06da92SBram Moolenaar     static int
luaV_blob(lua_State * L)2029b7828690SBram Moolenaar luaV_blob(lua_State *L)
2030b7828690SBram Moolenaar {
2031b7828690SBram Moolenaar     blob_T *b;
2032b7828690SBram Moolenaar     int initarg = !lua_isnoneornil(L, 1);
2033b7828690SBram Moolenaar 
2034b7828690SBram Moolenaar     if (initarg && !lua_isstring(L, 1))
2035b7828690SBram Moolenaar 	luaL_error(L, "string expected, got %s", luaL_typename(L, 1));
2036b7828690SBram Moolenaar     b = blob_alloc();
2037b7828690SBram Moolenaar     if (b == NULL)
2038b7828690SBram Moolenaar 	lua_pushnil(L);
2039b7828690SBram Moolenaar     else
2040b7828690SBram Moolenaar     {
2041b7828690SBram Moolenaar 	luaV_newblob(L, b);
2042b7828690SBram Moolenaar 	if (initarg)
2043b7828690SBram Moolenaar 	{
2044b7828690SBram Moolenaar 	    size_t i, l = 0;
2045b7828690SBram Moolenaar 	    const char *s = lua_tolstring(L, 1, &l);
2046b7828690SBram Moolenaar 
20475f1d3ae8SBram Moolenaar 	    if (ga_grow(&b->bv_ga, (int)l) == OK)
2048b7828690SBram Moolenaar 		for (i = 0; i < l; ++i)
2049b7828690SBram Moolenaar 		    ga_append(&b->bv_ga, s[i]);
2050b7828690SBram Moolenaar 	}
2051b7828690SBram Moolenaar     }
2052b7828690SBram Moolenaar     return 1;
2053b7828690SBram Moolenaar }
2054b7828690SBram Moolenaar 
2055b7828690SBram Moolenaar     static int
luaV_funcref(lua_State * L)2056ca06da92SBram Moolenaar luaV_funcref(lua_State *L)
2057ca06da92SBram Moolenaar {
2058ca06da92SBram Moolenaar     const char *name = luaL_checkstring(L, 1);
20592ab2e860SBram Moolenaar     // note: not checking if function exists (needs function_exists)
2060ca06da92SBram Moolenaar     if (name == NULL || *name == NUL || VIM_ISDIGIT(*name))
2061ca06da92SBram Moolenaar 	luaL_error(L, "invalid function name: %s", name);
2062ca06da92SBram Moolenaar     luaV_newfuncref(L, (char_u *) name);
20631dced572SBram Moolenaar     return 1;
20641dced572SBram Moolenaar }
20651dced572SBram Moolenaar 
20661dced572SBram Moolenaar     static int
luaV_buffer(lua_State * L)206755d5c034SBram Moolenaar luaV_buffer(lua_State *L)
206855d5c034SBram Moolenaar {
20690ba04296SBram Moolenaar     buf_T *buf;
20702ab2e860SBram Moolenaar     if (lua_isstring(L, 1)) // get by number or name?
207155d5c034SBram Moolenaar     {
20722ab2e860SBram Moolenaar 	if (lua_isnumber(L, 1)) // by number?
207355d5c034SBram Moolenaar 	{
20740ba04296SBram Moolenaar 	    int n = lua_tointeger(L, 1);
207529323590SBram Moolenaar 	    FOR_ALL_BUFFERS(buf)
20760ba04296SBram Moolenaar 		if (buf->b_fnum == n) break;
20770ba04296SBram Moolenaar 	}
2078ca06da92SBram Moolenaar 	else // by name
2079ca06da92SBram Moolenaar 	{
20800ba04296SBram Moolenaar 	    size_t l;
20810ba04296SBram Moolenaar 	    const char *s = lua_tolstring(L, 1, &l);
208229323590SBram Moolenaar 	    FOR_ALL_BUFFERS(buf)
208355d5c034SBram Moolenaar 	    {
208455d5c034SBram Moolenaar 		if (buf->b_ffname == NULL || buf->b_sfname == NULL)
208555d5c034SBram Moolenaar 		{
20860ba04296SBram Moolenaar 		    if (l == 0) break;
20870ba04296SBram Moolenaar 		}
20880d2e4fceSBram Moolenaar 		else if (strncmp(s, (char *)buf->b_ffname, l) == 0
20890d2e4fceSBram Moolenaar 			|| strncmp(s, (char *)buf->b_sfname, l) == 0)
20900ba04296SBram Moolenaar 		    break;
20910ba04296SBram Moolenaar 	    }
20920ba04296SBram Moolenaar 	}
20930ba04296SBram Moolenaar     }
20941dced572SBram Moolenaar     else
20952ab2e860SBram Moolenaar 	buf = (lua_toboolean(L, 1)) ? firstbuf : curbuf; // first buffer?
20960ba04296SBram Moolenaar     luaV_pushbuffer(L, buf);
20970ba04296SBram Moolenaar     return 1;
20980ba04296SBram Moolenaar }
20990ba04296SBram Moolenaar 
210055d5c034SBram Moolenaar     static int
luaV_window(lua_State * L)210155d5c034SBram Moolenaar luaV_window(lua_State *L)
210255d5c034SBram Moolenaar {
21030ba04296SBram Moolenaar     win_T *win;
21042ab2e860SBram Moolenaar     if (lua_isnumber(L, 1)) // get by number?
210555d5c034SBram Moolenaar     {
21060ba04296SBram Moolenaar 	int n = lua_tointeger(L, 1);
21070ba04296SBram Moolenaar 	for (win = firstwin; win != NULL; win = win->w_next, n--)
21080ba04296SBram Moolenaar 	    if (n == 1) break;
21090ba04296SBram Moolenaar     }
21101dced572SBram Moolenaar     else
21112ab2e860SBram Moolenaar 	win = (lua_toboolean(L, 1)) ? firstwin : curwin; // first window?
21120ba04296SBram Moolenaar     luaV_pushwindow(L, win);
21130ba04296SBram Moolenaar     return 1;
21140ba04296SBram Moolenaar }
21150ba04296SBram Moolenaar 
211655d5c034SBram Moolenaar     static int
luaV_open(lua_State * L)211755d5c034SBram Moolenaar luaV_open(lua_State *L)
211855d5c034SBram Moolenaar {
21190ba04296SBram Moolenaar     char_u *s = NULL;
21200ba04296SBram Moolenaar #ifdef HAVE_SANDBOX
21210ba04296SBram Moolenaar     luaV_checksandbox(L);
21220ba04296SBram Moolenaar #endif
21230ba04296SBram Moolenaar     if (lua_isstring(L, 1)) s = (char_u *) lua_tostring(L, 1);
2124fa263a51SBram Moolenaar     luaV_pushbuffer(L, buflist_new(s, NULL, 1L, BLN_LISTED));
21250ba04296SBram Moolenaar     return 1;
21260ba04296SBram Moolenaar }
21270ba04296SBram Moolenaar 
212855d5c034SBram Moolenaar     static int
luaV_type(lua_State * L)21291dced572SBram Moolenaar luaV_type(lua_State *L)
213055d5c034SBram Moolenaar {
21311dced572SBram Moolenaar     luaL_checkany(L, 1);
21322ab2e860SBram Moolenaar     if (lua_type(L, 1) == LUA_TUSERDATA) // check vim udata?
21331dced572SBram Moolenaar     {
21341dced572SBram Moolenaar 	lua_settop(L, 1);
21351dced572SBram Moolenaar 	if (lua_getmetatable(L, 1))
21361dced572SBram Moolenaar 	{
21371dced572SBram Moolenaar 	    luaV_getfield(L, LUAVIM_LIST);
21381dced572SBram Moolenaar 	    if (lua_rawequal(L, -1, 2))
21391dced572SBram Moolenaar 	    {
21401dced572SBram Moolenaar 		lua_pushstring(L, "list");
21410ba04296SBram Moolenaar 		return 1;
21420ba04296SBram Moolenaar 	    }
21431dced572SBram Moolenaar 	    luaV_getfield(L, LUAVIM_DICT);
21441dced572SBram Moolenaar 	    if (lua_rawequal(L, -1, 2))
214555d5c034SBram Moolenaar 	    {
21461dced572SBram Moolenaar 		lua_pushstring(L, "dict");
21470ba04296SBram Moolenaar 		return 1;
21480ba04296SBram Moolenaar 	    }
2149b7828690SBram Moolenaar 	    luaV_getfield(L, LUAVIM_BLOB);
2150b7828690SBram Moolenaar 	    if (lua_rawequal(L, -1, 2))
2151b7828690SBram Moolenaar 	    {
2152b7828690SBram Moolenaar 		lua_pushstring(L, "blob");
2153b7828690SBram Moolenaar 		return 1;
2154b7828690SBram Moolenaar 	    }
2155ca06da92SBram Moolenaar 	    luaV_getfield(L, LUAVIM_FUNCREF);
2156ca06da92SBram Moolenaar 	    if (lua_rawequal(L, -1, 2))
2157ca06da92SBram Moolenaar 	    {
2158ca06da92SBram Moolenaar 		lua_pushstring(L, "funcref");
2159ca06da92SBram Moolenaar 		return 1;
2160ca06da92SBram Moolenaar 	    }
21611dced572SBram Moolenaar 	    luaV_getfield(L, LUAVIM_BUFFER);
21621dced572SBram Moolenaar 	    if (lua_rawequal(L, -1, 2))
216355d5c034SBram Moolenaar 	    {
21641dced572SBram Moolenaar 		lua_pushstring(L, "buffer");
21651dced572SBram Moolenaar 		return 1;
21660ba04296SBram Moolenaar 	    }
21671dced572SBram Moolenaar 	    luaV_getfield(L, LUAVIM_WINDOW);
21681dced572SBram Moolenaar 	    if (lua_rawequal(L, -1, 2))
21691dced572SBram Moolenaar 	    {
21701dced572SBram Moolenaar 		lua_pushstring(L, "window");
21711dced572SBram Moolenaar 		return 1;
21721dced572SBram Moolenaar 	    }
21731dced572SBram Moolenaar 	}
21741dced572SBram Moolenaar     }
21752ab2e860SBram Moolenaar     lua_pushstring(L, luaL_typename(L, 1)); // fallback
21761dced572SBram Moolenaar     return 1;
21770ba04296SBram Moolenaar }
21780ba04296SBram Moolenaar 
2179eb04f089SBram Moolenaar     static int
luaV_call(lua_State * L)2180eb04f089SBram Moolenaar luaV_call(lua_State *L)
2181eb04f089SBram Moolenaar {
2182eb04f089SBram Moolenaar     int		argc = lua_gettop(L) - 1;
2183eb04f089SBram Moolenaar     size_t	funcname_len;
2184eb04f089SBram Moolenaar     char_u	*funcname;
2185eb04f089SBram Moolenaar     char	*error = NULL;
2186eb04f089SBram Moolenaar     typval_T	rettv;
2187eb04f089SBram Moolenaar     typval_T	argv[MAX_FUNC_ARGS + 1];
2188eb04f089SBram Moolenaar     int		i = 0;
2189eb04f089SBram Moolenaar 
2190eb04f089SBram Moolenaar     if (argc > MAX_FUNC_ARGS)
2191eb04f089SBram Moolenaar 	return luaL_error(L, "Function called with too many arguments");
2192eb04f089SBram Moolenaar 
2193eb04f089SBram Moolenaar     funcname = (char_u *)luaL_checklstring(L, 1, &funcname_len);
2194eb04f089SBram Moolenaar 
2195eb04f089SBram Moolenaar     for (; i < argc; i++)
2196eb04f089SBram Moolenaar     {
2197eb04f089SBram Moolenaar 	if (luaV_totypval(L, i + 2, &argv[i]) == FAIL)
2198eb04f089SBram Moolenaar 	{
2199eb04f089SBram Moolenaar 	    error = "lua: cannot convert value";
2200eb04f089SBram Moolenaar 	    goto free_vim_args;
2201eb04f089SBram Moolenaar 	}
2202eb04f089SBram Moolenaar     }
2203eb04f089SBram Moolenaar 
2204eb04f089SBram Moolenaar     argv[argc].v_type = VAR_UNKNOWN;
2205eb04f089SBram Moolenaar 
2206eb04f089SBram Moolenaar     if (call_vim_function(funcname, argc, argv, &rettv) == FAIL)
2207eb04f089SBram Moolenaar     {
2208eb04f089SBram Moolenaar 	error = "lua: call_vim_function failed";
2209eb04f089SBram Moolenaar 	goto free_vim_args;
2210eb04f089SBram Moolenaar     }
2211eb04f089SBram Moolenaar 
2212eb04f089SBram Moolenaar     luaV_pushtypval(L, &rettv);
2213eb04f089SBram Moolenaar     clear_tv(&rettv);
2214eb04f089SBram Moolenaar 
2215eb04f089SBram Moolenaar free_vim_args:
2216eb04f089SBram Moolenaar     while (i > 0)
2217eb04f089SBram Moolenaar 	clear_tv(&argv[--i]);
2218eb04f089SBram Moolenaar 
2219eb04f089SBram Moolenaar     if (error == NULL)
2220eb04f089SBram Moolenaar 	return 1;
2221eb04f089SBram Moolenaar     else
2222eb04f089SBram Moolenaar 	return luaL_error(L, error);
2223eb04f089SBram Moolenaar }
2224eb04f089SBram Moolenaar 
222511328bc7SYegappan Lakshmanan /*
222611328bc7SYegappan Lakshmanan  * Return the Vim version as a Lua table
222711328bc7SYegappan Lakshmanan  */
222811328bc7SYegappan Lakshmanan     static int
luaV_version(lua_State * L)222911328bc7SYegappan Lakshmanan luaV_version(lua_State *L)
223011328bc7SYegappan Lakshmanan {
223111328bc7SYegappan Lakshmanan     lua_newtable(L);
223211328bc7SYegappan Lakshmanan     lua_pushstring(L, "major");
223311328bc7SYegappan Lakshmanan     lua_pushinteger(L, VIM_VERSION_MAJOR);
223411328bc7SYegappan Lakshmanan     lua_settable(L, -3);
223511328bc7SYegappan Lakshmanan     lua_pushstring(L, "minor");
223611328bc7SYegappan Lakshmanan     lua_pushinteger(L, VIM_VERSION_MINOR);
223711328bc7SYegappan Lakshmanan     lua_settable(L, -3);
223811328bc7SYegappan Lakshmanan     lua_pushstring(L, "patch");
223911328bc7SYegappan Lakshmanan     lua_pushinteger(L, highest_patch());
224011328bc7SYegappan Lakshmanan     lua_settable(L, -3);
224111328bc7SYegappan Lakshmanan     return 1;
224211328bc7SYegappan Lakshmanan }
224311328bc7SYegappan Lakshmanan 
22440ba04296SBram Moolenaar static const luaL_Reg luaV_module[] = {
22450ba04296SBram Moolenaar     {"command", luaV_command},
22460ba04296SBram Moolenaar     {"eval", luaV_eval},
22470ba04296SBram Moolenaar     {"beep", luaV_beep},
22480ba04296SBram Moolenaar     {"line", luaV_line},
22491dced572SBram Moolenaar     {"list", luaV_list},
22501dced572SBram Moolenaar     {"dict", luaV_dict},
2251b7828690SBram Moolenaar     {"blob", luaV_blob},
2252ca06da92SBram Moolenaar     {"funcref", luaV_funcref},
22530ba04296SBram Moolenaar     {"buffer", luaV_buffer},
22540ba04296SBram Moolenaar     {"window", luaV_window},
22550ba04296SBram Moolenaar     {"open", luaV_open},
22561dced572SBram Moolenaar     {"type", luaV_type},
2257eb04f089SBram Moolenaar     {"call", luaV_call},
22589dc4bef8SYegappan Lakshmanan     {"_getvar", luaV_getvar},
22599dc4bef8SYegappan Lakshmanan     {"_setvar", luaV_setvar},
226011328bc7SYegappan Lakshmanan     {"version", luaV_version},
2261125ed274SBram Moolenaar     {"lua_version", NULL},
22620ba04296SBram Moolenaar     {NULL, NULL}
22630ba04296SBram Moolenaar };
22640ba04296SBram Moolenaar 
22652ab2e860SBram Moolenaar /*
22662ab2e860SBram Moolenaar  * for freeing list, dict, buffer and window objects; lightuserdata as arg
22672ab2e860SBram Moolenaar  */
22681dced572SBram Moolenaar     static int
luaV_free(lua_State * L)22691dced572SBram Moolenaar luaV_free(lua_State *L)
22701dced572SBram Moolenaar {
22711dced572SBram Moolenaar     lua_pushnil(L);
22721dced572SBram Moolenaar     luaV_setudata(L, lua_touserdata(L, 1));
22731dced572SBram Moolenaar     return 0;
22741dced572SBram Moolenaar }
22751dced572SBram Moolenaar 
22761dced572SBram Moolenaar     static int
luaV_luaeval(lua_State * L)22771dced572SBram Moolenaar luaV_luaeval(lua_State *L)
22781dced572SBram Moolenaar {
22791dced572SBram Moolenaar     luaL_Buffer b;
22801dced572SBram Moolenaar     size_t l;
22811dced572SBram Moolenaar     const char *str = lua_tolstring(L, 1, &l);
22821dced572SBram Moolenaar     typval_T *arg = (typval_T *) lua_touserdata(L, 2);
22831dced572SBram Moolenaar     typval_T *rettv = (typval_T *) lua_touserdata(L, 3);
22841dced572SBram Moolenaar     luaL_buffinit(L, &b);
22851dced572SBram Moolenaar     luaL_addlstring(&b, LUAVIM_EVALHEADER, sizeof(LUAVIM_EVALHEADER) - 1);
22861dced572SBram Moolenaar     luaL_addlstring(&b, str, l);
22871dced572SBram Moolenaar     luaL_pushresult(&b);
22881dced572SBram Moolenaar     str = lua_tolstring(L, -1, &l);
22892ab2e860SBram Moolenaar     if (luaL_loadbuffer(L, str, l, LUAVIM_EVALNAME)) // compile error?
22901dced572SBram Moolenaar     {
22911dced572SBram Moolenaar 	luaV_emsg(L);
22921dced572SBram Moolenaar 	return 0;
22931dced572SBram Moolenaar     }
22941dced572SBram Moolenaar     luaV_pushtypval(L, arg);
22952ab2e860SBram Moolenaar     if (lua_pcall(L, 1, 1, 0)) // running error?
22961dced572SBram Moolenaar     {
22971dced572SBram Moolenaar 	luaV_emsg(L);
22981dced572SBram Moolenaar 	return 0;
22991dced572SBram Moolenaar     }
2300ca06da92SBram Moolenaar     if (luaV_totypval(L, -1, rettv) == FAIL)
2301f9e3e09fSBram Moolenaar 	emsg("luaeval: cannot convert value");
2302f554a328SBram Moolenaar     return 0;
23031dced572SBram Moolenaar }
23041dced572SBram Moolenaar 
23051dced572SBram Moolenaar     static int
luaV_setref(lua_State * L)23061dced572SBram Moolenaar luaV_setref(lua_State *L)
23071dced572SBram Moolenaar {
23081dced572SBram Moolenaar     int copyID = lua_tointeger(L, 1);
23092459a5ecSBram Moolenaar     int abort = FALSE;
23102459a5ecSBram Moolenaar 
23111dced572SBram Moolenaar     luaV_getfield(L, LUAVIM_LIST);
23121dced572SBram Moolenaar     luaV_getfield(L, LUAVIM_DICT);
23134eefe47eSBram Moolenaar     luaV_getfield(L, LUAVIM_FUNCREF);
23141dced572SBram Moolenaar     lua_pushnil(L);
23154eefe47eSBram Moolenaar     // traverse cache table
2316b84634deSBram Moolenaar     while (!abort && lua_next(L, lua_upvalueindex(1)) != 0)
23171dced572SBram Moolenaar     {
23181dced572SBram Moolenaar 	lua_getmetatable(L, -1);
23194eefe47eSBram Moolenaar 	if (lua_rawequal(L, -1, 2)) // list?
23201dced572SBram Moolenaar 	{
23214eefe47eSBram Moolenaar 	    list_T *l = (list_T *)lua_touserdata(L, 5); // key
23224eefe47eSBram Moolenaar 
23237be3ab25SBram Moolenaar 	    abort = set_ref_in_list(l, copyID);
23244eefe47eSBram Moolenaar 	}
23254eefe47eSBram Moolenaar 	else if (lua_rawequal(L, -1, 3)) // dict?
23264eefe47eSBram Moolenaar 	{
23274eefe47eSBram Moolenaar 	    dict_T *d = (dict_T *)lua_touserdata(L, 5); // key
23284eefe47eSBram Moolenaar 
23297be3ab25SBram Moolenaar 	    abort = set_ref_in_dict(d, copyID);
23304eefe47eSBram Moolenaar 	}
23314eefe47eSBram Moolenaar 	else if (lua_rawequal(L, -1, 4)) // funcref?
23324eefe47eSBram Moolenaar 	{
23334eefe47eSBram Moolenaar 	    luaV_Funcref *f = (luaV_Funcref *)lua_touserdata(L, 5); // key
23344eefe47eSBram Moolenaar 
23357be3ab25SBram Moolenaar 	    abort = set_ref_in_dict(f->self, copyID);
23364eefe47eSBram Moolenaar 	}
23374eefe47eSBram Moolenaar 	lua_pop(L, 2); // metatable and value
23381dced572SBram Moolenaar     }
23392459a5ecSBram Moolenaar     lua_pushinteger(L, abort);
2340f554a328SBram Moolenaar     return 1;
23411dced572SBram Moolenaar }
23421dced572SBram Moolenaar 
2343125ed274SBram Moolenaar     static int
luaV_pushversion(lua_State * L)2344125ed274SBram Moolenaar luaV_pushversion(lua_State *L)
2345125ed274SBram Moolenaar {
2346125ed274SBram Moolenaar     int major = 0;
2347125ed274SBram Moolenaar     int minor = 0;
2348125ed274SBram Moolenaar     int patch = 0;
2349125ed274SBram Moolenaar     char s[16];
2350125ed274SBram Moolenaar 
2351125ed274SBram Moolenaar     sscanf(LUAVIM_VERSION, "Lua %d.%d.%d", &major, &minor, &patch);
2352125ed274SBram Moolenaar     vim_snprintf(s, sizeof(s), "%d.%d.%d", major, minor, patch);
2353125ed274SBram Moolenaar     lua_pushstring(L, s);
2354125ed274SBram Moolenaar     return 0;
2355125ed274SBram Moolenaar }
2356125ed274SBram Moolenaar 
2357eb04f089SBram Moolenaar #define LUA_VIM_FN_CODE \
2358788fbb47SBram Moolenaar     "vim.fn = setmetatable({}, {\n"\
2359788fbb47SBram Moolenaar     "  __index = function (t, key)\n"\
2360788fbb47SBram Moolenaar     "    local function _fn(...)\n"\
2361788fbb47SBram Moolenaar     "      return vim.call(key, ...)\n"\
2362788fbb47SBram Moolenaar     "    end\n"\
2363788fbb47SBram Moolenaar     "    t[key] = _fn\n"\
2364788fbb47SBram Moolenaar     "    return _fn\n"\
2365788fbb47SBram Moolenaar     "  end\n"\
2366eb04f089SBram Moolenaar     " })"
2367eb04f089SBram Moolenaar 
2368788fbb47SBram Moolenaar #define LUA_VIM_UPDATE_PACKAGE_PATHS \
2369788fbb47SBram Moolenaar     "local last_vim_paths = {}\n"\
2370788fbb47SBram Moolenaar     "vim._update_package_paths = function ()\n"\
2371788fbb47SBram Moolenaar     "  local cur_vim_paths = {}\n"\
2372788fbb47SBram Moolenaar     "  local function split(s, delimiter)\n"\
2373788fbb47SBram Moolenaar     "    result = {}\n"\
2374788fbb47SBram Moolenaar     "    for match in (s..delimiter):gmatch(\"(.-)\"..delimiter) do\n"\
2375788fbb47SBram Moolenaar     "      table.insert(result, match)\n"\
2376788fbb47SBram Moolenaar     "    end\n"\
2377788fbb47SBram Moolenaar     "    return result\n"\
2378788fbb47SBram Moolenaar     "  end\n"\
2379788fbb47SBram Moolenaar     "  local rtps = split(vim.eval('&runtimepath'), ',')\n"\
2380788fbb47SBram Moolenaar     "  local sep = package.config:sub(1, 1)\n"\
2381788fbb47SBram Moolenaar     "  for _, key in ipairs({'path', 'cpath'}) do\n"\
2382788fbb47SBram Moolenaar     "    local orig_str = package[key] .. ';'\n"\
2383788fbb47SBram Moolenaar     "    local pathtrails_ordered = {}\n"\
2384788fbb47SBram Moolenaar     "    -- Note: ignores trailing item without trailing `;`. Not using something\n"\
2385788fbb47SBram Moolenaar     "    -- simpler in order to preserve empty items (stand for default path).\n"\
2386788fbb47SBram Moolenaar     "    local orig = {}\n"\
2387788fbb47SBram Moolenaar     "    for s in orig_str:gmatch('[^;]*;') do\n"\
2388788fbb47SBram Moolenaar     "      s = s:sub(1, -2)  -- Strip trailing semicolon\n"\
2389788fbb47SBram Moolenaar     "      orig[#orig + 1] = s\n"\
2390788fbb47SBram Moolenaar     "    end\n"\
2391788fbb47SBram Moolenaar     "    if key == 'path' then\n"\
2392788fbb47SBram Moolenaar     "      -- /?.lua and /?/init.lua\n"\
2393788fbb47SBram Moolenaar     "      pathtrails_ordered = {sep .. '?.lua', sep .. '?' .. sep .. 'init.lua'}\n"\
2394788fbb47SBram Moolenaar     "    else\n"\
2395788fbb47SBram Moolenaar     "      local pathtrails = {}\n"\
2396788fbb47SBram Moolenaar     "      for _, s in ipairs(orig) do\n"\
2397788fbb47SBram Moolenaar     "        -- Find out path patterns. pathtrail should contain something like\n"\
2398788fbb47SBram Moolenaar     "        -- /?.so, \?.dll. This allows not to bother determining what correct\n"\
2399788fbb47SBram Moolenaar     "        -- suffixes are.\n"\
2400788fbb47SBram Moolenaar     "        local pathtrail = s:match('[/\\\\][^/\\\\]*%?.*$')\n"\
2401788fbb47SBram Moolenaar     "        if pathtrail and not pathtrails[pathtrail] then\n"\
2402788fbb47SBram Moolenaar     "          pathtrails[pathtrail] = true\n"\
2403788fbb47SBram Moolenaar     "          pathtrails_ordered[#pathtrails_ordered + 1] = pathtrail\n"\
2404788fbb47SBram Moolenaar     "        end\n"\
2405788fbb47SBram Moolenaar     "      end\n"\
2406788fbb47SBram Moolenaar     "    end\n"\
2407788fbb47SBram Moolenaar     "    local new = {}\n"\
2408788fbb47SBram Moolenaar     "    for _, rtp in ipairs(rtps) do\n"\
2409788fbb47SBram Moolenaar     "      if not rtp:match(';') then\n"\
2410788fbb47SBram Moolenaar     "        for _, pathtrail in pairs(pathtrails_ordered) do\n"\
2411788fbb47SBram Moolenaar     "          local new_path = rtp .. sep .. 'lua' .. pathtrail\n"\
2412788fbb47SBram Moolenaar     "          -- Always keep paths from &runtimepath at the start:\n"\
2413788fbb47SBram Moolenaar     "          -- append them here disregarding orig possibly containing one of them.\n"\
2414788fbb47SBram Moolenaar     "          new[#new + 1] = new_path\n"\
2415788fbb47SBram Moolenaar     "          cur_vim_paths[new_path] = true\n"\
2416788fbb47SBram Moolenaar     "        end\n"\
2417788fbb47SBram Moolenaar     "      end\n"\
2418788fbb47SBram Moolenaar     "    end\n"\
2419788fbb47SBram Moolenaar     "    for _, orig_path in ipairs(orig) do\n"\
2420788fbb47SBram Moolenaar     "      -- Handle removing obsolete paths originating from &runtimepath: such\n"\
2421788fbb47SBram Moolenaar     "      -- paths either belong to cur_nvim_paths and were already added above or\n"\
2422788fbb47SBram Moolenaar     "      -- to last_nvim_paths and should not be added at all if corresponding\n"\
2423788fbb47SBram Moolenaar     "      -- entry was removed from &runtimepath list.\n"\
2424788fbb47SBram Moolenaar     "      if not (cur_vim_paths[orig_path] or last_vim_paths[orig_path]) then\n"\
2425788fbb47SBram Moolenaar     "        new[#new + 1] = orig_path\n"\
2426788fbb47SBram Moolenaar     "      end\n"\
2427788fbb47SBram Moolenaar     "    end\n"\
2428788fbb47SBram Moolenaar     "    package[key] = table.concat(new, ';')\n"\
2429788fbb47SBram Moolenaar     "  end\n"\
2430788fbb47SBram Moolenaar     "  last_vim_paths = cur_vim_paths\n"\
2431788fbb47SBram Moolenaar     "end"
2432788fbb47SBram Moolenaar 
24339dc4bef8SYegappan Lakshmanan #define LUA_VIM_SETUP_VARIABLE_DICTS \
24349dc4bef8SYegappan Lakshmanan     "do\n"\
24359dc4bef8SYegappan Lakshmanan     "  local function make_dict_accessor(scope)\n"\
24369dc4bef8SYegappan Lakshmanan     "    local mt = {}\n"\
24379dc4bef8SYegappan Lakshmanan     "    function mt:__newindex(k, v)\n"\
24389dc4bef8SYegappan Lakshmanan     "      return vim._setvar(scope, 0, k, v)\n"\
24399dc4bef8SYegappan Lakshmanan     "    end\n"\
24409dc4bef8SYegappan Lakshmanan     "    function mt:__index(k)\n"\
24419dc4bef8SYegappan Lakshmanan     "      return vim._getvar(scope, 0, k)\n"\
24429dc4bef8SYegappan Lakshmanan     "    end\n"\
24439dc4bef8SYegappan Lakshmanan     "    return setmetatable({}, mt)\n"\
24449dc4bef8SYegappan Lakshmanan     "  end\n"\
24459dc4bef8SYegappan Lakshmanan     "  vim.g = make_dict_accessor('g')\n"\
24469dc4bef8SYegappan Lakshmanan     "  vim.v = make_dict_accessor('v')\n"\
24479dc4bef8SYegappan Lakshmanan     "  vim.b = make_dict_accessor('b')\n"\
24489dc4bef8SYegappan Lakshmanan     "  vim.w = make_dict_accessor('w')\n"\
24499dc4bef8SYegappan Lakshmanan     "  vim.t = make_dict_accessor('t')\n"\
24509dc4bef8SYegappan Lakshmanan     "end"
24519dc4bef8SYegappan Lakshmanan 
245255d5c034SBram Moolenaar     static int
luaopen_vim(lua_State * L)245355d5c034SBram Moolenaar luaopen_vim(lua_State *L)
245455d5c034SBram Moolenaar {
24552ab2e860SBram Moolenaar     // set cache table
24560ba04296SBram Moolenaar     lua_newtable(L);
24570ba04296SBram Moolenaar     lua_newtable(L);
24581dced572SBram Moolenaar     lua_pushstring(L, "v");
24590ba04296SBram Moolenaar     lua_setfield(L, -2, "__mode");
24602ab2e860SBram Moolenaar     lua_setmetatable(L, -2); // cache is weak-valued
24612ab2e860SBram Moolenaar     // print
24620ba04296SBram Moolenaar     lua_pushcfunction(L, luaV_print);
24630ba04296SBram Moolenaar     lua_setglobal(L, "print");
24642ab2e860SBram Moolenaar     // debug.debug
246538e2b063SBram Moolenaar     lua_getglobal(L, "debug");
246638e2b063SBram Moolenaar     lua_pushcfunction(L, luaV_debug);
246738e2b063SBram Moolenaar     lua_setfield(L, -2, "debug");
246838e2b063SBram Moolenaar     lua_pop(L, 1);
24692ab2e860SBram Moolenaar     // free
24700ba04296SBram Moolenaar     lua_pushlightuserdata(L, (void *) LUAVIM_FREE);
24712ab2e860SBram Moolenaar     lua_pushvalue(L, 1); // cache table
24721dced572SBram Moolenaar     lua_pushcclosure(L, luaV_free, 1);
24731dced572SBram Moolenaar     lua_rawset(L, LUA_REGISTRYINDEX);
24742ab2e860SBram Moolenaar     // luaeval
24751dced572SBram Moolenaar     lua_pushlightuserdata(L, (void *) LUAVIM_LUAEVAL);
24762ab2e860SBram Moolenaar     lua_pushvalue(L, 1); // cache table
24771dced572SBram Moolenaar     lua_pushcclosure(L, luaV_luaeval, 1);
24781dced572SBram Moolenaar     lua_rawset(L, LUA_REGISTRYINDEX);
24792ab2e860SBram Moolenaar     // setref
24801dced572SBram Moolenaar     lua_pushlightuserdata(L, (void *) LUAVIM_SETREF);
24812ab2e860SBram Moolenaar     lua_pushvalue(L, 1); // cache table
24821dced572SBram Moolenaar     lua_pushcclosure(L, luaV_setref, 1);
24830ba04296SBram Moolenaar     lua_rawset(L, LUA_REGISTRYINDEX);
24842ab2e860SBram Moolenaar     // register
24851dced572SBram Moolenaar     luaV_newmetatable(L, LUAVIM_LIST);
24861dced572SBram Moolenaar     lua_pushvalue(L, 1);
24871dced572SBram Moolenaar     luaV_openlib(L, luaV_List_mt, 1);
24881dced572SBram Moolenaar     luaV_newmetatable(L, LUAVIM_DICT);
24891dced572SBram Moolenaar     lua_pushvalue(L, 1);
24901dced572SBram Moolenaar     luaV_openlib(L, luaV_Dict_mt, 1);
2491b7828690SBram Moolenaar     luaV_newmetatable(L, LUAVIM_BLOB);
2492b7828690SBram Moolenaar     lua_pushvalue(L, 1);
2493b7828690SBram Moolenaar     luaV_openlib(L, luaV_Blob_mt, 1);
2494ca06da92SBram Moolenaar     luaV_newmetatable(L, LUAVIM_FUNCREF);
2495ca06da92SBram Moolenaar     lua_pushvalue(L, 1);
2496ca06da92SBram Moolenaar     luaV_openlib(L, luaV_Funcref_mt, 1);
24970ba04296SBram Moolenaar     luaV_newmetatable(L, LUAVIM_BUFFER);
24982ab2e860SBram Moolenaar     lua_pushvalue(L, 1); // cache table
24991dced572SBram Moolenaar     luaV_openlib(L, luaV_Buffer_mt, 1);
25000ba04296SBram Moolenaar     luaV_newmetatable(L, LUAVIM_WINDOW);
25012ab2e860SBram Moolenaar     lua_pushvalue(L, 1); // cache table
25021dced572SBram Moolenaar     luaV_openlib(L, luaV_Window_mt, 1);
25032ab2e860SBram Moolenaar     lua_newtable(L); // vim table
25042ab2e860SBram Moolenaar     lua_pushvalue(L, 1); // cache table
25051dced572SBram Moolenaar     luaV_openlib(L, luaV_module, 1);
2506125ed274SBram Moolenaar     luaV_pushversion(L);
2507125ed274SBram Moolenaar     lua_setfield(L, -2, "lua_version");
25081dced572SBram Moolenaar     lua_setglobal(L, LUAVIM_NAME);
2509eb04f089SBram Moolenaar     // custom code
25109309eb2fSBram Moolenaar     (void)luaL_dostring(L, LUA_VIM_FN_CODE);
2511788fbb47SBram Moolenaar     (void)luaL_dostring(L, LUA_VIM_UPDATE_PACKAGE_PATHS);
25129dc4bef8SYegappan Lakshmanan     (void)luaL_dostring(L, LUA_VIM_SETUP_VARIABLE_DICTS);
2513788fbb47SBram Moolenaar 
2514788fbb47SBram Moolenaar     lua_getglobal(L, "vim");
2515788fbb47SBram Moolenaar     lua_getfield(L, -1, "_update_package_paths");
2516788fbb47SBram Moolenaar 
2517788fbb47SBram Moolenaar     if (lua_pcall(L, 0, 0, 0))
2518788fbb47SBram Moolenaar 	luaV_emsg(L);
2519788fbb47SBram Moolenaar 
25200ba04296SBram Moolenaar     return 0;
25210ba04296SBram Moolenaar }
25220ba04296SBram Moolenaar 
252355d5c034SBram Moolenaar     static lua_State *
luaV_newstate(void)252455d5c034SBram Moolenaar luaV_newstate(void)
252555d5c034SBram Moolenaar {
25260ba04296SBram Moolenaar     lua_State *L = luaL_newstate();
25272ab2e860SBram Moolenaar     luaL_openlibs(L); // core libs
25282ab2e860SBram Moolenaar     lua_pushcfunction(L, luaopen_vim); // vim
25290ba04296SBram Moolenaar     lua_call(L, 0, 0);
25300ba04296SBram Moolenaar     return L;
25310ba04296SBram Moolenaar }
25320ba04296SBram Moolenaar 
253355d5c034SBram Moolenaar     static void
luaV_setrange(lua_State * L,int line1,int line2)253455d5c034SBram Moolenaar luaV_setrange(lua_State *L, int line1, int line2)
253555d5c034SBram Moolenaar {
25360ba04296SBram Moolenaar     lua_getglobal(L, LUAVIM_NAME);
25370ba04296SBram Moolenaar     lua_pushinteger(L, line1);
25380ba04296SBram Moolenaar     lua_setfield(L, -2, "firstline");
25390ba04296SBram Moolenaar     lua_pushinteger(L, line2);
25400ba04296SBram Moolenaar     lua_setfield(L, -2, "lastline");
25412ab2e860SBram Moolenaar     lua_pop(L, 1); // vim table
25420ba04296SBram Moolenaar }
25430ba04296SBram Moolenaar 
25440ba04296SBram Moolenaar 
25452ab2e860SBram Moolenaar // =======   Interface   =======
25460ba04296SBram Moolenaar 
25470ba04296SBram Moolenaar static lua_State *L = NULL;
25480ba04296SBram Moolenaar 
254955d5c034SBram Moolenaar     static int
lua_isopen(void)25501dced572SBram Moolenaar lua_isopen(void)
25512bd6a1b5SBram Moolenaar {
25522bd6a1b5SBram Moolenaar     return L != NULL;
25532bd6a1b5SBram Moolenaar }
25542bd6a1b5SBram Moolenaar 
25552bd6a1b5SBram Moolenaar     static int
lua_init(void)255655d5c034SBram Moolenaar lua_init(void)
255755d5c034SBram Moolenaar {
25581dced572SBram Moolenaar     if (!lua_isopen())
255955d5c034SBram Moolenaar     {
25600ba04296SBram Moolenaar #ifdef DYNAMIC_LUA
256155d5c034SBram Moolenaar 	if (!lua_enabled(TRUE))
256255d5c034SBram Moolenaar 	{
2563f9e3e09fSBram Moolenaar 	    emsg(_("Lua library cannot be loaded."));
25640ba04296SBram Moolenaar 	    return FAIL;
25650ba04296SBram Moolenaar 	}
25660ba04296SBram Moolenaar #endif
25670ba04296SBram Moolenaar 	L = luaV_newstate();
25680ba04296SBram Moolenaar     }
25690ba04296SBram Moolenaar     return OK;
25700ba04296SBram Moolenaar }
25710ba04296SBram Moolenaar 
257255d5c034SBram Moolenaar     void
lua_end(void)257355d5c034SBram Moolenaar lua_end(void)
257455d5c034SBram Moolenaar {
25751dced572SBram Moolenaar     if (lua_isopen())
257655d5c034SBram Moolenaar     {
25770ba04296SBram Moolenaar 	lua_close(L);
25780ba04296SBram Moolenaar 	L = NULL;
25790ba04296SBram Moolenaar     }
25800ba04296SBram Moolenaar }
25810ba04296SBram Moolenaar 
25822ab2e860SBram Moolenaar /*
25832ab2e860SBram Moolenaar  * ex commands
25842ab2e860SBram Moolenaar  */
258555d5c034SBram Moolenaar     void
ex_lua(exarg_T * eap)258655d5c034SBram Moolenaar ex_lua(exarg_T *eap)
258755d5c034SBram Moolenaar {
2588c8970b94SBram Moolenaar     char *script = (char *)script_get(eap, eap->arg);
2589c8970b94SBram Moolenaar 
2590c8970b94SBram Moolenaar     if (!eap->skip && lua_init() == OK)
259155d5c034SBram Moolenaar     {
2592c8970b94SBram Moolenaar 	char *s = script != NULL ? script : (char *)eap->arg;
2593c8970b94SBram Moolenaar 
25940ba04296SBram Moolenaar 	luaV_setrange(L, eap->line1, eap->line2);
25950ba04296SBram Moolenaar 	if (luaL_loadbuffer(L, s, strlen(s), LUAVIM_CHUNKNAME)
25960ba04296SBram Moolenaar 		|| lua_pcall(L, 0, 0, 0))
25970ba04296SBram Moolenaar 	    luaV_emsg(L);
25980ba04296SBram Moolenaar     }
2599c8970b94SBram Moolenaar     if (script != NULL)
2600c8970b94SBram Moolenaar 	vim_free(script);
26010ba04296SBram Moolenaar }
26020ba04296SBram Moolenaar 
260355d5c034SBram Moolenaar     void
ex_luado(exarg_T * eap)260455d5c034SBram Moolenaar ex_luado(exarg_T *eap)
260555d5c034SBram Moolenaar {
26060ba04296SBram Moolenaar     linenr_T l;
26070ba04296SBram Moolenaar     const char *s = (const char *) eap->arg;
26080ba04296SBram Moolenaar     luaL_Buffer b;
26090ba04296SBram Moolenaar     size_t len;
2610d58f03b1SBram Moolenaar     buf_T *was_curbuf = curbuf;
2611d58f03b1SBram Moolenaar 
26120ba04296SBram Moolenaar     if (lua_init() == FAIL) return;
261355d5c034SBram Moolenaar     if (u_save(eap->line1 - 1, eap->line2 + 1) == FAIL)
261455d5c034SBram Moolenaar     {
2615f9e3e09fSBram Moolenaar 	emsg(_("cannot save undo information"));
26160ba04296SBram Moolenaar 	return;
26170ba04296SBram Moolenaar     }
26180ba04296SBram Moolenaar     luaV_setrange(L, eap->line1, eap->line2);
26190ba04296SBram Moolenaar     luaL_buffinit(L, &b);
26202ab2e860SBram Moolenaar     luaL_addlstring(&b, "return function(line, linenr) ", 30); // header
26210ba04296SBram Moolenaar     luaL_addlstring(&b, s, strlen(s));
26222ab2e860SBram Moolenaar     luaL_addlstring(&b, " end", 4); // footer
26230ba04296SBram Moolenaar     luaL_pushresult(&b);
26240ba04296SBram Moolenaar     s = lua_tolstring(L, -1, &len);
262555d5c034SBram Moolenaar     if (luaL_loadbuffer(L, s, len, LUAVIM_CHUNKNAME))
262655d5c034SBram Moolenaar     {
26270ba04296SBram Moolenaar 	luaV_emsg(L);
26282ab2e860SBram Moolenaar 	lua_pop(L, 1); // function body
26290ba04296SBram Moolenaar 	return;
26300ba04296SBram Moolenaar     }
26310ba04296SBram Moolenaar     lua_call(L, 0, 1);
26322ab2e860SBram Moolenaar     lua_replace(L, -2); // function -> body
263355d5c034SBram Moolenaar     for (l = eap->line1; l <= eap->line2; l++)
263455d5c034SBram Moolenaar     {
2635e49b8e8dSBram Moolenaar 	// Check the line number, the command may have deleted lines.
2636d58f03b1SBram Moolenaar 	if (l > curbuf->b_ml.ml_line_count)
2637d58f03b1SBram Moolenaar 	    break;
2638d58f03b1SBram Moolenaar 
26392ab2e860SBram Moolenaar 	lua_pushvalue(L, -1); // function
26402ab2e860SBram Moolenaar 	luaV_pushline(L, curbuf, l); // current line as arg
26412ab2e860SBram Moolenaar 	lua_pushinteger(L, l); // current line number as arg
2642bd2f3c3eSBram Moolenaar 	if (lua_pcall(L, 2, 1, 0))
264355d5c034SBram Moolenaar 	{
26440ba04296SBram Moolenaar 	    luaV_emsg(L);
26450ba04296SBram Moolenaar 	    break;
26460ba04296SBram Moolenaar 	}
26472ab2e860SBram Moolenaar 	// Catch the command switching to another buffer.
2648d58f03b1SBram Moolenaar 	if (curbuf != was_curbuf)
2649d58f03b1SBram Moolenaar 	    break;
26502ab2e860SBram Moolenaar 	if (lua_isstring(L, -1)) // update line?
265155d5c034SBram Moolenaar 	{
26520ba04296SBram Moolenaar #ifdef HAVE_SANDBOX
26530ba04296SBram Moolenaar 	    luaV_checksandbox(L);
26540ba04296SBram Moolenaar #endif
26550ba04296SBram Moolenaar 	    ml_replace(l, luaV_toline(L, -1), TRUE);
26560ba04296SBram Moolenaar 	    changed_bytes(l, 0);
26572ab2e860SBram Moolenaar 	    lua_pop(L, 1); // result from luaV_toline
26580ba04296SBram Moolenaar 	}
26592ab2e860SBram Moolenaar 	lua_pop(L, 1); // line
26600ba04296SBram Moolenaar     }
26612ab2e860SBram Moolenaar     lua_pop(L, 1); // function
26620ba04296SBram Moolenaar     check_cursor();
26630ba04296SBram Moolenaar     update_screen(NOT_VALID);
26640ba04296SBram Moolenaar }
26650ba04296SBram Moolenaar 
266655d5c034SBram Moolenaar     void
ex_luafile(exarg_T * eap)266755d5c034SBram Moolenaar ex_luafile(exarg_T *eap)
266855d5c034SBram Moolenaar {
266955d5c034SBram Moolenaar     if (lua_init() == FAIL)
267055d5c034SBram Moolenaar 	return;
267155d5c034SBram Moolenaar     if (!eap->skip)
267255d5c034SBram Moolenaar     {
26730ba04296SBram Moolenaar 	luaV_setrange(L, eap->line1, eap->line2);
26740ba04296SBram Moolenaar 	if (luaL_loadfile(L, (char *) eap->arg) || lua_pcall(L, 0, 0, 0))
26750ba04296SBram Moolenaar 	    luaV_emsg(L);
26760ba04296SBram Moolenaar     }
26770ba04296SBram Moolenaar }
26780ba04296SBram Moolenaar 
26791dced572SBram Moolenaar #define luaV_freetype(typ,tname) \
26801dced572SBram Moolenaar 	void \
26811dced572SBram Moolenaar     lua_##tname##_free(typ *o) \
26821dced572SBram Moolenaar     { \
26831dced572SBram Moolenaar 	if (!lua_isopen()) return; \
26841dced572SBram Moolenaar 	luaV_getfield(L, LUAVIM_FREE); \
26851dced572SBram Moolenaar 	lua_pushlightuserdata(L, (void *) o); \
26861dced572SBram Moolenaar 	lua_call(L, 1, 0); \
26870ba04296SBram Moolenaar     }
26880ba04296SBram Moolenaar 
luaV_freetype(buf_T,buffer)26891dced572SBram Moolenaar luaV_freetype(buf_T, buffer)
26901dced572SBram Moolenaar luaV_freetype(win_T, window)
26911dced572SBram Moolenaar 
269255d5c034SBram Moolenaar     void
26931dced572SBram Moolenaar do_luaeval(char_u *str, typval_T *arg, typval_T *rettv)
269455d5c034SBram Moolenaar {
26951dced572SBram Moolenaar     lua_init();
26961dced572SBram Moolenaar     luaV_getfield(L, LUAVIM_LUAEVAL);
26971dced572SBram Moolenaar     lua_pushstring(L, (char *) str);
26981dced572SBram Moolenaar     lua_pushlightuserdata(L, (void *) arg);
26991dced572SBram Moolenaar     lua_pushlightuserdata(L, (void *) rettv);
27001dced572SBram Moolenaar     lua_call(L, 3, 0);
27011dced572SBram Moolenaar }
27021dced572SBram Moolenaar 
27032459a5ecSBram Moolenaar     int
set_ref_in_lua(int copyID)27041dced572SBram Moolenaar set_ref_in_lua(int copyID)
27051dced572SBram Moolenaar {
27062459a5ecSBram Moolenaar     int aborted = 0;
27072459a5ecSBram Moolenaar 
27082459a5ecSBram Moolenaar     if (lua_isopen())
27092459a5ecSBram Moolenaar     {
27101dced572SBram Moolenaar 	luaV_getfield(L, LUAVIM_SETREF);
27112ab2e860SBram Moolenaar 	// call the function with 1 arg, getting 1 result back
27121dced572SBram Moolenaar 	lua_pushinteger(L, copyID);
27132459a5ecSBram Moolenaar 	lua_call(L, 1, 1);
27142ab2e860SBram Moolenaar 	// get the result
27152459a5ecSBram Moolenaar 	aborted = lua_tointeger(L, -1);
27162ab2e860SBram Moolenaar 	// pop result off the stack
27172459a5ecSBram Moolenaar 	lua_pop(L, 1);
27182459a5ecSBram Moolenaar     }
27192459a5ecSBram Moolenaar     return aborted;
27200ba04296SBram Moolenaar }
27210ba04296SBram Moolenaar 
2722788fbb47SBram Moolenaar     void
update_package_paths_in_lua()2723788fbb47SBram Moolenaar update_package_paths_in_lua()
2724788fbb47SBram Moolenaar {
2725788fbb47SBram Moolenaar     if (lua_isopen())
2726788fbb47SBram Moolenaar     {
2727788fbb47SBram Moolenaar 	lua_getglobal(L, "vim");
2728788fbb47SBram Moolenaar 	lua_getfield(L, -1, "_update_package_paths");
2729788fbb47SBram Moolenaar 
2730788fbb47SBram Moolenaar 	if (lua_pcall(L, 0, 0, 0))
2731788fbb47SBram Moolenaar 	    luaV_emsg(L);
2732788fbb47SBram Moolenaar     }
2733788fbb47SBram Moolenaar }
2734788fbb47SBram Moolenaar 
2735801ab069SBram Moolenaar /*
2736801ab069SBram Moolenaar  * Native C function callback
2737801ab069SBram Moolenaar  */
2738801ab069SBram Moolenaar     static int
luaV_call_lua_func(int argcount,typval_T * argvars,typval_T * rettv,void * state)2739801ab069SBram Moolenaar luaV_call_lua_func(
2740801ab069SBram Moolenaar 	int	 argcount,
2741801ab069SBram Moolenaar 	typval_T *argvars,
2742801ab069SBram Moolenaar 	typval_T *rettv,
2743801ab069SBram Moolenaar 	void	 *state)
2744801ab069SBram Moolenaar {
2745801ab069SBram Moolenaar     int i;
2746801ab069SBram Moolenaar     int luaargcount = argcount;
2747801ab069SBram Moolenaar     luaV_CFuncState *funcstate = (luaV_CFuncState*)state;
2748801ab069SBram Moolenaar     lua_rawgeti(funcstate->L, LUA_REGISTRYINDEX, funcstate->lua_funcref);
2749801ab069SBram Moolenaar 
2750801ab069SBram Moolenaar     if (funcstate->lua_tableref != LUA_NOREF)
2751801ab069SBram Moolenaar     {
2752801ab069SBram Moolenaar 	// First arg for metatable __call method is a table
2753801ab069SBram Moolenaar 	luaargcount += 1;
2754801ab069SBram Moolenaar 	lua_rawgeti(funcstate->L, LUA_REGISTRYINDEX, funcstate->lua_tableref);
2755801ab069SBram Moolenaar     }
2756801ab069SBram Moolenaar 
2757801ab069SBram Moolenaar     for (i = 0; i < argcount; ++i)
2758801ab069SBram Moolenaar 	luaV_pushtypval(funcstate->L, &argvars[i]);
2759801ab069SBram Moolenaar 
2760801ab069SBram Moolenaar     if (lua_pcall(funcstate->L, luaargcount, 1, 0))
2761801ab069SBram Moolenaar     {
2762801ab069SBram Moolenaar 	luaV_emsg(funcstate->L);
2763801ab069SBram Moolenaar 	return FCERR_OTHER;
2764801ab069SBram Moolenaar     }
2765801ab069SBram Moolenaar 
2766801ab069SBram Moolenaar     luaV_checktypval(funcstate->L, -1, rettv, "get return value");
2767801ab069SBram Moolenaar     return FCERR_NONE;
2768801ab069SBram Moolenaar }
2769801ab069SBram Moolenaar 
2770801ab069SBram Moolenaar /*
2771801ab069SBram Moolenaar  * Free up any lua references held by the func state.
2772801ab069SBram Moolenaar  */
2773801ab069SBram Moolenaar     static void
luaV_call_lua_func_free(void * state)2774801ab069SBram Moolenaar luaV_call_lua_func_free(void *state)
2775801ab069SBram Moolenaar {
2776801ab069SBram Moolenaar     luaV_CFuncState *funcstate = (luaV_CFuncState*)state;
2777801ab069SBram Moolenaar     luaL_unref(L, LUA_REGISTRYINDEX, funcstate->lua_funcref);
2778801ab069SBram Moolenaar     funcstate->L = NULL;
2779801ab069SBram Moolenaar     if (funcstate->lua_tableref != LUA_NOREF)
2780801ab069SBram Moolenaar 	luaL_unref(L, LUA_REGISTRYINDEX, funcstate->lua_tableref);
2781801ab069SBram Moolenaar     VIM_CLEAR(funcstate);
2782801ab069SBram Moolenaar }
2783801ab069SBram Moolenaar 
27840ba04296SBram Moolenaar #endif
2785