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" 13e2793357SBram Moolenaar 140ba04296SBram Moolenaar #include <lua.h> 150ba04296SBram Moolenaar #include <lualib.h> 160ba04296SBram Moolenaar #include <lauxlib.h> 170ba04296SBram Moolenaar 180ba04296SBram Moolenaar /* Only do the following when the feature is enabled. Needed for "make 190ba04296SBram Moolenaar * depend". */ 200ba04296SBram Moolenaar #if defined(FEAT_LUA) || defined(PROTO) 210ba04296SBram Moolenaar 220ba04296SBram Moolenaar #define LUAVIM_CHUNKNAME "vim chunk" 230ba04296SBram Moolenaar #define LUAVIM_NAME "vim" 241dced572SBram Moolenaar #define LUAVIM_EVALNAME "luaeval" 251dced572SBram Moolenaar #define LUAVIM_EVALHEADER "local _A=select(1,...) return " 260ba04296SBram Moolenaar 270ba04296SBram Moolenaar typedef buf_T *luaV_Buffer; 280ba04296SBram Moolenaar typedef win_T *luaV_Window; 291dced572SBram Moolenaar typedef dict_T *luaV_Dict; 301dced572SBram Moolenaar typedef list_T *luaV_List; 31ca06da92SBram Moolenaar typedef struct { 32*4eefe47eSBram Moolenaar char_u *name; // funcref 33ca06da92SBram Moolenaar dict_T *self; // selfdict 34ca06da92SBram Moolenaar } luaV_Funcref; 350ba04296SBram Moolenaar typedef void (*msgfunc_T)(char_u *); 360ba04296SBram Moolenaar 371dced572SBram Moolenaar static const char LUAVIM_DICT[] = "dict"; 381dced572SBram Moolenaar static const char LUAVIM_LIST[] = "list"; 39ca06da92SBram Moolenaar static const char LUAVIM_FUNCREF[] = "funcref"; 400ba04296SBram Moolenaar static const char LUAVIM_BUFFER[] = "buffer"; 410ba04296SBram Moolenaar static const char LUAVIM_WINDOW[] = "window"; 420ba04296SBram Moolenaar static const char LUAVIM_FREE[] = "luaV_free"; 431dced572SBram Moolenaar static const char LUAVIM_LUAEVAL[] = "luaV_luaeval"; 441dced572SBram Moolenaar static const char LUAVIM_SETREF[] = "luaV_setref"; 450ba04296SBram Moolenaar 461dced572SBram Moolenaar /* most functions are closures with a cache table as first upvalue; 471dced572SBram Moolenaar * get/setudata manage references to vim userdata in cache table through 481dced572SBram Moolenaar * object pointers (light userdata) */ 491dced572SBram Moolenaar #define luaV_getudata(L, v) \ 501dced572SBram Moolenaar lua_pushlightuserdata((L), (void *) (v)); \ 511dced572SBram Moolenaar lua_rawget((L), lua_upvalueindex(1)) 521dced572SBram Moolenaar #define luaV_setudata(L, v) \ 531dced572SBram Moolenaar lua_pushlightuserdata((L), (void *) (v)); \ 541dced572SBram Moolenaar lua_pushvalue((L), -2); \ 551dced572SBram Moolenaar lua_rawset((L), lua_upvalueindex(1)) 560ba04296SBram Moolenaar #define luaV_getfield(L, s) \ 570ba04296SBram Moolenaar lua_pushlightuserdata((L), (void *)(s)); \ 580ba04296SBram Moolenaar lua_rawget((L), LUA_REGISTRYINDEX) 590ba04296SBram Moolenaar #define luaV_checksandbox(L) \ 600ba04296SBram Moolenaar if (sandbox) luaL_error((L), "not allowed in sandbox") 610ba04296SBram Moolenaar #define luaV_msg(L) luaV_msgfunc((L), (msgfunc_T) msg) 620ba04296SBram Moolenaar #define luaV_emsg(L) luaV_msgfunc((L), (msgfunc_T) emsg) 63ca06da92SBram Moolenaar #define luaV_checktypval(L, a, v, msg) \ 64ca06da92SBram Moolenaar do { \ 65ca06da92SBram Moolenaar if (luaV_totypval(L, a, v) == FAIL) \ 66ca06da92SBram Moolenaar luaL_error(L, msg ": cannot convert value"); \ 67ca06da92SBram Moolenaar } while (0) 680ba04296SBram Moolenaar 691dced572SBram Moolenaar static luaV_List *luaV_pushlist(lua_State *L, list_T *lis); 701dced572SBram Moolenaar static luaV_Dict *luaV_pushdict(lua_State *L, dict_T *dic); 71*4eefe47eSBram Moolenaar static luaV_Funcref *luaV_pushfuncref(lua_State *L, char_u *name); 721dced572SBram Moolenaar 731dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501 741dced572SBram Moolenaar #define luaV_openlib(L, l, n) luaL_openlib(L, NULL, l, n) 751dced572SBram Moolenaar #define luaL_typeerror luaL_typerror 761dced572SBram Moolenaar #else 771dced572SBram Moolenaar #define luaV_openlib luaL_setfuncs 781dced572SBram Moolenaar #endif 790ba04296SBram Moolenaar 800ba04296SBram Moolenaar #ifdef DYNAMIC_LUA 812334b6d5SBram Moolenaar 824f97475dSBram Moolenaar #ifndef MSWIN 832334b6d5SBram Moolenaar # include <dlfcn.h> 842334b6d5SBram Moolenaar # define HANDLE void* 852334b6d5SBram Moolenaar # define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL) 862334b6d5SBram Moolenaar # define symbol_from_dll dlsym 872334b6d5SBram Moolenaar # define close_dll dlclose 882334b6d5SBram Moolenaar #else 89ebbcb824SBram Moolenaar # define load_dll vimLoadLib 902334b6d5SBram Moolenaar # define symbol_from_dll GetProcAddress 912334b6d5SBram Moolenaar # define close_dll FreeLibrary 922334b6d5SBram Moolenaar #endif 932334b6d5SBram Moolenaar 940ba04296SBram Moolenaar /* lauxlib */ 951dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501 960ba04296SBram Moolenaar #define luaL_register dll_luaL_register 971dced572SBram Moolenaar #define luaL_prepbuffer dll_luaL_prepbuffer 981dced572SBram Moolenaar #define luaL_openlib dll_luaL_openlib 990ba04296SBram Moolenaar #define luaL_typerror dll_luaL_typerror 1001dced572SBram Moolenaar #define luaL_loadfile dll_luaL_loadfile 1011dced572SBram Moolenaar #define luaL_loadbuffer dll_luaL_loadbuffer 1021dced572SBram Moolenaar #else 1031dced572SBram Moolenaar #define luaL_prepbuffsize dll_luaL_prepbuffsize 1041dced572SBram Moolenaar #define luaL_setfuncs dll_luaL_setfuncs 1051dced572SBram Moolenaar #define luaL_loadfilex dll_luaL_loadfilex 1061dced572SBram Moolenaar #define luaL_loadbufferx dll_luaL_loadbufferx 1071dced572SBram Moolenaar #define luaL_argerror dll_luaL_argerror 1081dced572SBram Moolenaar #endif 109bd2f3c3eSBram Moolenaar #define luaL_checkany dll_luaL_checkany 1100ba04296SBram Moolenaar #define luaL_checklstring dll_luaL_checklstring 1110ba04296SBram Moolenaar #define luaL_checkinteger dll_luaL_checkinteger 1120ba04296SBram Moolenaar #define luaL_optinteger dll_luaL_optinteger 1130ba04296SBram Moolenaar #define luaL_checktype dll_luaL_checktype 1140ba04296SBram Moolenaar #define luaL_error dll_luaL_error 1150ba04296SBram Moolenaar #define luaL_newstate dll_luaL_newstate 1160ba04296SBram Moolenaar #define luaL_buffinit dll_luaL_buffinit 1170ba04296SBram Moolenaar #define luaL_addlstring dll_luaL_addlstring 1180ba04296SBram Moolenaar #define luaL_pushresult dll_luaL_pushresult 1190ba04296SBram Moolenaar /* lua */ 1201dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501 1211dced572SBram Moolenaar #define lua_tonumber dll_lua_tonumber 1221dced572SBram Moolenaar #define lua_tointeger dll_lua_tointeger 1231dced572SBram Moolenaar #define lua_call dll_lua_call 1241dced572SBram Moolenaar #define lua_pcall dll_lua_pcall 1251dced572SBram Moolenaar #else 1261dced572SBram Moolenaar #define lua_tonumberx dll_lua_tonumberx 1271dced572SBram Moolenaar #define lua_tointegerx dll_lua_tointegerx 1281dced572SBram Moolenaar #define lua_callk dll_lua_callk 1291dced572SBram Moolenaar #define lua_pcallk dll_lua_pcallk 1301dced572SBram Moolenaar #define lua_getglobal dll_lua_getglobal 1311dced572SBram Moolenaar #define lua_setglobal dll_lua_setglobal 1321dced572SBram Moolenaar #endif 1331f860d85SBram Moolenaar #if LUA_VERSION_NUM <= 502 1341f860d85SBram Moolenaar #define lua_replace dll_lua_replace 1351f860d85SBram Moolenaar #define lua_remove dll_lua_remove 1361f860d85SBram Moolenaar #endif 1371f860d85SBram Moolenaar #if LUA_VERSION_NUM >= 503 1381f860d85SBram Moolenaar #define lua_rotate dll_lua_rotate 1391f860d85SBram Moolenaar #define lua_copy dll_lua_copy 1401f860d85SBram Moolenaar #endif 141bd2f3c3eSBram Moolenaar #define lua_typename dll_lua_typename 1420ba04296SBram Moolenaar #define lua_close dll_lua_close 1430ba04296SBram Moolenaar #define lua_gettop dll_lua_gettop 1440ba04296SBram Moolenaar #define lua_settop dll_lua_settop 1450ba04296SBram Moolenaar #define lua_pushvalue dll_lua_pushvalue 1460ba04296SBram Moolenaar #define lua_isnumber dll_lua_isnumber 1470ba04296SBram Moolenaar #define lua_isstring dll_lua_isstring 1480ba04296SBram Moolenaar #define lua_type dll_lua_type 1490ba04296SBram Moolenaar #define lua_rawequal dll_lua_rawequal 1500ba04296SBram Moolenaar #define lua_toboolean dll_lua_toboolean 1510ba04296SBram Moolenaar #define lua_tolstring dll_lua_tolstring 1520ba04296SBram Moolenaar #define lua_touserdata dll_lua_touserdata 1530ba04296SBram Moolenaar #define lua_pushnil dll_lua_pushnil 1540ba04296SBram Moolenaar #define lua_pushnumber dll_lua_pushnumber 1550ba04296SBram Moolenaar #define lua_pushinteger dll_lua_pushinteger 1560ba04296SBram Moolenaar #define lua_pushlstring dll_lua_pushlstring 1570ba04296SBram Moolenaar #define lua_pushstring dll_lua_pushstring 1580ba04296SBram Moolenaar #define lua_pushfstring dll_lua_pushfstring 1590ba04296SBram Moolenaar #define lua_pushcclosure dll_lua_pushcclosure 1600ba04296SBram Moolenaar #define lua_pushboolean dll_lua_pushboolean 1610ba04296SBram Moolenaar #define lua_pushlightuserdata dll_lua_pushlightuserdata 1620ba04296SBram Moolenaar #define lua_getfield dll_lua_getfield 1630ba04296SBram Moolenaar #define lua_rawget dll_lua_rawget 1641dced572SBram Moolenaar #define lua_rawgeti dll_lua_rawgeti 1650ba04296SBram Moolenaar #define lua_createtable dll_lua_createtable 166830e3583SBram Moolenaar #if LUA_VERSION_NUM >= 504 167830e3583SBram Moolenaar #define lua_newuserdatauv dll_lua_newuserdatauv 168830e3583SBram Moolenaar #else 1690ba04296SBram Moolenaar #define lua_newuserdata dll_lua_newuserdata 170830e3583SBram Moolenaar #endif 1710ba04296SBram Moolenaar #define lua_getmetatable dll_lua_getmetatable 1720ba04296SBram Moolenaar #define lua_setfield dll_lua_setfield 1730ba04296SBram Moolenaar #define lua_rawset dll_lua_rawset 1740ba04296SBram Moolenaar #define lua_rawseti dll_lua_rawseti 1750ba04296SBram Moolenaar #define lua_setmetatable dll_lua_setmetatable 176bd2f3c3eSBram Moolenaar #define lua_next dll_lua_next 1770ba04296SBram Moolenaar /* libs */ 1780ba04296SBram Moolenaar #define luaopen_base dll_luaopen_base 1790ba04296SBram Moolenaar #define luaopen_table dll_luaopen_table 1800ba04296SBram Moolenaar #define luaopen_string dll_luaopen_string 1810ba04296SBram Moolenaar #define luaopen_math dll_luaopen_math 18216c98f9cSBram Moolenaar #define luaopen_io dll_luaopen_io 1830ba04296SBram Moolenaar #define luaopen_os dll_luaopen_os 1840ba04296SBram Moolenaar #define luaopen_package dll_luaopen_package 1850ba04296SBram Moolenaar #define luaopen_debug dll_luaopen_debug 18616c98f9cSBram Moolenaar #define luaL_openlibs dll_luaL_openlibs 1870ba04296SBram Moolenaar 1880ba04296SBram Moolenaar /* lauxlib */ 1891dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501 1900ba04296SBram Moolenaar void (*dll_luaL_register) (lua_State *L, const char *libname, const luaL_Reg *l); 1911dced572SBram Moolenaar char *(*dll_luaL_prepbuffer) (luaL_Buffer *B); 1921dced572SBram Moolenaar void (*dll_luaL_openlib) (lua_State *L, const char *libname, const luaL_Reg *l, int nup); 1930ba04296SBram Moolenaar int (*dll_luaL_typerror) (lua_State *L, int narg, const char *tname); 1941dced572SBram Moolenaar int (*dll_luaL_loadfile) (lua_State *L, const char *filename); 1951dced572SBram Moolenaar int (*dll_luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, const char *name); 1961dced572SBram Moolenaar #else 1971dced572SBram Moolenaar char *(*dll_luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); 1981dced572SBram Moolenaar void (*dll_luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); 1991dced572SBram Moolenaar int (*dll_luaL_loadfilex) (lua_State *L, const char *filename, const char *mode); 2001dced572SBram Moolenaar int (*dll_luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode); 2011dced572SBram Moolenaar int (*dll_luaL_argerror) (lua_State *L, int numarg, const char *extramsg); 2021dced572SBram Moolenaar #endif 203bd2f3c3eSBram Moolenaar void (*dll_luaL_checkany) (lua_State *L, int narg); 2040ba04296SBram Moolenaar const char *(*dll_luaL_checklstring) (lua_State *L, int numArg, size_t *l); 2050ba04296SBram Moolenaar lua_Integer (*dll_luaL_checkinteger) (lua_State *L, int numArg); 2060ba04296SBram Moolenaar lua_Integer (*dll_luaL_optinteger) (lua_State *L, int nArg, lua_Integer def); 2070ba04296SBram Moolenaar void (*dll_luaL_checktype) (lua_State *L, int narg, int t); 2080ba04296SBram Moolenaar int (*dll_luaL_error) (lua_State *L, const char *fmt, ...); 2090ba04296SBram Moolenaar lua_State *(*dll_luaL_newstate) (void); 2100ba04296SBram Moolenaar void (*dll_luaL_buffinit) (lua_State *L, luaL_Buffer *B); 2110ba04296SBram Moolenaar void (*dll_luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); 2120ba04296SBram Moolenaar void (*dll_luaL_pushresult) (luaL_Buffer *B); 2130ba04296SBram Moolenaar /* lua */ 2141dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501 2151dced572SBram Moolenaar lua_Number (*dll_lua_tonumber) (lua_State *L, int idx); 2161dced572SBram Moolenaar lua_Integer (*dll_lua_tointeger) (lua_State *L, int idx); 2171dced572SBram Moolenaar void (*dll_lua_call) (lua_State *L, int nargs, int nresults); 2181dced572SBram Moolenaar int (*dll_lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); 2191dced572SBram Moolenaar #else 2201dced572SBram Moolenaar lua_Number (*dll_lua_tonumberx) (lua_State *L, int idx, int *isnum); 2211dced572SBram Moolenaar lua_Integer (*dll_lua_tointegerx) (lua_State *L, int idx, int *isnum); 2221dced572SBram Moolenaar void (*dll_lua_callk) (lua_State *L, int nargs, int nresults, int ctx, 2231dced572SBram Moolenaar lua_CFunction k); 2241dced572SBram Moolenaar int (*dll_lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, 2251dced572SBram Moolenaar int ctx, lua_CFunction k); 2261dced572SBram Moolenaar void (*dll_lua_getglobal) (lua_State *L, const char *var); 2271dced572SBram Moolenaar void (*dll_lua_setglobal) (lua_State *L, const char *var); 2281f860d85SBram Moolenaar #endif 2291f860d85SBram Moolenaar #if LUA_VERSION_NUM <= 502 2301f860d85SBram Moolenaar void (*dll_lua_replace) (lua_State *L, int idx); 2311f860d85SBram Moolenaar void (*dll_lua_remove) (lua_State *L, int idx); 2321f860d85SBram Moolenaar #endif 2331f860d85SBram Moolenaar #if LUA_VERSION_NUM >= 503 2341f860d85SBram Moolenaar void (*dll_lua_rotate) (lua_State *L, int idx, int n); 2359514b1f9SBram Moolenaar void (*dll_lua_copy) (lua_State *L, int fromidx, int toidx); 2361dced572SBram Moolenaar #endif 237bd2f3c3eSBram Moolenaar const char *(*dll_lua_typename) (lua_State *L, int tp); 2380ba04296SBram Moolenaar void (*dll_lua_close) (lua_State *L); 2390ba04296SBram Moolenaar int (*dll_lua_gettop) (lua_State *L); 2400ba04296SBram Moolenaar void (*dll_lua_settop) (lua_State *L, int idx); 2410ba04296SBram Moolenaar void (*dll_lua_pushvalue) (lua_State *L, int idx); 2420ba04296SBram Moolenaar int (*dll_lua_isnumber) (lua_State *L, int idx); 2430ba04296SBram Moolenaar int (*dll_lua_isstring) (lua_State *L, int idx); 2440ba04296SBram Moolenaar int (*dll_lua_type) (lua_State *L, int idx); 2450ba04296SBram Moolenaar int (*dll_lua_rawequal) (lua_State *L, int idx1, int idx2); 2460ba04296SBram Moolenaar int (*dll_lua_toboolean) (lua_State *L, int idx); 2470ba04296SBram Moolenaar const char *(*dll_lua_tolstring) (lua_State *L, int idx, size_t *len); 2480ba04296SBram Moolenaar void *(*dll_lua_touserdata) (lua_State *L, int idx); 2490ba04296SBram Moolenaar void (*dll_lua_pushnil) (lua_State *L); 2500ba04296SBram Moolenaar void (*dll_lua_pushnumber) (lua_State *L, lua_Number n); 2510ba04296SBram Moolenaar void (*dll_lua_pushinteger) (lua_State *L, lua_Integer n); 2520ba04296SBram Moolenaar void (*dll_lua_pushlstring) (lua_State *L, const char *s, size_t l); 2530ba04296SBram Moolenaar void (*dll_lua_pushstring) (lua_State *L, const char *s); 2540ba04296SBram Moolenaar const char *(*dll_lua_pushfstring) (lua_State *L, const char *fmt, ...); 2550ba04296SBram Moolenaar void (*dll_lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); 2560ba04296SBram Moolenaar void (*dll_lua_pushboolean) (lua_State *L, int b); 2570ba04296SBram Moolenaar void (*dll_lua_pushlightuserdata) (lua_State *L, void *p); 2580ba04296SBram Moolenaar void (*dll_lua_getfield) (lua_State *L, int idx, const char *k); 25917413671SBram Moolenaar #if LUA_VERSION_NUM <= 502 2600ba04296SBram Moolenaar void (*dll_lua_rawget) (lua_State *L, int idx); 2611dced572SBram Moolenaar void (*dll_lua_rawgeti) (lua_State *L, int idx, int n); 26217413671SBram Moolenaar #else 26317413671SBram Moolenaar int (*dll_lua_rawget) (lua_State *L, int idx); 26417413671SBram Moolenaar int (*dll_lua_rawgeti) (lua_State *L, int idx, lua_Integer n); 26517413671SBram Moolenaar #endif 2660ba04296SBram Moolenaar void (*dll_lua_createtable) (lua_State *L, int narr, int nrec); 267830e3583SBram Moolenaar #if LUA_VERSION_NUM >= 504 268830e3583SBram Moolenaar void *(*dll_lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue); 269830e3583SBram Moolenaar #else 2700ba04296SBram Moolenaar void *(*dll_lua_newuserdata) (lua_State *L, size_t sz); 271830e3583SBram Moolenaar #endif 2720ba04296SBram Moolenaar int (*dll_lua_getmetatable) (lua_State *L, int objindex); 2730ba04296SBram Moolenaar void (*dll_lua_setfield) (lua_State *L, int idx, const char *k); 2740ba04296SBram Moolenaar void (*dll_lua_rawset) (lua_State *L, int idx); 27517413671SBram Moolenaar #if LUA_VERSION_NUM <= 502 2760ba04296SBram Moolenaar void (*dll_lua_rawseti) (lua_State *L, int idx, int n); 27717413671SBram Moolenaar #else 27817413671SBram Moolenaar void (*dll_lua_rawseti) (lua_State *L, int idx, lua_Integer n); 27917413671SBram Moolenaar #endif 2800ba04296SBram Moolenaar int (*dll_lua_setmetatable) (lua_State *L, int objindex); 281bd2f3c3eSBram Moolenaar int (*dll_lua_next) (lua_State *L, int idx); 2820ba04296SBram Moolenaar /* libs */ 2830ba04296SBram Moolenaar int (*dll_luaopen_base) (lua_State *L); 2840ba04296SBram Moolenaar int (*dll_luaopen_table) (lua_State *L); 2850ba04296SBram Moolenaar int (*dll_luaopen_string) (lua_State *L); 2860ba04296SBram Moolenaar int (*dll_luaopen_math) (lua_State *L); 28716c98f9cSBram Moolenaar int (*dll_luaopen_io) (lua_State *L); 2880ba04296SBram Moolenaar int (*dll_luaopen_os) (lua_State *L); 2890ba04296SBram Moolenaar int (*dll_luaopen_package) (lua_State *L); 2900ba04296SBram Moolenaar int (*dll_luaopen_debug) (lua_State *L); 29116c98f9cSBram Moolenaar void (*dll_luaL_openlibs) (lua_State *L); 2920ba04296SBram Moolenaar 2930ba04296SBram Moolenaar typedef void **luaV_function; 2940ba04296SBram Moolenaar typedef struct { 2950ba04296SBram Moolenaar const char *name; 2960ba04296SBram Moolenaar luaV_function func; 2970ba04296SBram Moolenaar } luaV_Reg; 2980ba04296SBram Moolenaar 2990ba04296SBram Moolenaar static const luaV_Reg luaV_dll[] = { 3000ba04296SBram Moolenaar /* lauxlib */ 3011dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501 3020ba04296SBram Moolenaar {"luaL_register", (luaV_function) &dll_luaL_register}, 3031dced572SBram Moolenaar {"luaL_prepbuffer", (luaV_function) &dll_luaL_prepbuffer}, 3041dced572SBram Moolenaar {"luaL_openlib", (luaV_function) &dll_luaL_openlib}, 3050ba04296SBram Moolenaar {"luaL_typerror", (luaV_function) &dll_luaL_typerror}, 3061dced572SBram Moolenaar {"luaL_loadfile", (luaV_function) &dll_luaL_loadfile}, 3071dced572SBram Moolenaar {"luaL_loadbuffer", (luaV_function) &dll_luaL_loadbuffer}, 3081dced572SBram Moolenaar #else 3091dced572SBram Moolenaar {"luaL_prepbuffsize", (luaV_function) &dll_luaL_prepbuffsize}, 3101dced572SBram Moolenaar {"luaL_setfuncs", (luaV_function) &dll_luaL_setfuncs}, 3111dced572SBram Moolenaar {"luaL_loadfilex", (luaV_function) &dll_luaL_loadfilex}, 3121dced572SBram Moolenaar {"luaL_loadbufferx", (luaV_function) &dll_luaL_loadbufferx}, 3131dced572SBram Moolenaar {"luaL_argerror", (luaV_function) &dll_luaL_argerror}, 3141dced572SBram Moolenaar #endif 315bd2f3c3eSBram Moolenaar {"luaL_checkany", (luaV_function) &dll_luaL_checkany}, 3160ba04296SBram Moolenaar {"luaL_checklstring", (luaV_function) &dll_luaL_checklstring}, 3170ba04296SBram Moolenaar {"luaL_checkinteger", (luaV_function) &dll_luaL_checkinteger}, 3180ba04296SBram Moolenaar {"luaL_optinteger", (luaV_function) &dll_luaL_optinteger}, 3190ba04296SBram Moolenaar {"luaL_checktype", (luaV_function) &dll_luaL_checktype}, 3200ba04296SBram Moolenaar {"luaL_error", (luaV_function) &dll_luaL_error}, 3210ba04296SBram Moolenaar {"luaL_newstate", (luaV_function) &dll_luaL_newstate}, 3220ba04296SBram Moolenaar {"luaL_buffinit", (luaV_function) &dll_luaL_buffinit}, 3230ba04296SBram Moolenaar {"luaL_addlstring", (luaV_function) &dll_luaL_addlstring}, 3240ba04296SBram Moolenaar {"luaL_pushresult", (luaV_function) &dll_luaL_pushresult}, 3250ba04296SBram Moolenaar /* lua */ 3261dced572SBram Moolenaar #if LUA_VERSION_NUM <= 501 3271dced572SBram Moolenaar {"lua_tonumber", (luaV_function) &dll_lua_tonumber}, 3281dced572SBram Moolenaar {"lua_tointeger", (luaV_function) &dll_lua_tointeger}, 3291dced572SBram Moolenaar {"lua_call", (luaV_function) &dll_lua_call}, 3301dced572SBram Moolenaar {"lua_pcall", (luaV_function) &dll_lua_pcall}, 3311dced572SBram Moolenaar #else 3321dced572SBram Moolenaar {"lua_tonumberx", (luaV_function) &dll_lua_tonumberx}, 3331dced572SBram Moolenaar {"lua_tointegerx", (luaV_function) &dll_lua_tointegerx}, 3341dced572SBram Moolenaar {"lua_callk", (luaV_function) &dll_lua_callk}, 3351dced572SBram Moolenaar {"lua_pcallk", (luaV_function) &dll_lua_pcallk}, 3361dced572SBram Moolenaar {"lua_getglobal", (luaV_function) &dll_lua_getglobal}, 3371dced572SBram Moolenaar {"lua_setglobal", (luaV_function) &dll_lua_setglobal}, 3381dced572SBram Moolenaar #endif 3391f860d85SBram Moolenaar #if LUA_VERSION_NUM <= 502 3401f860d85SBram Moolenaar {"lua_replace", (luaV_function) &dll_lua_replace}, 3411f860d85SBram Moolenaar {"lua_remove", (luaV_function) &dll_lua_remove}, 3421f860d85SBram Moolenaar #endif 3431f860d85SBram Moolenaar #if LUA_VERSION_NUM >= 503 3441f860d85SBram Moolenaar {"lua_rotate", (luaV_function) &dll_lua_rotate}, 3451f860d85SBram Moolenaar {"lua_copy", (luaV_function) &dll_lua_copy}, 3461f860d85SBram Moolenaar #endif 347bd2f3c3eSBram Moolenaar {"lua_typename", (luaV_function) &dll_lua_typename}, 3480ba04296SBram Moolenaar {"lua_close", (luaV_function) &dll_lua_close}, 3490ba04296SBram Moolenaar {"lua_gettop", (luaV_function) &dll_lua_gettop}, 3500ba04296SBram Moolenaar {"lua_settop", (luaV_function) &dll_lua_settop}, 3510ba04296SBram Moolenaar {"lua_pushvalue", (luaV_function) &dll_lua_pushvalue}, 3520ba04296SBram Moolenaar {"lua_isnumber", (luaV_function) &dll_lua_isnumber}, 3530ba04296SBram Moolenaar {"lua_isstring", (luaV_function) &dll_lua_isstring}, 3540ba04296SBram Moolenaar {"lua_type", (luaV_function) &dll_lua_type}, 3550ba04296SBram Moolenaar {"lua_rawequal", (luaV_function) &dll_lua_rawequal}, 3560ba04296SBram Moolenaar {"lua_toboolean", (luaV_function) &dll_lua_toboolean}, 3570ba04296SBram Moolenaar {"lua_tolstring", (luaV_function) &dll_lua_tolstring}, 3580ba04296SBram Moolenaar {"lua_touserdata", (luaV_function) &dll_lua_touserdata}, 3590ba04296SBram Moolenaar {"lua_pushnil", (luaV_function) &dll_lua_pushnil}, 3600ba04296SBram Moolenaar {"lua_pushnumber", (luaV_function) &dll_lua_pushnumber}, 3610ba04296SBram Moolenaar {"lua_pushinteger", (luaV_function) &dll_lua_pushinteger}, 3620ba04296SBram Moolenaar {"lua_pushlstring", (luaV_function) &dll_lua_pushlstring}, 3630ba04296SBram Moolenaar {"lua_pushstring", (luaV_function) &dll_lua_pushstring}, 3640ba04296SBram Moolenaar {"lua_pushfstring", (luaV_function) &dll_lua_pushfstring}, 3650ba04296SBram Moolenaar {"lua_pushcclosure", (luaV_function) &dll_lua_pushcclosure}, 3660ba04296SBram Moolenaar {"lua_pushboolean", (luaV_function) &dll_lua_pushboolean}, 3670ba04296SBram Moolenaar {"lua_pushlightuserdata", (luaV_function) &dll_lua_pushlightuserdata}, 3680ba04296SBram Moolenaar {"lua_getfield", (luaV_function) &dll_lua_getfield}, 3690ba04296SBram Moolenaar {"lua_rawget", (luaV_function) &dll_lua_rawget}, 3701dced572SBram Moolenaar {"lua_rawgeti", (luaV_function) &dll_lua_rawgeti}, 3710ba04296SBram Moolenaar {"lua_createtable", (luaV_function) &dll_lua_createtable}, 372830e3583SBram Moolenaar #if LUA_VERSION_NUM >= 504 373830e3583SBram Moolenaar {"lua_newuserdatauv", (luaV_function) &dll_lua_newuserdatauv}, 374830e3583SBram Moolenaar #else 3750ba04296SBram Moolenaar {"lua_newuserdata", (luaV_function) &dll_lua_newuserdata}, 376830e3583SBram Moolenaar #endif 3770ba04296SBram Moolenaar {"lua_getmetatable", (luaV_function) &dll_lua_getmetatable}, 3780ba04296SBram Moolenaar {"lua_setfield", (luaV_function) &dll_lua_setfield}, 3790ba04296SBram Moolenaar {"lua_rawset", (luaV_function) &dll_lua_rawset}, 3800ba04296SBram Moolenaar {"lua_rawseti", (luaV_function) &dll_lua_rawseti}, 3810ba04296SBram Moolenaar {"lua_setmetatable", (luaV_function) &dll_lua_setmetatable}, 382bd2f3c3eSBram Moolenaar {"lua_next", (luaV_function) &dll_lua_next}, 3830ba04296SBram Moolenaar /* libs */ 3840ba04296SBram Moolenaar {"luaopen_base", (luaV_function) &dll_luaopen_base}, 3850ba04296SBram Moolenaar {"luaopen_table", (luaV_function) &dll_luaopen_table}, 3860ba04296SBram Moolenaar {"luaopen_string", (luaV_function) &dll_luaopen_string}, 3870ba04296SBram Moolenaar {"luaopen_math", (luaV_function) &dll_luaopen_math}, 38816c98f9cSBram Moolenaar {"luaopen_io", (luaV_function) &dll_luaopen_io}, 3890ba04296SBram Moolenaar {"luaopen_os", (luaV_function) &dll_luaopen_os}, 3900ba04296SBram Moolenaar {"luaopen_package", (luaV_function) &dll_luaopen_package}, 3910ba04296SBram Moolenaar {"luaopen_debug", (luaV_function) &dll_luaopen_debug}, 39216c98f9cSBram Moolenaar {"luaL_openlibs", (luaV_function) &dll_luaL_openlibs}, 3930ba04296SBram Moolenaar {NULL, NULL} 3940ba04296SBram Moolenaar }; 3950ba04296SBram Moolenaar 3962334b6d5SBram Moolenaar static HANDLE hinstLua = NULL; 3970ba04296SBram Moolenaar 39855d5c034SBram Moolenaar static void 39955d5c034SBram Moolenaar end_dynamic_lua(void) 40055d5c034SBram Moolenaar { 40155d5c034SBram Moolenaar if (hinstLua) 40255d5c034SBram Moolenaar { 4032334b6d5SBram Moolenaar close_dll(hinstLua); 4040ba04296SBram Moolenaar hinstLua = 0; 4050ba04296SBram Moolenaar } 4060ba04296SBram Moolenaar } 4070ba04296SBram Moolenaar 40855d5c034SBram Moolenaar static int 40955d5c034SBram Moolenaar lua_link_init(char *libname, int verbose) 41055d5c034SBram Moolenaar { 4110ba04296SBram Moolenaar const luaV_Reg *reg; 4120ba04296SBram Moolenaar if (hinstLua) return OK; 4132334b6d5SBram Moolenaar hinstLua = load_dll(libname); 41455d5c034SBram Moolenaar if (!hinstLua) 41555d5c034SBram Moolenaar { 41655d5c034SBram Moolenaar if (verbose) 417f9e3e09fSBram Moolenaar semsg(_(e_loadlib), libname); 4180ba04296SBram Moolenaar return FAIL; 4190ba04296SBram Moolenaar } 42055d5c034SBram Moolenaar for (reg = luaV_dll; reg->func; reg++) 42155d5c034SBram Moolenaar { 4222334b6d5SBram Moolenaar if ((*reg->func = symbol_from_dll(hinstLua, reg->name)) == NULL) 4232334b6d5SBram Moolenaar { 4242334b6d5SBram Moolenaar close_dll(hinstLua); 4250ba04296SBram Moolenaar hinstLua = 0; 42655d5c034SBram Moolenaar if (verbose) 427f9e3e09fSBram Moolenaar semsg(_(e_loadfunc), reg->name); 4280ba04296SBram Moolenaar return FAIL; 4290ba04296SBram Moolenaar } 4300ba04296SBram Moolenaar } 4310ba04296SBram Moolenaar return OK; 4320ba04296SBram Moolenaar } 433d90b6c02SBram Moolenaar #endif /* DYNAMIC_LUA */ 4340ba04296SBram Moolenaar 435d90b6c02SBram Moolenaar #if defined(DYNAMIC_LUA) || defined(PROTO) 43655d5c034SBram Moolenaar int 43755d5c034SBram Moolenaar lua_enabled(int verbose) 43855d5c034SBram Moolenaar { 43925e4fcdeSBram Moolenaar return lua_link_init((char *)p_luadll, verbose) == OK; 4400ba04296SBram Moolenaar } 441d90b6c02SBram Moolenaar #endif 4420ba04296SBram Moolenaar 4431dced572SBram Moolenaar #if LUA_VERSION_NUM > 501 4441dced572SBram Moolenaar static int 4451dced572SBram Moolenaar luaL_typeerror(lua_State *L, int narg, const char *tname) 4461dced572SBram Moolenaar { 4471dced572SBram Moolenaar const char *msg = lua_pushfstring(L, "%s expected, got %s", 4481dced572SBram Moolenaar tname, luaL_typename(L, narg)); 4491dced572SBram Moolenaar return luaL_argerror(L, narg, msg); 4501dced572SBram Moolenaar } 4511dced572SBram Moolenaar #endif 4521dced572SBram Moolenaar 4530ba04296SBram Moolenaar 4540ba04296SBram Moolenaar /* ======= Internal ======= */ 4550ba04296SBram Moolenaar 45655d5c034SBram Moolenaar static void 45755d5c034SBram Moolenaar luaV_newmetatable(lua_State *L, const char *tname) 45855d5c034SBram Moolenaar { 4590ba04296SBram Moolenaar lua_newtable(L); 4600ba04296SBram Moolenaar lua_pushlightuserdata(L, (void *) tname); 4610ba04296SBram Moolenaar lua_pushvalue(L, -2); 4620ba04296SBram Moolenaar lua_rawset(L, LUA_REGISTRYINDEX); 4630ba04296SBram Moolenaar } 4640ba04296SBram Moolenaar 46555d5c034SBram Moolenaar static void * 46655d5c034SBram Moolenaar luaV_toudata(lua_State *L, int ud, const char *tname) 46755d5c034SBram Moolenaar { 4680ba04296SBram Moolenaar void *p = lua_touserdata(L, ud); 46955d5c034SBram Moolenaar 47055d5c034SBram Moolenaar if (p != NULL) /* value is userdata? */ 47155d5c034SBram Moolenaar { 47255d5c034SBram Moolenaar if (lua_getmetatable(L, ud)) /* does it have a metatable? */ 47355d5c034SBram Moolenaar { 4740ba04296SBram Moolenaar luaV_getfield(L, tname); /* get metatable */ 47555d5c034SBram Moolenaar if (lua_rawequal(L, -1, -2)) /* MTs match? */ 47655d5c034SBram Moolenaar { 4770ba04296SBram Moolenaar lua_pop(L, 2); /* MTs */ 4780ba04296SBram Moolenaar return p; 4790ba04296SBram Moolenaar } 4800ba04296SBram Moolenaar } 4810ba04296SBram Moolenaar } 4820ba04296SBram Moolenaar return NULL; 4830ba04296SBram Moolenaar } 4840ba04296SBram Moolenaar 48555d5c034SBram Moolenaar static void * 4861dced572SBram Moolenaar luaV_checkcache(lua_State *L, void *p) 4871dced572SBram Moolenaar { 4881dced572SBram Moolenaar luaV_getudata(L, p); 4891dced572SBram Moolenaar if (lua_isnil(L, -1)) luaL_error(L, "invalid object"); 4901dced572SBram Moolenaar lua_pop(L, 1); 4911dced572SBram Moolenaar return p; 4921dced572SBram Moolenaar } 4931dced572SBram Moolenaar 4941dced572SBram Moolenaar #define luaV_unbox(L,luatyp,ud) (*((luatyp *) lua_touserdata((L),(ud)))) 4951dced572SBram Moolenaar 4961dced572SBram Moolenaar #define luaV_checkvalid(L,luatyp,ud) \ 4971dced572SBram Moolenaar luaV_checkcache((L), (void *) luaV_unbox((L),luatyp,(ud))) 4981dced572SBram Moolenaar 4991dced572SBram Moolenaar static void * 50055d5c034SBram Moolenaar luaV_checkudata(lua_State *L, int ud, const char *tname) 50155d5c034SBram Moolenaar { 5020ba04296SBram Moolenaar void *p = luaV_toudata(L, ud, tname); 5031dced572SBram Moolenaar if (p == NULL) luaL_typeerror(L, ud, tname); 5040ba04296SBram Moolenaar return p; 5050ba04296SBram Moolenaar } 5060ba04296SBram Moolenaar 50755d5c034SBram Moolenaar static void 50855d5c034SBram Moolenaar luaV_pushtypval(lua_State *L, typval_T *tv) 50955d5c034SBram Moolenaar { 5101dced572SBram Moolenaar if (tv == NULL) 5111dced572SBram Moolenaar { 5121dced572SBram Moolenaar lua_pushnil(L); 5131dced572SBram Moolenaar return; 5141dced572SBram Moolenaar } 51555d5c034SBram Moolenaar switch (tv->v_type) 51655d5c034SBram Moolenaar { 5170ba04296SBram Moolenaar case VAR_STRING: 518d04da7cbSBram Moolenaar lua_pushstring(L, tv->vval.v_string == NULL 519d04da7cbSBram Moolenaar ? "" : (char *)tv->vval.v_string); 5200ba04296SBram Moolenaar break; 5210ba04296SBram Moolenaar case VAR_NUMBER: 5220ba04296SBram Moolenaar lua_pushinteger(L, (int) tv->vval.v_number); 5230ba04296SBram Moolenaar break; 5240ba04296SBram Moolenaar #ifdef FEAT_FLOAT 5250ba04296SBram Moolenaar case VAR_FLOAT: 5260ba04296SBram Moolenaar lua_pushnumber(L, (lua_Number) tv->vval.v_float); 5270ba04296SBram Moolenaar break; 5280ba04296SBram Moolenaar #endif 5291dced572SBram Moolenaar case VAR_LIST: 5301dced572SBram Moolenaar luaV_pushlist(L, tv->vval.v_list); 5310ba04296SBram Moolenaar break; 5321dced572SBram Moolenaar case VAR_DICT: 5331dced572SBram Moolenaar luaV_pushdict(L, tv->vval.v_dict); 5341dced572SBram Moolenaar break; 535520e1e41SBram Moolenaar case VAR_SPECIAL: 536520e1e41SBram Moolenaar if (tv->vval.v_number <= VVAL_TRUE) 537520e1e41SBram Moolenaar lua_pushinteger(L, (int) tv->vval.v_number); 538520e1e41SBram Moolenaar else 539520e1e41SBram Moolenaar lua_pushnil(L); 540520e1e41SBram Moolenaar break; 541ca06da92SBram Moolenaar case VAR_FUNC: 542*4eefe47eSBram Moolenaar luaV_pushfuncref(L, tv->vval.v_string); 543ca06da92SBram Moolenaar break; 5441dced572SBram Moolenaar default: 5451dced572SBram Moolenaar lua_pushnil(L); 5460ba04296SBram Moolenaar } 5471dced572SBram Moolenaar } 54855d5c034SBram Moolenaar 549ca06da92SBram Moolenaar /* 550ca06da92SBram Moolenaar * Converts lua value at 'pos' to typval 'tv'. 551ca06da92SBram Moolenaar * Returns OK or FAIL. 552ca06da92SBram Moolenaar */ 553ca06da92SBram Moolenaar static int 5541dced572SBram Moolenaar luaV_totypval(lua_State *L, int pos, typval_T *tv) 55555d5c034SBram Moolenaar { 556ca06da92SBram Moolenaar int status = OK; 557ca06da92SBram Moolenaar 558ca06da92SBram Moolenaar switch (lua_type(L, pos)) 559ca06da92SBram Moolenaar { 5601dced572SBram Moolenaar case LUA_TBOOLEAN: 561520e1e41SBram Moolenaar tv->v_type = VAR_SPECIAL; 5621dced572SBram Moolenaar tv->vval.v_number = (varnumber_T) lua_toboolean(L, pos); 5631dced572SBram Moolenaar break; 5649067cd6cSBram Moolenaar case LUA_TNIL: 5659067cd6cSBram Moolenaar tv->v_type = VAR_SPECIAL; 5669067cd6cSBram Moolenaar tv->vval.v_number = VVAL_NULL; 5679067cd6cSBram Moolenaar break; 5681dced572SBram Moolenaar case LUA_TSTRING: 5691dced572SBram Moolenaar tv->v_type = VAR_STRING; 5701dced572SBram Moolenaar tv->vval.v_string = vim_strsave((char_u *) lua_tostring(L, pos)); 5711dced572SBram Moolenaar break; 5721dced572SBram Moolenaar case LUA_TNUMBER: 5731dced572SBram Moolenaar #ifdef FEAT_FLOAT 5741dced572SBram Moolenaar tv->v_type = VAR_FLOAT; 5751dced572SBram Moolenaar tv->vval.v_float = (float_T) lua_tonumber(L, pos); 5761dced572SBram Moolenaar #else 5771dced572SBram Moolenaar tv->v_type = VAR_NUMBER; 5781dced572SBram Moolenaar tv->vval.v_number = (varnumber_T) lua_tointeger(L, pos); 5791dced572SBram Moolenaar #endif 5801dced572SBram Moolenaar break; 581ca06da92SBram Moolenaar case LUA_TUSERDATA: 582ca06da92SBram Moolenaar { 5831dced572SBram Moolenaar void *p = lua_touserdata(L, pos); 584ca06da92SBram Moolenaar 5851dced572SBram Moolenaar if (lua_getmetatable(L, pos)) /* has metatable? */ 5862334b6d5SBram Moolenaar { 5871dced572SBram Moolenaar /* check list */ 5881dced572SBram Moolenaar luaV_getfield(L, LUAVIM_LIST); 5891dced572SBram Moolenaar if (lua_rawequal(L, -1, -2)) 59055d5c034SBram Moolenaar { 5911dced572SBram Moolenaar tv->v_type = VAR_LIST; 5921dced572SBram Moolenaar tv->vval.v_list = *((luaV_List *) p); 5931dced572SBram Moolenaar ++tv->vval.v_list->lv_refcount; 5941dced572SBram Moolenaar lua_pop(L, 2); /* MTs */ 595ca06da92SBram Moolenaar break; 5961dced572SBram Moolenaar } 5971dced572SBram Moolenaar /* check dict */ 5981dced572SBram Moolenaar luaV_getfield(L, LUAVIM_DICT); 5991dced572SBram Moolenaar if (lua_rawequal(L, -1, -3)) 60055d5c034SBram Moolenaar { 6011dced572SBram Moolenaar tv->v_type = VAR_DICT; 6021dced572SBram Moolenaar tv->vval.v_dict = *((luaV_Dict *) p); 6031dced572SBram Moolenaar ++tv->vval.v_dict->dv_refcount; 6041dced572SBram Moolenaar lua_pop(L, 3); /* MTs */ 6050ba04296SBram Moolenaar break; 6060ba04296SBram Moolenaar } 607ca06da92SBram Moolenaar /* check funcref */ 608ca06da92SBram Moolenaar luaV_getfield(L, LUAVIM_FUNCREF); 609ca06da92SBram Moolenaar if (lua_rawequal(L, -1, -4)) 610ca06da92SBram Moolenaar { 611ca06da92SBram Moolenaar luaV_Funcref *f = (luaV_Funcref *) p; 612*4eefe47eSBram Moolenaar func_ref(f->name); 613*4eefe47eSBram Moolenaar tv->v_type = VAR_FUNC; 614*4eefe47eSBram Moolenaar tv->vval.v_string = vim_strsave(f->name); 615ca06da92SBram Moolenaar lua_pop(L, 4); /* MTs */ 616ca06da92SBram Moolenaar break; 617ca06da92SBram Moolenaar } 618ca06da92SBram Moolenaar lua_pop(L, 4); /* MTs */ 619ca06da92SBram Moolenaar } 620ca06da92SBram Moolenaar } 621ca06da92SBram Moolenaar /* FALLTHROUGH */ 6220ba04296SBram Moolenaar default: 6231dced572SBram Moolenaar tv->v_type = VAR_NUMBER; 6241dced572SBram Moolenaar tv->vval.v_number = 0; 625ca06da92SBram Moolenaar status = FAIL; 6260ba04296SBram Moolenaar } 627ca06da92SBram Moolenaar return status; 6280ba04296SBram Moolenaar } 6290ba04296SBram Moolenaar 6300ba04296SBram Moolenaar /* similar to luaL_addlstring, but replaces \0 with \n if toline and 6310ba04296SBram Moolenaar * \n with \0 otherwise */ 63255d5c034SBram Moolenaar static void 63355d5c034SBram Moolenaar luaV_addlstring(luaL_Buffer *b, const char *s, size_t l, int toline) 63455d5c034SBram Moolenaar { 63555d5c034SBram Moolenaar while (l--) 63655d5c034SBram Moolenaar { 63755d5c034SBram Moolenaar if (*s == '\0' && toline) 63855d5c034SBram Moolenaar luaL_addchar(b, '\n'); 63955d5c034SBram Moolenaar else if (*s == '\n' && !toline) 64055d5c034SBram Moolenaar luaL_addchar(b, '\0'); 64155d5c034SBram Moolenaar else 64255d5c034SBram Moolenaar luaL_addchar(b, *s); 6430ba04296SBram Moolenaar s++; 6440ba04296SBram Moolenaar } 6450ba04296SBram Moolenaar } 6460ba04296SBram Moolenaar 64755d5c034SBram Moolenaar static void 64855d5c034SBram Moolenaar luaV_pushline(lua_State *L, buf_T *buf, linenr_T n) 64955d5c034SBram Moolenaar { 6500ba04296SBram Moolenaar const char *s = (const char *) ml_get_buf(buf, n, FALSE); 6510ba04296SBram Moolenaar luaL_Buffer b; 6520ba04296SBram Moolenaar luaL_buffinit(L, &b); 6530ba04296SBram Moolenaar luaV_addlstring(&b, s, strlen(s), 0); 6540ba04296SBram Moolenaar luaL_pushresult(&b); 6550ba04296SBram Moolenaar } 6560ba04296SBram Moolenaar 65755d5c034SBram Moolenaar static char_u * 65855d5c034SBram Moolenaar luaV_toline(lua_State *L, int pos) 65955d5c034SBram Moolenaar { 6600ba04296SBram Moolenaar size_t l; 6610ba04296SBram Moolenaar const char *s = lua_tolstring(L, pos, &l); 66255d5c034SBram Moolenaar 6630ba04296SBram Moolenaar luaL_Buffer b; 6640ba04296SBram Moolenaar luaL_buffinit(L, &b); 6650ba04296SBram Moolenaar luaV_addlstring(&b, s, l, 1); 6660ba04296SBram Moolenaar luaL_pushresult(&b); 6670ba04296SBram Moolenaar return (char_u *) lua_tostring(L, -1); 6680ba04296SBram Moolenaar } 6690ba04296SBram Moolenaar 6700ba04296SBram Moolenaar /* pops a string s from the top of the stack and calls mf(t) for pieces t of 6710ba04296SBram Moolenaar * s separated by newlines */ 67255d5c034SBram Moolenaar static void 67355d5c034SBram Moolenaar luaV_msgfunc(lua_State *L, msgfunc_T mf) 67455d5c034SBram Moolenaar { 6750ba04296SBram Moolenaar luaL_Buffer b; 6760ba04296SBram Moolenaar size_t l; 6770ba04296SBram Moolenaar const char *p, *s = lua_tolstring(L, -1, &l); 6780ba04296SBram Moolenaar luaL_buffinit(L, &b); 6790ba04296SBram Moolenaar luaV_addlstring(&b, s, l, 0); 6800ba04296SBram Moolenaar luaL_pushresult(&b); 6810ba04296SBram Moolenaar /* break string */ 6820ba04296SBram Moolenaar p = s = lua_tolstring(L, -1, &l); 68355d5c034SBram Moolenaar while (l--) 68455d5c034SBram Moolenaar { 68555d5c034SBram Moolenaar if (*p++ == '\0') /* break? */ 68655d5c034SBram Moolenaar { 6870ba04296SBram Moolenaar mf((char_u *) s); 6880ba04296SBram Moolenaar s = p; 6890ba04296SBram Moolenaar } 6900ba04296SBram Moolenaar } 6910ba04296SBram Moolenaar mf((char_u *) s); 6920ba04296SBram Moolenaar lua_pop(L, 2); /* original and modified strings */ 6930ba04296SBram Moolenaar } 6940ba04296SBram Moolenaar 6951dced572SBram Moolenaar #define luaV_newtype(typ,tname,luatyp,luatname) \ 6961dced572SBram Moolenaar static luatyp * \ 6971dced572SBram Moolenaar luaV_new##tname(lua_State *L, typ *obj) \ 6981dced572SBram Moolenaar { \ 6991dced572SBram Moolenaar luatyp *o = (luatyp *) lua_newuserdata(L, sizeof(luatyp)); \ 7001dced572SBram Moolenaar *o = obj; \ 7011dced572SBram Moolenaar luaV_setudata(L, obj); /* cache[obj] = udata */ \ 7021dced572SBram Moolenaar luaV_getfield(L, luatname); \ 7031dced572SBram Moolenaar lua_setmetatable(L, -2); \ 7041dced572SBram Moolenaar return o; \ 7050ba04296SBram Moolenaar } 7060ba04296SBram Moolenaar 7071dced572SBram Moolenaar #define luaV_pushtype(typ,tname,luatyp) \ 7081dced572SBram Moolenaar static luatyp * \ 7091dced572SBram Moolenaar luaV_push##tname(lua_State *L, typ *obj) \ 7101dced572SBram Moolenaar { \ 7111dced572SBram Moolenaar luatyp *o = NULL; \ 7121dced572SBram Moolenaar if (obj == NULL) \ 7131dced572SBram Moolenaar lua_pushnil(L); \ 7141dced572SBram Moolenaar else { \ 7151dced572SBram Moolenaar luaV_getudata(L, obj); \ 7161dced572SBram Moolenaar if (lua_isnil(L, -1)) /* not interned? */ \ 7171dced572SBram Moolenaar { \ 7181dced572SBram Moolenaar lua_pop(L, 1); \ 7191dced572SBram Moolenaar o = luaV_new##tname(L, obj); \ 7201dced572SBram Moolenaar } \ 7211dced572SBram Moolenaar else \ 7221dced572SBram Moolenaar o = (luatyp *) lua_touserdata(L, -1); \ 7231dced572SBram Moolenaar } \ 7241dced572SBram Moolenaar return o; \ 7250ba04296SBram Moolenaar } 7261dced572SBram Moolenaar 7271dced572SBram Moolenaar #define luaV_type_tostring(tname,luatname) \ 7281dced572SBram Moolenaar static int \ 7291dced572SBram Moolenaar luaV_##tname##_tostring(lua_State *L) \ 7301dced572SBram Moolenaar { \ 7311dced572SBram Moolenaar lua_pushfstring(L, "%s: %p", luatname, lua_touserdata(L, 1)); \ 7321dced572SBram Moolenaar return 1; \ 7331dced572SBram Moolenaar } 7341dced572SBram Moolenaar 7351dced572SBram Moolenaar /* ======= List type ======= */ 7361dced572SBram Moolenaar 7371dced572SBram Moolenaar static luaV_List * 7381dced572SBram Moolenaar luaV_newlist(lua_State *L, list_T *lis) 7391dced572SBram Moolenaar { 7401dced572SBram Moolenaar luaV_List *l = (luaV_List *) lua_newuserdata(L, sizeof(luaV_List)); 7411dced572SBram Moolenaar *l = lis; 7421dced572SBram Moolenaar lis->lv_refcount++; /* reference in Lua */ 7431dced572SBram Moolenaar luaV_setudata(L, lis); /* cache[lis] = udata */ 7441dced572SBram Moolenaar luaV_getfield(L, LUAVIM_LIST); 7451dced572SBram Moolenaar lua_setmetatable(L, -2); 7461dced572SBram Moolenaar return l; 7471dced572SBram Moolenaar } 7481dced572SBram Moolenaar 7491dced572SBram Moolenaar luaV_pushtype(list_T, list, luaV_List) 7501dced572SBram Moolenaar luaV_type_tostring(list, LUAVIM_LIST) 7511dced572SBram Moolenaar 7521dced572SBram Moolenaar static int 7531dced572SBram Moolenaar luaV_list_len(lua_State *L) 7541dced572SBram Moolenaar { 7551dced572SBram Moolenaar list_T *l = luaV_unbox(L, luaV_List, 1); 7561dced572SBram Moolenaar lua_pushinteger(L, (l == NULL) ? 0 : (int) l->lv_len); 7570ba04296SBram Moolenaar return 1; 7580ba04296SBram Moolenaar } 7590ba04296SBram Moolenaar 76055d5c034SBram Moolenaar static int 7611dced572SBram Moolenaar luaV_list_iter(lua_State *L) 7621dced572SBram Moolenaar { 7631dced572SBram Moolenaar listitem_T *li = (listitem_T *) lua_touserdata(L, lua_upvalueindex(2)); 7641dced572SBram Moolenaar if (li == NULL) return 0; 7651dced572SBram Moolenaar luaV_pushtypval(L, &li->li_tv); 7661dced572SBram Moolenaar lua_pushlightuserdata(L, (void *) li->li_next); 7671dced572SBram Moolenaar lua_replace(L, lua_upvalueindex(2)); 7681dced572SBram Moolenaar return 1; 7691dced572SBram Moolenaar } 7701dced572SBram Moolenaar 7711dced572SBram Moolenaar static int 7721dced572SBram Moolenaar luaV_list_call(lua_State *L) 7731dced572SBram Moolenaar { 7741dced572SBram Moolenaar list_T *l = luaV_unbox(L, luaV_List, 1); 7751dced572SBram Moolenaar lua_pushvalue(L, lua_upvalueindex(1)); /* pass cache table along */ 7761dced572SBram Moolenaar lua_pushlightuserdata(L, (void *) l->lv_first); 7771dced572SBram Moolenaar lua_pushcclosure(L, luaV_list_iter, 2); 7781dced572SBram Moolenaar return 1; 7791dced572SBram Moolenaar } 7801dced572SBram Moolenaar 7811dced572SBram Moolenaar static int 7821dced572SBram Moolenaar luaV_list_index(lua_State *L) 7831dced572SBram Moolenaar { 7841dced572SBram Moolenaar list_T *l = luaV_unbox(L, luaV_List, 1); 7851dced572SBram Moolenaar if (lua_isnumber(L, 2)) /* list item? */ 7861dced572SBram Moolenaar { 7871dced572SBram Moolenaar listitem_T *li = list_find(l, (long) luaL_checkinteger(L, 2)); 7881dced572SBram Moolenaar if (li == NULL) 7891dced572SBram Moolenaar lua_pushnil(L); 7901dced572SBram Moolenaar else 7911dced572SBram Moolenaar luaV_pushtypval(L, &li->li_tv); 7921dced572SBram Moolenaar } 7931dced572SBram Moolenaar else if (lua_isstring(L, 2)) /* method? */ 7941dced572SBram Moolenaar { 7951dced572SBram Moolenaar const char *s = lua_tostring(L, 2); 7961dced572SBram Moolenaar if (strncmp(s, "add", 3) == 0 797b376647bSBram Moolenaar || strncmp(s, "insert", 6) == 0) 7981dced572SBram Moolenaar { 7991dced572SBram Moolenaar lua_getmetatable(L, 1); 8001dced572SBram Moolenaar lua_getfield(L, -1, s); 8011dced572SBram Moolenaar } 8021dced572SBram Moolenaar else 8031dced572SBram Moolenaar lua_pushnil(L); 8041dced572SBram Moolenaar } 8051dced572SBram Moolenaar else 8061dced572SBram Moolenaar lua_pushnil(L); 8071dced572SBram Moolenaar return 1; 8081dced572SBram Moolenaar } 8091dced572SBram Moolenaar 8101dced572SBram Moolenaar static int 8111dced572SBram Moolenaar luaV_list_newindex(lua_State *L) 8121dced572SBram Moolenaar { 8131dced572SBram Moolenaar list_T *l = luaV_unbox(L, luaV_List, 1); 8141dced572SBram Moolenaar long n = (long) luaL_checkinteger(L, 2); 8151dced572SBram Moolenaar listitem_T *li; 8161dced572SBram Moolenaar if (l->lv_lock) 8171dced572SBram Moolenaar luaL_error(L, "list is locked"); 8181dced572SBram Moolenaar li = list_find(l, n); 8191dced572SBram Moolenaar if (li == NULL) return 0; 8201dced572SBram Moolenaar if (lua_isnil(L, 3)) /* remove? */ 8211dced572SBram Moolenaar { 8223ec7f4e4SBram Moolenaar vimlist_remove(l, li, li); 8231dced572SBram Moolenaar clear_tv(&li->li_tv); 8241dced572SBram Moolenaar vim_free(li); 8251dced572SBram Moolenaar } 8261dced572SBram Moolenaar else 8271dced572SBram Moolenaar { 8281dced572SBram Moolenaar typval_T v; 829ca06da92SBram Moolenaar luaV_checktypval(L, 3, &v, "setting list item"); 8301dced572SBram Moolenaar clear_tv(&li->li_tv); 8311dced572SBram Moolenaar copy_tv(&v, &li->li_tv); 832b376647bSBram Moolenaar clear_tv(&v); 8331dced572SBram Moolenaar } 8341dced572SBram Moolenaar return 0; 8351dced572SBram Moolenaar } 8361dced572SBram Moolenaar 8371dced572SBram Moolenaar static int 8381dced572SBram Moolenaar luaV_list_add(lua_State *L) 8391dced572SBram Moolenaar { 8401dced572SBram Moolenaar luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST); 8411dced572SBram Moolenaar list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis); 842b376647bSBram Moolenaar typval_T v; 8431dced572SBram Moolenaar if (l->lv_lock) 8441dced572SBram Moolenaar luaL_error(L, "list is locked"); 8451dced572SBram Moolenaar lua_settop(L, 2); 846ca06da92SBram Moolenaar luaV_checktypval(L, 2, &v, "adding list item"); 847b376647bSBram Moolenaar if (list_append_tv(l, &v) == FAIL) 848ca06da92SBram Moolenaar luaL_error(L, "failed to add item to list"); 849b376647bSBram Moolenaar clear_tv(&v); 8501dced572SBram Moolenaar lua_settop(L, 1); 8511dced572SBram Moolenaar return 1; 8521dced572SBram Moolenaar } 8531dced572SBram Moolenaar 8541dced572SBram Moolenaar static int 8551dced572SBram Moolenaar luaV_list_insert(lua_State *L) 8561dced572SBram Moolenaar { 8571dced572SBram Moolenaar luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST); 8581dced572SBram Moolenaar list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis); 85946538ee4SBram Moolenaar long pos = (long) luaL_optinteger(L, 3, 0); 8601dced572SBram Moolenaar listitem_T *li = NULL; 8611dced572SBram Moolenaar typval_T v; 8621dced572SBram Moolenaar if (l->lv_lock) 8631dced572SBram Moolenaar luaL_error(L, "list is locked"); 8641dced572SBram Moolenaar if (pos < l->lv_len) 8651dced572SBram Moolenaar { 8661dced572SBram Moolenaar li = list_find(l, pos); 8671dced572SBram Moolenaar if (li == NULL) 8681dced572SBram Moolenaar luaL_error(L, "invalid position"); 8691dced572SBram Moolenaar } 8701dced572SBram Moolenaar lua_settop(L, 2); 871ca06da92SBram Moolenaar luaV_checktypval(L, 2, &v, "inserting list item"); 872b376647bSBram Moolenaar if (list_insert_tv(l, &v, li) == FAIL) 873ca06da92SBram Moolenaar luaL_error(L, "failed to add item to list"); 874b376647bSBram Moolenaar clear_tv(&v); 8751dced572SBram Moolenaar lua_settop(L, 1); 8761dced572SBram Moolenaar return 1; 8771dced572SBram Moolenaar } 8781dced572SBram Moolenaar 8791dced572SBram Moolenaar static const luaL_Reg luaV_List_mt[] = { 8801dced572SBram Moolenaar {"__tostring", luaV_list_tostring}, 8811dced572SBram Moolenaar {"__len", luaV_list_len}, 8821dced572SBram Moolenaar {"__call", luaV_list_call}, 8831dced572SBram Moolenaar {"__index", luaV_list_index}, 8841dced572SBram Moolenaar {"__newindex", luaV_list_newindex}, 8851dced572SBram Moolenaar {"add", luaV_list_add}, 8861dced572SBram Moolenaar {"insert", luaV_list_insert}, 8871dced572SBram Moolenaar {NULL, NULL} 8881dced572SBram Moolenaar }; 8891dced572SBram Moolenaar 8901dced572SBram Moolenaar 8911dced572SBram Moolenaar /* ======= Dict type ======= */ 8921dced572SBram Moolenaar 8931dced572SBram Moolenaar static luaV_Dict * 8941dced572SBram Moolenaar luaV_newdict(lua_State *L, dict_T *dic) 8951dced572SBram Moolenaar { 8961dced572SBram Moolenaar luaV_Dict *d = (luaV_Dict *) lua_newuserdata(L, sizeof(luaV_Dict)); 8971dced572SBram Moolenaar *d = dic; 8981dced572SBram Moolenaar dic->dv_refcount++; /* reference in Lua */ 8991dced572SBram Moolenaar luaV_setudata(L, dic); /* cache[dic] = udata */ 9001dced572SBram Moolenaar luaV_getfield(L, LUAVIM_DICT); 9011dced572SBram Moolenaar lua_setmetatable(L, -2); 9021dced572SBram Moolenaar return d; 9031dced572SBram Moolenaar } 9041dced572SBram Moolenaar 9051dced572SBram Moolenaar luaV_pushtype(dict_T, dict, luaV_Dict) 9061dced572SBram Moolenaar luaV_type_tostring(dict, LUAVIM_DICT) 9071dced572SBram Moolenaar 9081dced572SBram Moolenaar static int 9091dced572SBram Moolenaar luaV_dict_len(lua_State *L) 9101dced572SBram Moolenaar { 9111dced572SBram Moolenaar dict_T *d = luaV_unbox(L, luaV_Dict, 1); 9121dced572SBram Moolenaar lua_pushinteger(L, (d == NULL) ? 0 : (int) d->dv_hashtab.ht_used); 9131dced572SBram Moolenaar return 1; 9141dced572SBram Moolenaar } 9151dced572SBram Moolenaar 9161dced572SBram Moolenaar static int 917feeaa688SBram Moolenaar luaV_dict_iter(lua_State *L UNUSED) 9181dced572SBram Moolenaar { 919feeaa688SBram Moolenaar #ifdef FEAT_EVAL 9201dced572SBram Moolenaar hashitem_T *hi = (hashitem_T *) lua_touserdata(L, lua_upvalueindex(2)); 9211dced572SBram Moolenaar int n = lua_tointeger(L, lua_upvalueindex(3)); 9221dced572SBram Moolenaar dictitem_T *di; 9231dced572SBram Moolenaar if (n <= 0) return 0; 9241dced572SBram Moolenaar while (HASHITEM_EMPTY(hi)) hi++; 9251dced572SBram Moolenaar di = dict_lookup(hi); 9261dced572SBram Moolenaar lua_pushstring(L, (char *) hi->hi_key); 9271dced572SBram Moolenaar luaV_pushtypval(L, &di->di_tv); 9281dced572SBram Moolenaar lua_pushlightuserdata(L, (void *) (hi + 1)); 9291dced572SBram Moolenaar lua_replace(L, lua_upvalueindex(2)); 9301dced572SBram Moolenaar lua_pushinteger(L, n - 1); 9311dced572SBram Moolenaar lua_replace(L, lua_upvalueindex(3)); 9321dced572SBram Moolenaar return 2; 933feeaa688SBram Moolenaar #else 934feeaa688SBram Moolenaar return 0; 935feeaa688SBram Moolenaar #endif 9361dced572SBram Moolenaar } 9371dced572SBram Moolenaar 9381dced572SBram Moolenaar static int 9391dced572SBram Moolenaar luaV_dict_call(lua_State *L) 9401dced572SBram Moolenaar { 9411dced572SBram Moolenaar dict_T *d = luaV_unbox(L, luaV_Dict, 1); 9421dced572SBram Moolenaar hashtab_T *ht = &d->dv_hashtab; 9431dced572SBram Moolenaar lua_pushvalue(L, lua_upvalueindex(1)); /* pass cache table along */ 9441dced572SBram Moolenaar lua_pushlightuserdata(L, (void *) ht->ht_array); 9451dced572SBram Moolenaar lua_pushinteger(L, ht->ht_used); /* # remaining items */ 9461dced572SBram Moolenaar lua_pushcclosure(L, luaV_dict_iter, 3); 9471dced572SBram Moolenaar return 1; 9481dced572SBram Moolenaar } 9491dced572SBram Moolenaar 9501dced572SBram Moolenaar static int 9511dced572SBram Moolenaar luaV_dict_index(lua_State *L) 9521dced572SBram Moolenaar { 9531dced572SBram Moolenaar dict_T *d = luaV_unbox(L, luaV_Dict, 1); 9541dced572SBram Moolenaar char_u *key = (char_u *) luaL_checkstring(L, 2); 9551dced572SBram Moolenaar dictitem_T *di = dict_find(d, key, -1); 956ca06da92SBram Moolenaar 9571dced572SBram Moolenaar if (di == NULL) 9581dced572SBram Moolenaar lua_pushnil(L); 9591dced572SBram Moolenaar else 960ca06da92SBram Moolenaar { 9611dced572SBram Moolenaar luaV_pushtypval(L, &di->di_tv); 962ca06da92SBram Moolenaar if (di->di_tv.v_type == VAR_FUNC) /* funcref? */ 963ca06da92SBram Moolenaar { 964ca06da92SBram Moolenaar luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, -1); 965ca06da92SBram Moolenaar f->self = d; /* keep "self" reference */ 966ca06da92SBram Moolenaar d->dv_refcount++; 967ca06da92SBram Moolenaar } 968ca06da92SBram Moolenaar } 9691dced572SBram Moolenaar return 1; 9701dced572SBram Moolenaar } 9711dced572SBram Moolenaar 9721dced572SBram Moolenaar static int 9731dced572SBram Moolenaar luaV_dict_newindex(lua_State *L) 9741dced572SBram Moolenaar { 9751dced572SBram Moolenaar dict_T *d = luaV_unbox(L, luaV_Dict, 1); 9761dced572SBram Moolenaar char_u *key = (char_u *) luaL_checkstring(L, 2); 9771dced572SBram Moolenaar dictitem_T *di; 978ca06da92SBram Moolenaar typval_T v; 979713bf9e9SBram Moolenaar 9801dced572SBram Moolenaar if (d->dv_lock) 9811dced572SBram Moolenaar luaL_error(L, "dict is locked"); 982d6ef5f9bSBram Moolenaar if (key == NULL) 983d6ef5f9bSBram Moolenaar return 0; 984d6ef5f9bSBram Moolenaar if (*key == NUL) 985ca06da92SBram Moolenaar luaL_error(L, "empty key"); 98617413671SBram Moolenaar if (!lua_isnil(L, 3)) /* read value? */ 98717413671SBram Moolenaar { 988ca06da92SBram Moolenaar luaV_checktypval(L, 3, &v, "setting dict item"); 989ca06da92SBram Moolenaar if (d->dv_scope == VAR_DEF_SCOPE && v.v_type == VAR_FUNC) 990ca06da92SBram Moolenaar luaL_error(L, "cannot assign funcref to builtin scope"); 991ca06da92SBram Moolenaar } 9921dced572SBram Moolenaar di = dict_find(d, key, -1); 9931dced572SBram Moolenaar if (di == NULL) /* non-existing key? */ 9941dced572SBram Moolenaar { 995d6ef5f9bSBram Moolenaar if (lua_isnil(L, 3)) 996d6ef5f9bSBram Moolenaar return 0; 9971dced572SBram Moolenaar di = dictitem_alloc(key); 998d6ef5f9bSBram Moolenaar if (di == NULL) 999d6ef5f9bSBram Moolenaar return 0; 10001dced572SBram Moolenaar if (dict_add(d, di) == FAIL) 10011dced572SBram Moolenaar { 10021dced572SBram Moolenaar vim_free(di); 10031dced572SBram Moolenaar return 0; 10041dced572SBram Moolenaar } 10051dced572SBram Moolenaar } 10061dced572SBram Moolenaar else 10071dced572SBram Moolenaar clear_tv(&di->di_tv); 10081dced572SBram Moolenaar if (lua_isnil(L, 3)) /* remove? */ 10091dced572SBram Moolenaar { 10101dced572SBram Moolenaar hashitem_T *hi = hash_find(&d->dv_hashtab, di->di_key); 10111dced572SBram Moolenaar hash_remove(&d->dv_hashtab, hi); 10121dced572SBram Moolenaar dictitem_free(di); 10131dced572SBram Moolenaar } 1014ca06da92SBram Moolenaar else 1015ca06da92SBram Moolenaar { 10161dced572SBram Moolenaar copy_tv(&v, &di->di_tv); 1017b376647bSBram Moolenaar clear_tv(&v); 10181dced572SBram Moolenaar } 10191dced572SBram Moolenaar return 0; 10201dced572SBram Moolenaar } 10211dced572SBram Moolenaar 10221dced572SBram Moolenaar static const luaL_Reg luaV_Dict_mt[] = { 10231dced572SBram Moolenaar {"__tostring", luaV_dict_tostring}, 10241dced572SBram Moolenaar {"__len", luaV_dict_len}, 10251dced572SBram Moolenaar {"__call", luaV_dict_call}, 10261dced572SBram Moolenaar {"__index", luaV_dict_index}, 10271dced572SBram Moolenaar {"__newindex", luaV_dict_newindex}, 10281dced572SBram Moolenaar {NULL, NULL} 10291dced572SBram Moolenaar }; 10301dced572SBram Moolenaar 10311dced572SBram Moolenaar 1032ca06da92SBram Moolenaar /* ======= Funcref type ======= */ 1033ca06da92SBram Moolenaar 1034ca06da92SBram Moolenaar static luaV_Funcref * 1035ca06da92SBram Moolenaar luaV_newfuncref(lua_State *L, char_u *name) 1036ca06da92SBram Moolenaar { 1037ca06da92SBram Moolenaar luaV_Funcref *f = (luaV_Funcref *)lua_newuserdata(L, sizeof(luaV_Funcref)); 1038ca06da92SBram Moolenaar 1039ca06da92SBram Moolenaar if (name != NULL) 1040ca06da92SBram Moolenaar { 1041*4eefe47eSBram Moolenaar func_ref(name); 1042*4eefe47eSBram Moolenaar f->name = vim_strsave(name); 1043ca06da92SBram Moolenaar } 1044ca06da92SBram Moolenaar f->self = NULL; 1045ca06da92SBram Moolenaar luaV_getfield(L, LUAVIM_FUNCREF); 1046ca06da92SBram Moolenaar lua_setmetatable(L, -2); 1047ca06da92SBram Moolenaar return f; 1048ca06da92SBram Moolenaar } 1049ca06da92SBram Moolenaar 1050ca06da92SBram Moolenaar static luaV_Funcref * 1051*4eefe47eSBram Moolenaar luaV_pushfuncref(lua_State *L, char_u *name) 1052ca06da92SBram Moolenaar { 1053*4eefe47eSBram Moolenaar return luaV_newfuncref(L, name); 1054ca06da92SBram Moolenaar } 1055ca06da92SBram Moolenaar 1056ca06da92SBram Moolenaar 1057ca06da92SBram Moolenaar luaV_type_tostring(funcref, LUAVIM_FUNCREF) 1058ca06da92SBram Moolenaar 1059ca06da92SBram Moolenaar static int 1060ca06da92SBram Moolenaar luaV_funcref_gc(lua_State *L) 1061ca06da92SBram Moolenaar { 1062ca06da92SBram Moolenaar luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1); 1063ca06da92SBram Moolenaar 1064*4eefe47eSBram Moolenaar func_unref(f->name); 1065*4eefe47eSBram Moolenaar vim_free(f->name); 1066*4eefe47eSBram Moolenaar // NOTE: Don't call "dict_unref(f->self)", because the dict of "f->self" 1067*4eefe47eSBram Moolenaar // will be (or has been already) freed by Vim's garbage collection. 1068ca06da92SBram Moolenaar return 0; 1069ca06da92SBram Moolenaar } 1070ca06da92SBram Moolenaar 1071ca06da92SBram Moolenaar /* equivalent to string(funcref) */ 1072ca06da92SBram Moolenaar static int 1073ca06da92SBram Moolenaar luaV_funcref_len(lua_State *L) 1074ca06da92SBram Moolenaar { 1075ca06da92SBram Moolenaar luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1); 1076ca06da92SBram Moolenaar 1077*4eefe47eSBram Moolenaar lua_pushstring(L, (const char *) f->name); 1078ca06da92SBram Moolenaar return 1; 1079ca06da92SBram Moolenaar } 1080ca06da92SBram Moolenaar 1081ca06da92SBram Moolenaar static int 1082ca06da92SBram Moolenaar luaV_funcref_call(lua_State *L) 1083ca06da92SBram Moolenaar { 1084ca06da92SBram Moolenaar luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1); 1085*4eefe47eSBram Moolenaar int i, n = lua_gettop(L) - 1; // #args 1086*4eefe47eSBram Moolenaar int status = FAIL; 1087*4eefe47eSBram Moolenaar typval_T args; 1088*4eefe47eSBram Moolenaar typval_T rettv; 1089ca06da92SBram Moolenaar 1090*4eefe47eSBram Moolenaar args.v_type = VAR_LIST; 1091*4eefe47eSBram Moolenaar args.vval.v_list = list_alloc(); 1092*4eefe47eSBram Moolenaar rettv.v_type = VAR_UNKNOWN; // as in clear_tv 1093*4eefe47eSBram Moolenaar if (args.vval.v_list != NULL) 1094d6ef5f9bSBram Moolenaar { 1095*4eefe47eSBram Moolenaar typval_T v; 1096*4eefe47eSBram Moolenaar 109717413671SBram Moolenaar for (i = 0; i < n; i++) 109817413671SBram Moolenaar { 1099ca06da92SBram Moolenaar luaV_checktypval(L, i + 2, &v, "calling funcref"); 1100*4eefe47eSBram Moolenaar list_append_tv(args.vval.v_list, &v); 1101713bf9e9SBram Moolenaar clear_tv(&v); 1102ca06da92SBram Moolenaar } 1103*4eefe47eSBram Moolenaar status = func_call(f->name, &args, NULL, f->self, &rettv); 1104ca06da92SBram Moolenaar if (status == OK) 1105ca06da92SBram Moolenaar luaV_pushtypval(L, &rettv); 1106*4eefe47eSBram Moolenaar clear_tv(&args); 1107ca06da92SBram Moolenaar clear_tv(&rettv); 1108d6ef5f9bSBram Moolenaar } 1109ca06da92SBram Moolenaar if (status != OK) 1110ca06da92SBram Moolenaar luaL_error(L, "cannot call funcref"); 1111ca06da92SBram Moolenaar return 1; 1112ca06da92SBram Moolenaar } 1113ca06da92SBram Moolenaar 1114ca06da92SBram Moolenaar static const luaL_Reg luaV_Funcref_mt[] = { 1115ca06da92SBram Moolenaar {"__tostring", luaV_funcref_tostring}, 1116ca06da92SBram Moolenaar {"__gc", luaV_funcref_gc}, 1117ca06da92SBram Moolenaar {"__len", luaV_funcref_len}, 1118ca06da92SBram Moolenaar {"__call", luaV_funcref_call}, 1119ca06da92SBram Moolenaar {NULL, NULL} 1120ca06da92SBram Moolenaar }; 1121ca06da92SBram Moolenaar 1122ca06da92SBram Moolenaar 11231dced572SBram Moolenaar /* ======= Buffer type ======= */ 11241dced572SBram Moolenaar 11251dced572SBram Moolenaar luaV_newtype(buf_T, buffer, luaV_Buffer, LUAVIM_BUFFER) 11261dced572SBram Moolenaar luaV_pushtype(buf_T, buffer, luaV_Buffer) 11271dced572SBram Moolenaar luaV_type_tostring(buffer, LUAVIM_BUFFER) 11281dced572SBram Moolenaar 11291dced572SBram Moolenaar static int 113055d5c034SBram Moolenaar luaV_buffer_len(lua_State *L) 113155d5c034SBram Moolenaar { 11321dced572SBram Moolenaar buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1); 11331dced572SBram Moolenaar lua_pushinteger(L, b->b_ml.ml_line_count); 11340ba04296SBram Moolenaar return 1; 11350ba04296SBram Moolenaar } 11360ba04296SBram Moolenaar 113755d5c034SBram Moolenaar static int 113855d5c034SBram Moolenaar luaV_buffer_call(lua_State *L) 113955d5c034SBram Moolenaar { 11401dced572SBram Moolenaar buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1); 11410ba04296SBram Moolenaar lua_settop(L, 1); 11421dced572SBram Moolenaar set_curbuf(b, DOBUF_SPLIT); 11430ba04296SBram Moolenaar return 1; 11440ba04296SBram Moolenaar } 11450ba04296SBram Moolenaar 114655d5c034SBram Moolenaar static int 114755d5c034SBram Moolenaar luaV_buffer_index(lua_State *L) 114855d5c034SBram Moolenaar { 11491dced572SBram Moolenaar buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1); 11500ba04296SBram Moolenaar linenr_T n = (linenr_T) lua_tointeger(L, 2); 11511dced572SBram Moolenaar if (n > 0 && n <= b->b_ml.ml_line_count) 11521dced572SBram Moolenaar luaV_pushline(L, b, n); 115355d5c034SBram Moolenaar else if (lua_isstring(L, 2)) 115455d5c034SBram Moolenaar { 11550ba04296SBram Moolenaar const char *s = lua_tostring(L, 2); 11560ba04296SBram Moolenaar if (strncmp(s, "name", 4) == 0) 1157fe08df45SBram Moolenaar lua_pushstring(L, (b->b_sfname == NULL) 1158fe08df45SBram Moolenaar ? "" : (char *) b->b_sfname); 11590ba04296SBram Moolenaar else if (strncmp(s, "fname", 5) == 0) 1160fe08df45SBram Moolenaar lua_pushstring(L, (b->b_ffname == NULL) 1161fe08df45SBram Moolenaar ? "" : (char *) b->b_ffname); 11620ba04296SBram Moolenaar else if (strncmp(s, "number", 6) == 0) 11631dced572SBram Moolenaar lua_pushinteger(L, b->b_fnum); 11640ba04296SBram Moolenaar /* methods */ 11650ba04296SBram Moolenaar else if (strncmp(s, "insert", 6) == 0 11660ba04296SBram Moolenaar || strncmp(s, "next", 4) == 0 11670ba04296SBram Moolenaar || strncmp(s, "previous", 8) == 0 116855d5c034SBram Moolenaar || strncmp(s, "isvalid", 7) == 0) 116955d5c034SBram Moolenaar { 11700ba04296SBram Moolenaar lua_getmetatable(L, 1); 11710ba04296SBram Moolenaar lua_getfield(L, -1, s); 11720ba04296SBram Moolenaar } 117355d5c034SBram Moolenaar else 117455d5c034SBram Moolenaar lua_pushnil(L); 11750ba04296SBram Moolenaar } 117655d5c034SBram Moolenaar else 117755d5c034SBram Moolenaar lua_pushnil(L); 11780ba04296SBram Moolenaar return 1; 11790ba04296SBram Moolenaar } 11800ba04296SBram Moolenaar 118155d5c034SBram Moolenaar static int 118255d5c034SBram Moolenaar luaV_buffer_newindex(lua_State *L) 118355d5c034SBram Moolenaar { 11841dced572SBram Moolenaar buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1); 11850ba04296SBram Moolenaar linenr_T n = (linenr_T) luaL_checkinteger(L, 2); 11860ba04296SBram Moolenaar #ifdef HAVE_SANDBOX 11870ba04296SBram Moolenaar luaV_checksandbox(L); 11880ba04296SBram Moolenaar #endif 11891dced572SBram Moolenaar if (n < 1 || n > b->b_ml.ml_line_count) 11900ba04296SBram Moolenaar luaL_error(L, "invalid line number"); 119155d5c034SBram Moolenaar if (lua_isnil(L, 3)) /* delete line */ 119255d5c034SBram Moolenaar { 11930ba04296SBram Moolenaar buf_T *buf = curbuf; 11941dced572SBram Moolenaar curbuf = b; 119555d5c034SBram Moolenaar if (u_savedel(n, 1L) == FAIL) 119655d5c034SBram Moolenaar { 11970ba04296SBram Moolenaar curbuf = buf; 11980ba04296SBram Moolenaar luaL_error(L, "cannot save undo information"); 11990ba04296SBram Moolenaar } 120055d5c034SBram Moolenaar else if (ml_delete(n, FALSE) == FAIL) 120155d5c034SBram Moolenaar { 12020ba04296SBram Moolenaar curbuf = buf; 12030ba04296SBram Moolenaar luaL_error(L, "cannot delete line"); 12040ba04296SBram Moolenaar } 1205ca06da92SBram Moolenaar else 1206ca06da92SBram Moolenaar { 12070ba04296SBram Moolenaar deleted_lines_mark(n, 1L); 12081dced572SBram Moolenaar if (b == curwin->w_buffer) /* fix cursor in current window? */ 120955d5c034SBram Moolenaar { 121055d5c034SBram Moolenaar if (curwin->w_cursor.lnum >= n) 121155d5c034SBram Moolenaar { 121255d5c034SBram Moolenaar if (curwin->w_cursor.lnum > n) 121355d5c034SBram Moolenaar { 12140ba04296SBram Moolenaar curwin->w_cursor.lnum -= 1; 12150ba04296SBram Moolenaar check_cursor_col(); 12160ba04296SBram Moolenaar } 12170ba04296SBram Moolenaar else check_cursor(); 12180ba04296SBram Moolenaar changed_cline_bef_curs(); 12190ba04296SBram Moolenaar } 12200ba04296SBram Moolenaar invalidate_botline(); 12210ba04296SBram Moolenaar } 12220ba04296SBram Moolenaar } 12230ba04296SBram Moolenaar curbuf = buf; 12240ba04296SBram Moolenaar } 122555d5c034SBram Moolenaar else if (lua_isstring(L, 3)) /* update line */ 122655d5c034SBram Moolenaar { 12270ba04296SBram Moolenaar buf_T *buf = curbuf; 12281dced572SBram Moolenaar curbuf = b; 122955d5c034SBram Moolenaar if (u_savesub(n) == FAIL) 123055d5c034SBram Moolenaar { 12310ba04296SBram Moolenaar curbuf = buf; 12320ba04296SBram Moolenaar luaL_error(L, "cannot save undo information"); 12330ba04296SBram Moolenaar } 123455d5c034SBram Moolenaar else if (ml_replace(n, luaV_toline(L, 3), TRUE) == FAIL) 123555d5c034SBram Moolenaar { 12360ba04296SBram Moolenaar curbuf = buf; 12370ba04296SBram Moolenaar luaL_error(L, "cannot replace line"); 12380ba04296SBram Moolenaar } 12390ba04296SBram Moolenaar else changed_bytes(n, 0); 12400ba04296SBram Moolenaar curbuf = buf; 12411dced572SBram Moolenaar if (b == curwin->w_buffer) 12420ba04296SBram Moolenaar check_cursor_col(); 12430ba04296SBram Moolenaar } 12440ba04296SBram Moolenaar else 12450ba04296SBram Moolenaar luaL_error(L, "wrong argument to change line"); 12460ba04296SBram Moolenaar return 0; 12470ba04296SBram Moolenaar } 12480ba04296SBram Moolenaar 124955d5c034SBram Moolenaar static int 125055d5c034SBram Moolenaar luaV_buffer_insert(lua_State *L) 125155d5c034SBram Moolenaar { 12521dced572SBram Moolenaar luaV_Buffer *lb = luaV_checkudata(L, 1, LUAVIM_BUFFER); 12531dced572SBram Moolenaar buf_T *b = (buf_T *) luaV_checkcache(L, (void *) *lb); 12541dced572SBram Moolenaar linenr_T last = b->b_ml.ml_line_count; 12550ba04296SBram Moolenaar linenr_T n = (linenr_T) luaL_optinteger(L, 3, last); 12560ba04296SBram Moolenaar buf_T *buf; 12570ba04296SBram Moolenaar luaL_checktype(L, 2, LUA_TSTRING); 12580ba04296SBram Moolenaar #ifdef HAVE_SANDBOX 12590ba04296SBram Moolenaar luaV_checksandbox(L); 12600ba04296SBram Moolenaar #endif 12610ba04296SBram Moolenaar /* fix insertion line */ 12620ba04296SBram Moolenaar if (n < 0) n = 0; 12630ba04296SBram Moolenaar if (n > last) n = last; 12640ba04296SBram Moolenaar /* insert */ 12650ba04296SBram Moolenaar buf = curbuf; 12661dced572SBram Moolenaar curbuf = b; 126755d5c034SBram Moolenaar if (u_save(n, n + 1) == FAIL) 126855d5c034SBram Moolenaar { 12690ba04296SBram Moolenaar curbuf = buf; 12700ba04296SBram Moolenaar luaL_error(L, "cannot save undo information"); 12710ba04296SBram Moolenaar } 127255d5c034SBram Moolenaar else if (ml_append(n, luaV_toline(L, 2), 0, FALSE) == FAIL) 127355d5c034SBram Moolenaar { 12740ba04296SBram Moolenaar curbuf = buf; 12750ba04296SBram Moolenaar luaL_error(L, "cannot insert line"); 12760ba04296SBram Moolenaar } 12770ba04296SBram Moolenaar else 12780ba04296SBram Moolenaar appended_lines_mark(n, 1L); 12790ba04296SBram Moolenaar curbuf = buf; 12800ba04296SBram Moolenaar update_screen(VALID); 12810ba04296SBram Moolenaar return 0; 12820ba04296SBram Moolenaar } 12830ba04296SBram Moolenaar 128455d5c034SBram Moolenaar static int 128555d5c034SBram Moolenaar luaV_buffer_next(lua_State *L) 128655d5c034SBram Moolenaar { 12870ba04296SBram Moolenaar luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); 12881dced572SBram Moolenaar buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b); 12891dced572SBram Moolenaar luaV_pushbuffer(L, buf->b_next); 12900ba04296SBram Moolenaar return 1; 12910ba04296SBram Moolenaar } 12920ba04296SBram Moolenaar 129355d5c034SBram Moolenaar static int 129455d5c034SBram Moolenaar luaV_buffer_previous(lua_State *L) 129555d5c034SBram Moolenaar { 12960ba04296SBram Moolenaar luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); 12971dced572SBram Moolenaar buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b); 12981dced572SBram Moolenaar luaV_pushbuffer(L, buf->b_prev); 12990ba04296SBram Moolenaar return 1; 13000ba04296SBram Moolenaar } 13010ba04296SBram Moolenaar 130255d5c034SBram Moolenaar static int 130355d5c034SBram Moolenaar luaV_buffer_isvalid(lua_State *L) 130455d5c034SBram Moolenaar { 13050ba04296SBram Moolenaar luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); 13061dced572SBram Moolenaar luaV_getudata(L, *b); 13070ba04296SBram Moolenaar lua_pushboolean(L, !lua_isnil(L, -1)); 13080ba04296SBram Moolenaar return 1; 13090ba04296SBram Moolenaar } 13100ba04296SBram Moolenaar 13110ba04296SBram Moolenaar static const luaL_Reg luaV_Buffer_mt[] = { 13120ba04296SBram Moolenaar {"__tostring", luaV_buffer_tostring}, 13130ba04296SBram Moolenaar {"__len", luaV_buffer_len}, 13140ba04296SBram Moolenaar {"__call", luaV_buffer_call}, 13150ba04296SBram Moolenaar {"__index", luaV_buffer_index}, 13160ba04296SBram Moolenaar {"__newindex", luaV_buffer_newindex}, 13170ba04296SBram Moolenaar {"insert", luaV_buffer_insert}, 13180ba04296SBram Moolenaar {"next", luaV_buffer_next}, 13190ba04296SBram Moolenaar {"previous", luaV_buffer_previous}, 13200ba04296SBram Moolenaar {"isvalid", luaV_buffer_isvalid}, 13210ba04296SBram Moolenaar {NULL, NULL} 13220ba04296SBram Moolenaar }; 13230ba04296SBram Moolenaar 13240ba04296SBram Moolenaar 13250ba04296SBram Moolenaar /* ======= Window type ======= */ 13260ba04296SBram Moolenaar 13271dced572SBram Moolenaar luaV_newtype(win_T, window, luaV_Window, LUAVIM_WINDOW) 13281dced572SBram Moolenaar luaV_pushtype(win_T, window, luaV_Window) 13291dced572SBram Moolenaar luaV_type_tostring(window, LUAVIM_WINDOW) 13300ba04296SBram Moolenaar 133155d5c034SBram Moolenaar static int 133255d5c034SBram Moolenaar luaV_window_call(lua_State *L) 133355d5c034SBram Moolenaar { 13341dced572SBram Moolenaar win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1); 13350ba04296SBram Moolenaar lua_settop(L, 1); 13361dced572SBram Moolenaar win_goto(w); 13370ba04296SBram Moolenaar return 1; 13380ba04296SBram Moolenaar } 13390ba04296SBram Moolenaar 134055d5c034SBram Moolenaar static int 134155d5c034SBram Moolenaar luaV_window_index(lua_State *L) 134255d5c034SBram Moolenaar { 13431dced572SBram Moolenaar win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1); 13440ba04296SBram Moolenaar const char *s = luaL_checkstring(L, 2); 13450ba04296SBram Moolenaar if (strncmp(s, "buffer", 6) == 0) 13461dced572SBram Moolenaar luaV_pushbuffer(L, w->w_buffer); 13470ba04296SBram Moolenaar else if (strncmp(s, "line", 4) == 0) 13481dced572SBram Moolenaar lua_pushinteger(L, w->w_cursor.lnum); 13490ba04296SBram Moolenaar else if (strncmp(s, "col", 3) == 0) 13501dced572SBram Moolenaar lua_pushinteger(L, w->w_cursor.col + 1); 13510ba04296SBram Moolenaar else if (strncmp(s, "width", 5) == 0) 13520263146bSBram Moolenaar lua_pushinteger(L, w->w_width); 13530ba04296SBram Moolenaar else if (strncmp(s, "height", 6) == 0) 13541dced572SBram Moolenaar lua_pushinteger(L, w->w_height); 13550ba04296SBram Moolenaar /* methods */ 13560ba04296SBram Moolenaar else if (strncmp(s, "next", 4) == 0 13570ba04296SBram Moolenaar || strncmp(s, "previous", 8) == 0 135855d5c034SBram Moolenaar || strncmp(s, "isvalid", 7) == 0) 135955d5c034SBram Moolenaar { 13600ba04296SBram Moolenaar lua_getmetatable(L, 1); 13610ba04296SBram Moolenaar lua_getfield(L, -1, s); 13620ba04296SBram Moolenaar } 13630ba04296SBram Moolenaar else 13640ba04296SBram Moolenaar lua_pushnil(L); 13650ba04296SBram Moolenaar return 1; 13660ba04296SBram Moolenaar } 13670ba04296SBram Moolenaar 136855d5c034SBram Moolenaar static int 136955d5c034SBram Moolenaar luaV_window_newindex(lua_State *L) 137055d5c034SBram Moolenaar { 13711dced572SBram Moolenaar win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1); 13720ba04296SBram Moolenaar const char *s = luaL_checkstring(L, 2); 13730ba04296SBram Moolenaar int v = luaL_checkinteger(L, 3); 137455d5c034SBram Moolenaar if (strncmp(s, "line", 4) == 0) 137555d5c034SBram Moolenaar { 13760ba04296SBram Moolenaar #ifdef HAVE_SANDBOX 13770ba04296SBram Moolenaar luaV_checksandbox(L); 13780ba04296SBram Moolenaar #endif 13791dced572SBram Moolenaar if (v < 1 || v > w->w_buffer->b_ml.ml_line_count) 13800ba04296SBram Moolenaar luaL_error(L, "line out of range"); 13811dced572SBram Moolenaar w->w_cursor.lnum = v; 13820ba04296SBram Moolenaar update_screen(VALID); 13830ba04296SBram Moolenaar } 138455d5c034SBram Moolenaar else if (strncmp(s, "col", 3) == 0) 138555d5c034SBram Moolenaar { 13860ba04296SBram Moolenaar #ifdef HAVE_SANDBOX 13870ba04296SBram Moolenaar luaV_checksandbox(L); 13880ba04296SBram Moolenaar #endif 13891dced572SBram Moolenaar w->w_cursor.col = v - 1; 139053901442SBram Moolenaar w->w_set_curswant = TRUE; 13910ba04296SBram Moolenaar update_screen(VALID); 13920ba04296SBram Moolenaar } 139355d5c034SBram Moolenaar else if (strncmp(s, "width", 5) == 0) 139455d5c034SBram Moolenaar { 13950ba04296SBram Moolenaar win_T *win = curwin; 13960ba04296SBram Moolenaar #ifdef FEAT_GUI 13970ba04296SBram Moolenaar need_mouse_correct = TRUE; 13980ba04296SBram Moolenaar #endif 13991dced572SBram Moolenaar curwin = w; 14000ba04296SBram Moolenaar win_setwidth(v); 14010ba04296SBram Moolenaar curwin = win; 14020ba04296SBram Moolenaar } 140355d5c034SBram Moolenaar else if (strncmp(s, "height", 6) == 0) 140455d5c034SBram Moolenaar { 14050ba04296SBram Moolenaar win_T *win = curwin; 14060ba04296SBram Moolenaar #ifdef FEAT_GUI 14070ba04296SBram Moolenaar need_mouse_correct = TRUE; 14080ba04296SBram Moolenaar #endif 14091dced572SBram Moolenaar curwin = w; 14100ba04296SBram Moolenaar win_setheight(v); 14110ba04296SBram Moolenaar curwin = win; 14120ba04296SBram Moolenaar } 14130ba04296SBram Moolenaar else 14140ba04296SBram Moolenaar luaL_error(L, "invalid window property: `%s'", s); 14150ba04296SBram Moolenaar return 0; 14160ba04296SBram Moolenaar } 14170ba04296SBram Moolenaar 141855d5c034SBram Moolenaar static int 141955d5c034SBram Moolenaar luaV_window_next(lua_State *L) 142055d5c034SBram Moolenaar { 14210ba04296SBram Moolenaar luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); 14221dced572SBram Moolenaar win_T *win = (win_T *) luaV_checkcache(L, (void *) *w); 14231dced572SBram Moolenaar luaV_pushwindow(L, win->w_next); 14240ba04296SBram Moolenaar return 1; 14250ba04296SBram Moolenaar } 14260ba04296SBram Moolenaar 142755d5c034SBram Moolenaar static int 142855d5c034SBram Moolenaar luaV_window_previous(lua_State *L) 142955d5c034SBram Moolenaar { 14300ba04296SBram Moolenaar luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); 14311dced572SBram Moolenaar win_T *win = (win_T *) luaV_checkcache(L, (void *) *w); 14321dced572SBram Moolenaar luaV_pushwindow(L, win->w_prev); 14330ba04296SBram Moolenaar return 1; 14340ba04296SBram Moolenaar } 14350ba04296SBram Moolenaar 143655d5c034SBram Moolenaar static int 143755d5c034SBram Moolenaar luaV_window_isvalid(lua_State *L) 143855d5c034SBram Moolenaar { 14390ba04296SBram Moolenaar luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); 14401dced572SBram Moolenaar luaV_getudata(L, *w); 14410ba04296SBram Moolenaar lua_pushboolean(L, !lua_isnil(L, -1)); 14420ba04296SBram Moolenaar return 1; 14430ba04296SBram Moolenaar } 14440ba04296SBram Moolenaar 14450ba04296SBram Moolenaar static const luaL_Reg luaV_Window_mt[] = { 14460ba04296SBram Moolenaar {"__tostring", luaV_window_tostring}, 14470ba04296SBram Moolenaar {"__call", luaV_window_call}, 14480ba04296SBram Moolenaar {"__index", luaV_window_index}, 14490ba04296SBram Moolenaar {"__newindex", luaV_window_newindex}, 14500ba04296SBram Moolenaar {"next", luaV_window_next}, 14510ba04296SBram Moolenaar {"previous", luaV_window_previous}, 14520ba04296SBram Moolenaar {"isvalid", luaV_window_isvalid}, 14530ba04296SBram Moolenaar {NULL, NULL} 14540ba04296SBram Moolenaar }; 14550ba04296SBram Moolenaar 14560ba04296SBram Moolenaar 14570ba04296SBram Moolenaar /* ======= Vim module ======= */ 14580ba04296SBram Moolenaar 145955d5c034SBram Moolenaar static int 146055d5c034SBram Moolenaar luaV_print(lua_State *L) 146155d5c034SBram Moolenaar { 14620ba04296SBram Moolenaar int i, n = lua_gettop(L); /* nargs */ 14630ba04296SBram Moolenaar const char *s; 14640ba04296SBram Moolenaar size_t l; 14650ba04296SBram Moolenaar luaL_Buffer b; 14660ba04296SBram Moolenaar luaL_buffinit(L, &b); 14670ba04296SBram Moolenaar lua_getglobal(L, "tostring"); 146855d5c034SBram Moolenaar for (i = 1; i <= n; i++) 146955d5c034SBram Moolenaar { 14700ba04296SBram Moolenaar lua_pushvalue(L, -1); /* tostring */ 14710ba04296SBram Moolenaar lua_pushvalue(L, i); /* arg */ 14720ba04296SBram Moolenaar lua_call(L, 1, 1); 14730ba04296SBram Moolenaar s = lua_tolstring(L, -1, &l); 14740ba04296SBram Moolenaar if (s == NULL) 14750ba04296SBram Moolenaar return luaL_error(L, "cannot convert to string"); 14760ba04296SBram Moolenaar if (i > 1) luaL_addchar(&b, ' '); /* use space instead of tab */ 14770ba04296SBram Moolenaar luaV_addlstring(&b, s, l, 0); 14780ba04296SBram Moolenaar lua_pop(L, 1); 14790ba04296SBram Moolenaar } 14800ba04296SBram Moolenaar luaL_pushresult(&b); 14810ba04296SBram Moolenaar luaV_msg(L); 14820ba04296SBram Moolenaar return 0; 14830ba04296SBram Moolenaar } 14840ba04296SBram Moolenaar 148555d5c034SBram Moolenaar static int 148638e2b063SBram Moolenaar luaV_debug(lua_State *L) 148738e2b063SBram Moolenaar { 148838e2b063SBram Moolenaar lua_settop(L, 0); 148938e2b063SBram Moolenaar lua_getglobal(L, "vim"); 149038e2b063SBram Moolenaar lua_getfield(L, -1, "eval"); 149138e2b063SBram Moolenaar lua_remove(L, -2); /* vim.eval at position 1 */ 149238e2b063SBram Moolenaar for (;;) 149338e2b063SBram Moolenaar { 149438e2b063SBram Moolenaar const char *input; 149538e2b063SBram Moolenaar size_t l; 149638e2b063SBram Moolenaar lua_pushvalue(L, 1); /* vim.eval */ 149738e2b063SBram Moolenaar lua_pushliteral(L, "input('lua_debug> ')"); 149838e2b063SBram Moolenaar lua_call(L, 1, 1); /* return string */ 149938e2b063SBram Moolenaar input = lua_tolstring(L, -1, &l); 150038e2b063SBram Moolenaar if (l == 0 || strcmp(input, "cont") == 0) 150138e2b063SBram Moolenaar return 0; 150238e2b063SBram Moolenaar msg_putchar('\n'); /* avoid outputting on input line */ 150338e2b063SBram Moolenaar if (luaL_loadbuffer(L, input, l, "=(debug command)") 150438e2b063SBram Moolenaar || lua_pcall(L, 0, 0, 0)) 150538e2b063SBram Moolenaar luaV_emsg(L); 150638e2b063SBram Moolenaar lua_settop(L, 1); /* remove eventual returns, but keep vim.eval */ 150738e2b063SBram Moolenaar } 150838e2b063SBram Moolenaar } 150938e2b063SBram Moolenaar 151038e2b063SBram Moolenaar static int 151155d5c034SBram Moolenaar luaV_command(lua_State *L) 151255d5c034SBram Moolenaar { 15130ba04296SBram Moolenaar do_cmdline_cmd((char_u *) luaL_checkstring(L, 1)); 15140ba04296SBram Moolenaar update_screen(VALID); 15150ba04296SBram Moolenaar return 0; 15160ba04296SBram Moolenaar } 15170ba04296SBram Moolenaar 151855d5c034SBram Moolenaar static int 151955d5c034SBram Moolenaar luaV_eval(lua_State *L) 152055d5c034SBram Moolenaar { 15210ba04296SBram Moolenaar typval_T *tv = eval_expr((char_u *) luaL_checkstring(L, 1), NULL); 15220ba04296SBram Moolenaar if (tv == NULL) luaL_error(L, "invalid expression"); 15230ba04296SBram Moolenaar luaV_pushtypval(L, tv); 1524b376647bSBram Moolenaar free_tv(tv); 15250ba04296SBram Moolenaar return 1; 15260ba04296SBram Moolenaar } 15270ba04296SBram Moolenaar 152855d5c034SBram Moolenaar static int 15290d2e4fceSBram Moolenaar luaV_beep(lua_State *L UNUSED) 153055d5c034SBram Moolenaar { 1531165bc69dSBram Moolenaar vim_beep(BO_LANG); 15320ba04296SBram Moolenaar return 0; 15330ba04296SBram Moolenaar } 15340ba04296SBram Moolenaar 153555d5c034SBram Moolenaar static int 153655d5c034SBram Moolenaar luaV_line(lua_State *L) 153755d5c034SBram Moolenaar { 15380ba04296SBram Moolenaar luaV_pushline(L, curbuf, curwin->w_cursor.lnum); 15390ba04296SBram Moolenaar return 1; 15400ba04296SBram Moolenaar } 15410ba04296SBram Moolenaar 154255d5c034SBram Moolenaar static int 15431dced572SBram Moolenaar luaV_list(lua_State *L) 15441dced572SBram Moolenaar { 1545ca06da92SBram Moolenaar list_T *l; 1546ca06da92SBram Moolenaar int initarg = !lua_isnoneornil(L, 1); 1547ca06da92SBram Moolenaar 1548ca06da92SBram Moolenaar if (initarg && lua_type(L, 1) != LUA_TTABLE) 1549ca06da92SBram Moolenaar luaL_error(L, "table expected, got %s", luaL_typename(L, 1)); 1550ca06da92SBram Moolenaar l = list_alloc(); 15511dced572SBram Moolenaar if (l == NULL) 15521dced572SBram Moolenaar lua_pushnil(L); 15531dced572SBram Moolenaar else 1554ca06da92SBram Moolenaar { 15551dced572SBram Moolenaar luaV_newlist(L, l); 155617413671SBram Moolenaar if (initarg) /* traverse table to init list */ 155717413671SBram Moolenaar { 1558ca06da92SBram Moolenaar int notnil, i = 0; 1559ca06da92SBram Moolenaar typval_T v; 156017413671SBram Moolenaar do 156117413671SBram Moolenaar { 1562ca06da92SBram Moolenaar lua_rawgeti(L, 1, ++i); 1563ca06da92SBram Moolenaar notnil = !lua_isnil(L, -1); 156417413671SBram Moolenaar if (notnil) 156517413671SBram Moolenaar { 1566ca06da92SBram Moolenaar luaV_checktypval(L, -1, &v, "vim.list"); 1567ca06da92SBram Moolenaar list_append_tv(l, &v); 1568713bf9e9SBram Moolenaar clear_tv(&v); 1569ca06da92SBram Moolenaar } 1570ca06da92SBram Moolenaar lua_pop(L, 1); /* value */ 1571ca06da92SBram Moolenaar } while (notnil); 1572ca06da92SBram Moolenaar } 1573ca06da92SBram Moolenaar } 15741dced572SBram Moolenaar return 1; 15751dced572SBram Moolenaar } 15761dced572SBram Moolenaar 15771dced572SBram Moolenaar static int 15781dced572SBram Moolenaar luaV_dict(lua_State *L) 15791dced572SBram Moolenaar { 1580ca06da92SBram Moolenaar dict_T *d; 1581ca06da92SBram Moolenaar int initarg = !lua_isnoneornil(L, 1); 1582ca06da92SBram Moolenaar 1583ca06da92SBram Moolenaar if (initarg && lua_type(L, 1) != LUA_TTABLE) 1584ca06da92SBram Moolenaar luaL_error(L, "table expected, got %s", luaL_typename(L, 1)); 1585ca06da92SBram Moolenaar d = dict_alloc(); 15861dced572SBram Moolenaar if (d == NULL) 15871dced572SBram Moolenaar lua_pushnil(L); 15881dced572SBram Moolenaar else 1589ca06da92SBram Moolenaar { 15901dced572SBram Moolenaar luaV_newdict(L, d); 1591ca06da92SBram Moolenaar if (initarg) /* traverse table to init dict */ 1592ca06da92SBram Moolenaar { 1593ca06da92SBram Moolenaar lua_pushnil(L); 1594ca06da92SBram Moolenaar while (lua_next(L, 1)) 1595ca06da92SBram Moolenaar { 1596ca06da92SBram Moolenaar char_u *key; 1597ca06da92SBram Moolenaar dictitem_T *di; 1598ca06da92SBram Moolenaar typval_T v; 1599d6ef5f9bSBram Moolenaar 1600ca06da92SBram Moolenaar lua_pushvalue(L, -2); /* dup key in case it's a number */ 1601ca06da92SBram Moolenaar key = (char_u *) lua_tostring(L, -1); 1602d6ef5f9bSBram Moolenaar if (key == NULL) 1603d6ef5f9bSBram Moolenaar { 1604d6ef5f9bSBram Moolenaar lua_pushnil(L); 1605d6ef5f9bSBram Moolenaar return 1; 1606d6ef5f9bSBram Moolenaar } 1607d6ef5f9bSBram Moolenaar if (*key == NUL) 1608ca06da92SBram Moolenaar luaL_error(L, "table has empty key"); 1609ca06da92SBram Moolenaar luaV_checktypval(L, -2, &v, "vim.dict"); /* value */ 1610ca06da92SBram Moolenaar di = dictitem_alloc(key); 1611d6ef5f9bSBram Moolenaar if (di == NULL || dict_add(d, di) == FAIL) 1612d6ef5f9bSBram Moolenaar { 1613ca06da92SBram Moolenaar vim_free(di); 1614ca06da92SBram Moolenaar lua_pushnil(L); 1615ca06da92SBram Moolenaar return 1; 1616ca06da92SBram Moolenaar } 1617ca06da92SBram Moolenaar copy_tv(&v, &di->di_tv); 1618ca06da92SBram Moolenaar clear_tv(&v); 1619ca06da92SBram Moolenaar lua_pop(L, 2); /* key copy and value */ 1620ca06da92SBram Moolenaar } 1621ca06da92SBram Moolenaar } 1622ca06da92SBram Moolenaar } 1623ca06da92SBram Moolenaar return 1; 1624ca06da92SBram Moolenaar } 1625ca06da92SBram Moolenaar 1626ca06da92SBram Moolenaar static int 1627ca06da92SBram Moolenaar luaV_funcref(lua_State *L) 1628ca06da92SBram Moolenaar { 1629ca06da92SBram Moolenaar const char *name = luaL_checkstring(L, 1); 1630ca06da92SBram Moolenaar /* note: not checking if function exists (needs function_exists) */ 1631ca06da92SBram Moolenaar if (name == NULL || *name == NUL || VIM_ISDIGIT(*name)) 1632ca06da92SBram Moolenaar luaL_error(L, "invalid function name: %s", name); 1633ca06da92SBram Moolenaar luaV_newfuncref(L, (char_u *) name); 16341dced572SBram Moolenaar return 1; 16351dced572SBram Moolenaar } 16361dced572SBram Moolenaar 16371dced572SBram Moolenaar static int 163855d5c034SBram Moolenaar luaV_buffer(lua_State *L) 163955d5c034SBram Moolenaar { 16400ba04296SBram Moolenaar buf_T *buf; 164155d5c034SBram Moolenaar if (lua_isstring(L, 1)) /* get by number or name? */ 164255d5c034SBram Moolenaar { 164355d5c034SBram Moolenaar if (lua_isnumber(L, 1)) /* by number? */ 164455d5c034SBram Moolenaar { 16450ba04296SBram Moolenaar int n = lua_tointeger(L, 1); 164629323590SBram Moolenaar FOR_ALL_BUFFERS(buf) 16470ba04296SBram Moolenaar if (buf->b_fnum == n) break; 16480ba04296SBram Moolenaar } 1649ca06da92SBram Moolenaar else // by name 1650ca06da92SBram Moolenaar { 16510ba04296SBram Moolenaar size_t l; 16520ba04296SBram Moolenaar const char *s = lua_tolstring(L, 1, &l); 165329323590SBram Moolenaar FOR_ALL_BUFFERS(buf) 165455d5c034SBram Moolenaar { 165555d5c034SBram Moolenaar if (buf->b_ffname == NULL || buf->b_sfname == NULL) 165655d5c034SBram Moolenaar { 16570ba04296SBram Moolenaar if (l == 0) break; 16580ba04296SBram Moolenaar } 16590d2e4fceSBram Moolenaar else if (strncmp(s, (char *)buf->b_ffname, l) == 0 16600d2e4fceSBram Moolenaar || strncmp(s, (char *)buf->b_sfname, l) == 0) 16610ba04296SBram Moolenaar break; 16620ba04296SBram Moolenaar } 16630ba04296SBram Moolenaar } 16640ba04296SBram Moolenaar } 16651dced572SBram Moolenaar else 16660ba04296SBram Moolenaar buf = (lua_toboolean(L, 1)) ? firstbuf : curbuf; /* first buffer? */ 16670ba04296SBram Moolenaar luaV_pushbuffer(L, buf); 16680ba04296SBram Moolenaar return 1; 16690ba04296SBram Moolenaar } 16700ba04296SBram Moolenaar 167155d5c034SBram Moolenaar static int 167255d5c034SBram Moolenaar luaV_window(lua_State *L) 167355d5c034SBram Moolenaar { 16740ba04296SBram Moolenaar win_T *win; 167555d5c034SBram Moolenaar if (lua_isnumber(L, 1)) /* get by number? */ 167655d5c034SBram Moolenaar { 16770ba04296SBram Moolenaar int n = lua_tointeger(L, 1); 16780ba04296SBram Moolenaar for (win = firstwin; win != NULL; win = win->w_next, n--) 16790ba04296SBram Moolenaar if (n == 1) break; 16800ba04296SBram Moolenaar } 16811dced572SBram Moolenaar else 16820ba04296SBram Moolenaar win = (lua_toboolean(L, 1)) ? firstwin : curwin; /* first window? */ 16830ba04296SBram Moolenaar luaV_pushwindow(L, win); 16840ba04296SBram Moolenaar return 1; 16850ba04296SBram Moolenaar } 16860ba04296SBram Moolenaar 168755d5c034SBram Moolenaar static int 168855d5c034SBram Moolenaar luaV_open(lua_State *L) 168955d5c034SBram Moolenaar { 16900ba04296SBram Moolenaar char_u *s = NULL; 16910ba04296SBram Moolenaar #ifdef HAVE_SANDBOX 16920ba04296SBram Moolenaar luaV_checksandbox(L); 16930ba04296SBram Moolenaar #endif 16940ba04296SBram Moolenaar if (lua_isstring(L, 1)) s = (char_u *) lua_tostring(L, 1); 1695fa263a51SBram Moolenaar luaV_pushbuffer(L, buflist_new(s, NULL, 1L, BLN_LISTED)); 16960ba04296SBram Moolenaar return 1; 16970ba04296SBram Moolenaar } 16980ba04296SBram Moolenaar 169955d5c034SBram Moolenaar static int 17001dced572SBram Moolenaar luaV_type(lua_State *L) 170155d5c034SBram Moolenaar { 17021dced572SBram Moolenaar luaL_checkany(L, 1); 17031dced572SBram Moolenaar if (lua_type(L, 1) == LUA_TUSERDATA) /* check vim udata? */ 17041dced572SBram Moolenaar { 17051dced572SBram Moolenaar lua_settop(L, 1); 17061dced572SBram Moolenaar if (lua_getmetatable(L, 1)) 17071dced572SBram Moolenaar { 17081dced572SBram Moolenaar luaV_getfield(L, LUAVIM_LIST); 17091dced572SBram Moolenaar if (lua_rawequal(L, -1, 2)) 17101dced572SBram Moolenaar { 17111dced572SBram Moolenaar lua_pushstring(L, "list"); 17120ba04296SBram Moolenaar return 1; 17130ba04296SBram Moolenaar } 17141dced572SBram Moolenaar luaV_getfield(L, LUAVIM_DICT); 17151dced572SBram Moolenaar if (lua_rawequal(L, -1, 2)) 171655d5c034SBram Moolenaar { 17171dced572SBram Moolenaar lua_pushstring(L, "dict"); 17180ba04296SBram Moolenaar return 1; 17190ba04296SBram Moolenaar } 1720ca06da92SBram Moolenaar luaV_getfield(L, LUAVIM_FUNCREF); 1721ca06da92SBram Moolenaar if (lua_rawequal(L, -1, 2)) 1722ca06da92SBram Moolenaar { 1723ca06da92SBram Moolenaar lua_pushstring(L, "funcref"); 1724ca06da92SBram Moolenaar return 1; 1725ca06da92SBram Moolenaar } 17261dced572SBram Moolenaar luaV_getfield(L, LUAVIM_BUFFER); 17271dced572SBram Moolenaar if (lua_rawequal(L, -1, 2)) 172855d5c034SBram Moolenaar { 17291dced572SBram Moolenaar lua_pushstring(L, "buffer"); 17301dced572SBram Moolenaar return 1; 17310ba04296SBram Moolenaar } 17321dced572SBram Moolenaar luaV_getfield(L, LUAVIM_WINDOW); 17331dced572SBram Moolenaar if (lua_rawequal(L, -1, 2)) 17341dced572SBram Moolenaar { 17351dced572SBram Moolenaar lua_pushstring(L, "window"); 17361dced572SBram Moolenaar return 1; 17371dced572SBram Moolenaar } 17381dced572SBram Moolenaar } 17391dced572SBram Moolenaar } 17401dced572SBram Moolenaar lua_pushstring(L, luaL_typename(L, 1)); /* fallback */ 17411dced572SBram Moolenaar return 1; 17420ba04296SBram Moolenaar } 17430ba04296SBram Moolenaar 17440ba04296SBram Moolenaar static const luaL_Reg luaV_module[] = { 17450ba04296SBram Moolenaar {"command", luaV_command}, 17460ba04296SBram Moolenaar {"eval", luaV_eval}, 17470ba04296SBram Moolenaar {"beep", luaV_beep}, 17480ba04296SBram Moolenaar {"line", luaV_line}, 17491dced572SBram Moolenaar {"list", luaV_list}, 17501dced572SBram Moolenaar {"dict", luaV_dict}, 1751ca06da92SBram Moolenaar {"funcref", luaV_funcref}, 17520ba04296SBram Moolenaar {"buffer", luaV_buffer}, 17530ba04296SBram Moolenaar {"window", luaV_window}, 17540ba04296SBram Moolenaar {"open", luaV_open}, 17551dced572SBram Moolenaar {"type", luaV_type}, 17560ba04296SBram Moolenaar {NULL, NULL} 17570ba04296SBram Moolenaar }; 17580ba04296SBram Moolenaar 17591dced572SBram Moolenaar /* for freeing list, dict, buffer and window objects; lightuserdata as arg */ 17601dced572SBram Moolenaar static int 17611dced572SBram Moolenaar luaV_free(lua_State *L) 17621dced572SBram Moolenaar { 17631dced572SBram Moolenaar lua_pushnil(L); 17641dced572SBram Moolenaar luaV_setudata(L, lua_touserdata(L, 1)); 17651dced572SBram Moolenaar return 0; 17661dced572SBram Moolenaar } 17671dced572SBram Moolenaar 17681dced572SBram Moolenaar static int 17691dced572SBram Moolenaar luaV_luaeval(lua_State *L) 17701dced572SBram Moolenaar { 17711dced572SBram Moolenaar luaL_Buffer b; 17721dced572SBram Moolenaar size_t l; 17731dced572SBram Moolenaar const char *str = lua_tolstring(L, 1, &l); 17741dced572SBram Moolenaar typval_T *arg = (typval_T *) lua_touserdata(L, 2); 17751dced572SBram Moolenaar typval_T *rettv = (typval_T *) lua_touserdata(L, 3); 17761dced572SBram Moolenaar luaL_buffinit(L, &b); 17771dced572SBram Moolenaar luaL_addlstring(&b, LUAVIM_EVALHEADER, sizeof(LUAVIM_EVALHEADER) - 1); 17781dced572SBram Moolenaar luaL_addlstring(&b, str, l); 17791dced572SBram Moolenaar luaL_pushresult(&b); 17801dced572SBram Moolenaar str = lua_tolstring(L, -1, &l); 17811dced572SBram Moolenaar if (luaL_loadbuffer(L, str, l, LUAVIM_EVALNAME)) /* compile error? */ 17821dced572SBram Moolenaar { 17831dced572SBram Moolenaar luaV_emsg(L); 17841dced572SBram Moolenaar return 0; 17851dced572SBram Moolenaar } 17861dced572SBram Moolenaar luaV_pushtypval(L, arg); 17871dced572SBram Moolenaar if (lua_pcall(L, 1, 1, 0)) /* running error? */ 17881dced572SBram Moolenaar { 17891dced572SBram Moolenaar luaV_emsg(L); 17901dced572SBram Moolenaar return 0; 17911dced572SBram Moolenaar } 1792ca06da92SBram Moolenaar if (luaV_totypval(L, -1, rettv) == FAIL) 1793f9e3e09fSBram Moolenaar emsg("luaeval: cannot convert value"); 1794f554a328SBram Moolenaar return 0; 17951dced572SBram Moolenaar } 17961dced572SBram Moolenaar 17971dced572SBram Moolenaar static int 17981dced572SBram Moolenaar luaV_setref(lua_State *L) 17991dced572SBram Moolenaar { 18001dced572SBram Moolenaar int copyID = lua_tointeger(L, 1); 18012459a5ecSBram Moolenaar int abort = FALSE; 18022459a5ecSBram Moolenaar 18031dced572SBram Moolenaar luaV_getfield(L, LUAVIM_LIST); 18041dced572SBram Moolenaar luaV_getfield(L, LUAVIM_DICT); 1805*4eefe47eSBram Moolenaar luaV_getfield(L, LUAVIM_FUNCREF); 18061dced572SBram Moolenaar lua_pushnil(L); 1807*4eefe47eSBram Moolenaar // traverse cache table 1808b84634deSBram Moolenaar while (!abort && lua_next(L, lua_upvalueindex(1)) != 0) 18091dced572SBram Moolenaar { 18101dced572SBram Moolenaar lua_getmetatable(L, -1); 1811*4eefe47eSBram Moolenaar if (lua_rawequal(L, -1, 2)) // list? 18121dced572SBram Moolenaar { 1813*4eefe47eSBram Moolenaar list_T *l = (list_T *)lua_touserdata(L, 5); // key 1814*4eefe47eSBram Moolenaar 1815*4eefe47eSBram Moolenaar if (l->lv_copyID != copyID) 18161dced572SBram Moolenaar { 1817*4eefe47eSBram Moolenaar l->lv_copyID = copyID; 1818*4eefe47eSBram Moolenaar abort = set_ref_in_list(l, copyID, NULL); 18191dced572SBram Moolenaar } 1820*4eefe47eSBram Moolenaar } 1821*4eefe47eSBram Moolenaar else if (lua_rawequal(L, -1, 3)) // dict? 1822*4eefe47eSBram Moolenaar { 1823*4eefe47eSBram Moolenaar dict_T *d = (dict_T *)lua_touserdata(L, 5); // key 1824*4eefe47eSBram Moolenaar 1825*4eefe47eSBram Moolenaar if (d->dv_copyID != copyID) 1826*4eefe47eSBram Moolenaar { 1827*4eefe47eSBram Moolenaar d->dv_copyID = copyID; 1828*4eefe47eSBram Moolenaar abort = set_ref_in_ht(&d->dv_hashtab, copyID, NULL); 1829*4eefe47eSBram Moolenaar } 1830*4eefe47eSBram Moolenaar } 1831*4eefe47eSBram Moolenaar else if (lua_rawequal(L, -1, 4)) // funcref? 1832*4eefe47eSBram Moolenaar { 1833*4eefe47eSBram Moolenaar luaV_Funcref *f = (luaV_Funcref *)lua_touserdata(L, 5); // key 1834*4eefe47eSBram Moolenaar 1835*4eefe47eSBram Moolenaar if (f->self != NULL && f->self->dv_copyID != copyID) 1836*4eefe47eSBram Moolenaar { 1837*4eefe47eSBram Moolenaar f->self->dv_copyID = copyID; 1838*4eefe47eSBram Moolenaar abort = set_ref_in_ht(&f->self->dv_hashtab, copyID, NULL); 1839*4eefe47eSBram Moolenaar } 1840*4eefe47eSBram Moolenaar } 1841*4eefe47eSBram Moolenaar lua_pop(L, 2); // metatable and value 18421dced572SBram Moolenaar } 18432459a5ecSBram Moolenaar lua_pushinteger(L, abort); 1844f554a328SBram Moolenaar return 1; 18451dced572SBram Moolenaar } 18461dced572SBram Moolenaar 184755d5c034SBram Moolenaar static int 184855d5c034SBram Moolenaar luaopen_vim(lua_State *L) 184955d5c034SBram Moolenaar { 18501dced572SBram Moolenaar /* set cache table */ 18510ba04296SBram Moolenaar lua_newtable(L); 18520ba04296SBram Moolenaar lua_newtable(L); 18531dced572SBram Moolenaar lua_pushstring(L, "v"); 18540ba04296SBram Moolenaar lua_setfield(L, -2, "__mode"); 18551dced572SBram Moolenaar lua_setmetatable(L, -2); /* cache is weak-valued */ 18560ba04296SBram Moolenaar /* print */ 18570ba04296SBram Moolenaar lua_pushcfunction(L, luaV_print); 18580ba04296SBram Moolenaar lua_setglobal(L, "print"); 185938e2b063SBram Moolenaar /* debug.debug */ 186038e2b063SBram Moolenaar lua_getglobal(L, "debug"); 186138e2b063SBram Moolenaar lua_pushcfunction(L, luaV_debug); 186238e2b063SBram Moolenaar lua_setfield(L, -2, "debug"); 186338e2b063SBram Moolenaar lua_pop(L, 1); 18640ba04296SBram Moolenaar /* free */ 18650ba04296SBram Moolenaar lua_pushlightuserdata(L, (void *) LUAVIM_FREE); 18661dced572SBram Moolenaar lua_pushvalue(L, 1); /* cache table */ 18671dced572SBram Moolenaar lua_pushcclosure(L, luaV_free, 1); 18681dced572SBram Moolenaar lua_rawset(L, LUA_REGISTRYINDEX); 18691dced572SBram Moolenaar /* luaeval */ 18701dced572SBram Moolenaar lua_pushlightuserdata(L, (void *) LUAVIM_LUAEVAL); 18711dced572SBram Moolenaar lua_pushvalue(L, 1); /* cache table */ 18721dced572SBram Moolenaar lua_pushcclosure(L, luaV_luaeval, 1); 18731dced572SBram Moolenaar lua_rawset(L, LUA_REGISTRYINDEX); 18741dced572SBram Moolenaar /* setref */ 18751dced572SBram Moolenaar lua_pushlightuserdata(L, (void *) LUAVIM_SETREF); 18761dced572SBram Moolenaar lua_pushvalue(L, 1); /* cache table */ 18771dced572SBram Moolenaar lua_pushcclosure(L, luaV_setref, 1); 18780ba04296SBram Moolenaar lua_rawset(L, LUA_REGISTRYINDEX); 18790ba04296SBram Moolenaar /* register */ 18801dced572SBram Moolenaar luaV_newmetatable(L, LUAVIM_LIST); 18811dced572SBram Moolenaar lua_pushvalue(L, 1); 18821dced572SBram Moolenaar luaV_openlib(L, luaV_List_mt, 1); 18831dced572SBram Moolenaar luaV_newmetatable(L, LUAVIM_DICT); 18841dced572SBram Moolenaar lua_pushvalue(L, 1); 18851dced572SBram Moolenaar luaV_openlib(L, luaV_Dict_mt, 1); 1886ca06da92SBram Moolenaar luaV_newmetatable(L, LUAVIM_FUNCREF); 1887ca06da92SBram Moolenaar lua_pushvalue(L, 1); 1888ca06da92SBram Moolenaar luaV_openlib(L, luaV_Funcref_mt, 1); 18890ba04296SBram Moolenaar luaV_newmetatable(L, LUAVIM_BUFFER); 18901dced572SBram Moolenaar lua_pushvalue(L, 1); /* cache table */ 18911dced572SBram Moolenaar luaV_openlib(L, luaV_Buffer_mt, 1); 18920ba04296SBram Moolenaar luaV_newmetatable(L, LUAVIM_WINDOW); 18931dced572SBram Moolenaar lua_pushvalue(L, 1); /* cache table */ 18941dced572SBram Moolenaar luaV_openlib(L, luaV_Window_mt, 1); 18951dced572SBram Moolenaar lua_newtable(L); /* vim table */ 18961dced572SBram Moolenaar lua_pushvalue(L, 1); /* cache table */ 18971dced572SBram Moolenaar luaV_openlib(L, luaV_module, 1); 18981dced572SBram Moolenaar lua_setglobal(L, LUAVIM_NAME); 18990ba04296SBram Moolenaar return 0; 19000ba04296SBram Moolenaar } 19010ba04296SBram Moolenaar 190255d5c034SBram Moolenaar static lua_State * 190355d5c034SBram Moolenaar luaV_newstate(void) 190455d5c034SBram Moolenaar { 19050ba04296SBram Moolenaar lua_State *L = luaL_newstate(); 190616c98f9cSBram Moolenaar luaL_openlibs(L); /* core libs */ 190716c98f9cSBram Moolenaar lua_pushcfunction(L, luaopen_vim); /* vim */ 19080ba04296SBram Moolenaar lua_call(L, 0, 0); 19090ba04296SBram Moolenaar return L; 19100ba04296SBram Moolenaar } 19110ba04296SBram Moolenaar 191255d5c034SBram Moolenaar static void 191355d5c034SBram Moolenaar luaV_setrange(lua_State *L, int line1, int line2) 191455d5c034SBram Moolenaar { 19150ba04296SBram Moolenaar lua_getglobal(L, LUAVIM_NAME); 19160ba04296SBram Moolenaar lua_pushinteger(L, line1); 19170ba04296SBram Moolenaar lua_setfield(L, -2, "firstline"); 19180ba04296SBram Moolenaar lua_pushinteger(L, line2); 19190ba04296SBram Moolenaar lua_setfield(L, -2, "lastline"); 19200ba04296SBram Moolenaar lua_pop(L, 1); /* vim table */ 19210ba04296SBram Moolenaar } 19220ba04296SBram Moolenaar 19230ba04296SBram Moolenaar 19240ba04296SBram Moolenaar /* ======= Interface ======= */ 19250ba04296SBram Moolenaar 19260ba04296SBram Moolenaar static lua_State *L = NULL; 19270ba04296SBram Moolenaar 192855d5c034SBram Moolenaar static int 19291dced572SBram Moolenaar lua_isopen(void) 19302bd6a1b5SBram Moolenaar { 19312bd6a1b5SBram Moolenaar return L != NULL; 19322bd6a1b5SBram Moolenaar } 19332bd6a1b5SBram Moolenaar 19342bd6a1b5SBram Moolenaar static int 193555d5c034SBram Moolenaar lua_init(void) 193655d5c034SBram Moolenaar { 19371dced572SBram Moolenaar if (!lua_isopen()) 193855d5c034SBram Moolenaar { 19390ba04296SBram Moolenaar #ifdef DYNAMIC_LUA 194055d5c034SBram Moolenaar if (!lua_enabled(TRUE)) 194155d5c034SBram Moolenaar { 1942f9e3e09fSBram Moolenaar emsg(_("Lua library cannot be loaded.")); 19430ba04296SBram Moolenaar return FAIL; 19440ba04296SBram Moolenaar } 19450ba04296SBram Moolenaar #endif 19460ba04296SBram Moolenaar L = luaV_newstate(); 19470ba04296SBram Moolenaar } 19480ba04296SBram Moolenaar return OK; 19490ba04296SBram Moolenaar } 19500ba04296SBram Moolenaar 195155d5c034SBram Moolenaar void 195255d5c034SBram Moolenaar lua_end(void) 195355d5c034SBram Moolenaar { 19541dced572SBram Moolenaar if (lua_isopen()) 195555d5c034SBram Moolenaar { 19560ba04296SBram Moolenaar lua_close(L); 19570ba04296SBram Moolenaar L = NULL; 19580ba04296SBram Moolenaar #ifdef DYNAMIC_LUA 19590ba04296SBram Moolenaar end_dynamic_lua(); 19600ba04296SBram Moolenaar #endif 19610ba04296SBram Moolenaar } 19620ba04296SBram Moolenaar } 19630ba04296SBram Moolenaar 19640ba04296SBram Moolenaar /* ex commands */ 196555d5c034SBram Moolenaar void 196655d5c034SBram Moolenaar ex_lua(exarg_T *eap) 196755d5c034SBram Moolenaar { 19680ba04296SBram Moolenaar char *script; 19690ba04296SBram Moolenaar if (lua_init() == FAIL) return; 19700ba04296SBram Moolenaar script = (char *) script_get(eap, eap->arg); 197155d5c034SBram Moolenaar if (!eap->skip) 197255d5c034SBram Moolenaar { 19730ba04296SBram Moolenaar char *s = (script) ? script : (char *) eap->arg; 19740ba04296SBram Moolenaar luaV_setrange(L, eap->line1, eap->line2); 19750ba04296SBram Moolenaar if (luaL_loadbuffer(L, s, strlen(s), LUAVIM_CHUNKNAME) 19760ba04296SBram Moolenaar || lua_pcall(L, 0, 0, 0)) 19770ba04296SBram Moolenaar luaV_emsg(L); 19780ba04296SBram Moolenaar } 19790ba04296SBram Moolenaar if (script != NULL) vim_free(script); 19800ba04296SBram Moolenaar } 19810ba04296SBram Moolenaar 198255d5c034SBram Moolenaar void 198355d5c034SBram Moolenaar ex_luado(exarg_T *eap) 198455d5c034SBram Moolenaar { 19850ba04296SBram Moolenaar linenr_T l; 19860ba04296SBram Moolenaar const char *s = (const char *) eap->arg; 19870ba04296SBram Moolenaar luaL_Buffer b; 19880ba04296SBram Moolenaar size_t len; 1989d58f03b1SBram Moolenaar buf_T *was_curbuf = curbuf; 1990d58f03b1SBram Moolenaar 19910ba04296SBram Moolenaar if (lua_init() == FAIL) return; 199255d5c034SBram Moolenaar if (u_save(eap->line1 - 1, eap->line2 + 1) == FAIL) 199355d5c034SBram Moolenaar { 1994f9e3e09fSBram Moolenaar emsg(_("cannot save undo information")); 19950ba04296SBram Moolenaar return; 19960ba04296SBram Moolenaar } 19970ba04296SBram Moolenaar luaV_setrange(L, eap->line1, eap->line2); 19980ba04296SBram Moolenaar luaL_buffinit(L, &b); 1999bd2f3c3eSBram Moolenaar luaL_addlstring(&b, "return function(line, linenr) ", 30); /* header */ 20000ba04296SBram Moolenaar luaL_addlstring(&b, s, strlen(s)); 20010ba04296SBram Moolenaar luaL_addlstring(&b, " end", 4); /* footer */ 20020ba04296SBram Moolenaar luaL_pushresult(&b); 20030ba04296SBram Moolenaar s = lua_tolstring(L, -1, &len); 200455d5c034SBram Moolenaar if (luaL_loadbuffer(L, s, len, LUAVIM_CHUNKNAME)) 200555d5c034SBram Moolenaar { 20060ba04296SBram Moolenaar luaV_emsg(L); 20070ba04296SBram Moolenaar lua_pop(L, 1); /* function body */ 20080ba04296SBram Moolenaar return; 20090ba04296SBram Moolenaar } 20100ba04296SBram Moolenaar lua_call(L, 0, 1); 20110ba04296SBram Moolenaar lua_replace(L, -2); /* function -> body */ 201255d5c034SBram Moolenaar for (l = eap->line1; l <= eap->line2; l++) 201355d5c034SBram Moolenaar { 2014d58f03b1SBram Moolenaar /* Check the line number, the command my have deleted lines. */ 2015d58f03b1SBram Moolenaar if (l > curbuf->b_ml.ml_line_count) 2016d58f03b1SBram Moolenaar break; 2017d58f03b1SBram Moolenaar 20180ba04296SBram Moolenaar lua_pushvalue(L, -1); /* function */ 20190ba04296SBram Moolenaar luaV_pushline(L, curbuf, l); /* current line as arg */ 2020bd2f3c3eSBram Moolenaar lua_pushinteger(L, l); /* current line number as arg */ 2021bd2f3c3eSBram Moolenaar if (lua_pcall(L, 2, 1, 0)) 202255d5c034SBram Moolenaar { 20230ba04296SBram Moolenaar luaV_emsg(L); 20240ba04296SBram Moolenaar break; 20250ba04296SBram Moolenaar } 2026d58f03b1SBram Moolenaar /* Catch the command switching to another buffer. */ 2027d58f03b1SBram Moolenaar if (curbuf != was_curbuf) 2028d58f03b1SBram Moolenaar break; 202955d5c034SBram Moolenaar if (lua_isstring(L, -1)) /* update line? */ 203055d5c034SBram Moolenaar { 20310ba04296SBram Moolenaar #ifdef HAVE_SANDBOX 20320ba04296SBram Moolenaar luaV_checksandbox(L); 20330ba04296SBram Moolenaar #endif 20340ba04296SBram Moolenaar ml_replace(l, luaV_toline(L, -1), TRUE); 20350ba04296SBram Moolenaar changed_bytes(l, 0); 20360ba04296SBram Moolenaar lua_pop(L, 1); /* result from luaV_toline */ 20370ba04296SBram Moolenaar } 20380ba04296SBram Moolenaar lua_pop(L, 1); /* line */ 20390ba04296SBram Moolenaar } 20400ba04296SBram Moolenaar lua_pop(L, 1); /* function */ 20410ba04296SBram Moolenaar check_cursor(); 20420ba04296SBram Moolenaar update_screen(NOT_VALID); 20430ba04296SBram Moolenaar } 20440ba04296SBram Moolenaar 204555d5c034SBram Moolenaar void 204655d5c034SBram Moolenaar ex_luafile(exarg_T *eap) 204755d5c034SBram Moolenaar { 204855d5c034SBram Moolenaar if (lua_init() == FAIL) 204955d5c034SBram Moolenaar return; 205055d5c034SBram Moolenaar if (!eap->skip) 205155d5c034SBram Moolenaar { 20520ba04296SBram Moolenaar luaV_setrange(L, eap->line1, eap->line2); 20530ba04296SBram Moolenaar if (luaL_loadfile(L, (char *) eap->arg) || lua_pcall(L, 0, 0, 0)) 20540ba04296SBram Moolenaar luaV_emsg(L); 20550ba04296SBram Moolenaar } 20560ba04296SBram Moolenaar } 20570ba04296SBram Moolenaar 20581dced572SBram Moolenaar #define luaV_freetype(typ,tname) \ 20591dced572SBram Moolenaar void \ 20601dced572SBram Moolenaar lua_##tname##_free(typ *o) \ 20611dced572SBram Moolenaar { \ 20621dced572SBram Moolenaar if (!lua_isopen()) return; \ 20631dced572SBram Moolenaar luaV_getfield(L, LUAVIM_FREE); \ 20641dced572SBram Moolenaar lua_pushlightuserdata(L, (void *) o); \ 20651dced572SBram Moolenaar lua_call(L, 1, 0); \ 20660ba04296SBram Moolenaar } 20670ba04296SBram Moolenaar 20681dced572SBram Moolenaar luaV_freetype(buf_T, buffer) 20691dced572SBram Moolenaar luaV_freetype(win_T, window) 20701dced572SBram Moolenaar 207155d5c034SBram Moolenaar void 20721dced572SBram Moolenaar do_luaeval(char_u *str, typval_T *arg, typval_T *rettv) 207355d5c034SBram Moolenaar { 20741dced572SBram Moolenaar lua_init(); 20751dced572SBram Moolenaar luaV_getfield(L, LUAVIM_LUAEVAL); 20761dced572SBram Moolenaar lua_pushstring(L, (char *) str); 20771dced572SBram Moolenaar lua_pushlightuserdata(L, (void *) arg); 20781dced572SBram Moolenaar lua_pushlightuserdata(L, (void *) rettv); 20791dced572SBram Moolenaar lua_call(L, 3, 0); 20801dced572SBram Moolenaar } 20811dced572SBram Moolenaar 20822459a5ecSBram Moolenaar int 20831dced572SBram Moolenaar set_ref_in_lua(int copyID) 20841dced572SBram Moolenaar { 20852459a5ecSBram Moolenaar int aborted = 0; 20862459a5ecSBram Moolenaar 20872459a5ecSBram Moolenaar if (lua_isopen()) 20882459a5ecSBram Moolenaar { 20891dced572SBram Moolenaar luaV_getfield(L, LUAVIM_SETREF); 20902459a5ecSBram Moolenaar /* call the function with 1 arg, getting 1 result back */ 20911dced572SBram Moolenaar lua_pushinteger(L, copyID); 20922459a5ecSBram Moolenaar lua_call(L, 1, 1); 20932459a5ecSBram Moolenaar /* get the result */ 20942459a5ecSBram Moolenaar aborted = lua_tointeger(L, -1); 20952459a5ecSBram Moolenaar /* pop result off the stack */ 20962459a5ecSBram Moolenaar lua_pop(L, 1); 20972459a5ecSBram Moolenaar } 20982459a5ecSBram Moolenaar return aborted; 20990ba04296SBram Moolenaar } 21000ba04296SBram Moolenaar 21010ba04296SBram Moolenaar #endif 2102