blob: abcd850b3d7d86aceefd4e792a892a6cd3f2fa4a [file] [log] [blame]
Bram Moolenaar1dced572012-04-05 16:54:08 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Lua interface by Luis Carvalho
6 *
7 * Do ":help uganda" in Vim to read copying and usage conditions.
8 * Do ":help credits" in Vim to see a list of people who contributed.
9 * See README.txt for an overview of the Vim source code.
10 */
11
Bram Moolenaare2793352011-01-17 19:53:27 +010012#include "vim.h"
13
Bram Moolenaar0ba04292010-07-14 23:23:17 +020014#include <lua.h>
15#include <lualib.h>
16#include <lauxlib.h>
Bram Moolenaar0ba04292010-07-14 23:23:17 +020017
Bram Moolenaar2ab2e862019-12-04 21:24:53 +010018// Only do the following when the feature is enabled. Needed for "make
19// depend".
Bram Moolenaar0ba04292010-07-14 23:23:17 +020020#if defined(FEAT_LUA) || defined(PROTO)
21
22#define LUAVIM_CHUNKNAME "vim chunk"
23#define LUAVIM_NAME "vim"
Bram Moolenaar1dced572012-04-05 16:54:08 +020024#define LUAVIM_EVALNAME "luaeval"
25#define LUAVIM_EVALHEADER "local _A=select(1,...) return "
Bram Moolenaar0ba04292010-07-14 23:23:17 +020026
27typedef buf_T *luaV_Buffer;
28typedef win_T *luaV_Window;
Bram Moolenaar1dced572012-04-05 16:54:08 +020029typedef dict_T *luaV_Dict;
30typedef list_T *luaV_List;
Bram Moolenaarb7828692019-03-23 13:57:02 +010031typedef blob_T *luaV_Blob;
Bram Moolenaarca06da92018-07-01 15:12:05 +020032typedef struct {
Bram Moolenaar4eefe472019-03-19 21:59:19 +010033 char_u *name; // funcref
Bram Moolenaarca06da92018-07-01 15:12:05 +020034 dict_T *self; // selfdict
35} luaV_Funcref;
Bram Moolenaarc8970b92020-10-26 20:18:08 +010036typedef int (*msgfunc_T)(char *);
Bram Moolenaar0ba04292010-07-14 23:23:17 +020037
Bram Moolenaar801ab062020-06-25 19:27:56 +020038typedef struct {
39 int lua_funcref; // ref to a lua func
40 int lua_tableref; // ref to a lua table if metatable else LUA_NOREF. used
41 // for __call
42 lua_State *L;
43} luaV_CFuncState;
44
Bram Moolenaar1dced572012-04-05 16:54:08 +020045static const char LUAVIM_DICT[] = "dict";
46static const char LUAVIM_LIST[] = "list";
Bram Moolenaarb7828692019-03-23 13:57:02 +010047static const char LUAVIM_BLOB[] = "blob";
Bram Moolenaarca06da92018-07-01 15:12:05 +020048static const char LUAVIM_FUNCREF[] = "funcref";
Bram Moolenaar0ba04292010-07-14 23:23:17 +020049static const char LUAVIM_BUFFER[] = "buffer";
50static const char LUAVIM_WINDOW[] = "window";
51static const char LUAVIM_FREE[] = "luaV_free";
Bram Moolenaar1dced572012-04-05 16:54:08 +020052static const char LUAVIM_LUAEVAL[] = "luaV_luaeval";
53static const char LUAVIM_SETREF[] = "luaV_setref";
Bram Moolenaar0ba04292010-07-14 23:23:17 +020054
Bram Moolenaar801ab062020-06-25 19:27:56 +020055static const char LUA___CALL[] = "__call";
56
Bram Moolenaar2ab2e862019-12-04 21:24:53 +010057// most functions are closures with a cache table as first upvalue;
58// get/setudata manage references to vim userdata in cache table through
59// object pointers (light userdata)
Bram Moolenaar1dced572012-04-05 16:54:08 +020060#define luaV_getudata(L, v) \
61 lua_pushlightuserdata((L), (void *) (v)); \
62 lua_rawget((L), lua_upvalueindex(1))
63#define luaV_setudata(L, v) \
64 lua_pushlightuserdata((L), (void *) (v)); \
65 lua_pushvalue((L), -2); \
66 lua_rawset((L), lua_upvalueindex(1))
Bram Moolenaar0ba04292010-07-14 23:23:17 +020067#define luaV_getfield(L, s) \
68 lua_pushlightuserdata((L), (void *)(s)); \
69 lua_rawget((L), LUA_REGISTRYINDEX)
70#define luaV_checksandbox(L) \
71 if (sandbox) luaL_error((L), "not allowed in sandbox")
72#define luaV_msg(L) luaV_msgfunc((L), (msgfunc_T) msg)
73#define luaV_emsg(L) luaV_msgfunc((L), (msgfunc_T) emsg)
Bram Moolenaarca06da92018-07-01 15:12:05 +020074#define luaV_checktypval(L, a, v, msg) \
75 do { \
Bram Moolenaar801ab062020-06-25 19:27:56 +020076 if (luaV_totypval(L, a, v) == FAIL) \
Bram Moolenaarca06da92018-07-01 15:12:05 +020077 luaL_error(L, msg ": cannot convert value"); \
78 } while (0)
Bram Moolenaar0ba04292010-07-14 23:23:17 +020079
Bram Moolenaarca06da92018-07-01 15:12:05 +020080static luaV_List *luaV_pushlist(lua_State *L, list_T *lis);
81static luaV_Dict *luaV_pushdict(lua_State *L, dict_T *dic);
Bram Moolenaarb7828692019-03-23 13:57:02 +010082static luaV_Blob *luaV_pushblob(lua_State *L, blob_T *blo);
Bram Moolenaar4eefe472019-03-19 21:59:19 +010083static luaV_Funcref *luaV_pushfuncref(lua_State *L, char_u *name);
Bram Moolenaar801ab062020-06-25 19:27:56 +020084static int luaV_call_lua_func(int argcount, typval_T *argvars, typval_T *rettv, void *state);
85static void luaV_call_lua_func_free(void *state);
Bram Moolenaar1dced572012-04-05 16:54:08 +020086
87#if LUA_VERSION_NUM <= 501
88#define luaV_openlib(L, l, n) luaL_openlib(L, NULL, l, n)
89#define luaL_typeerror luaL_typerror
90#else
91#define luaV_openlib luaL_setfuncs
92#endif
Bram Moolenaar0ba04292010-07-14 23:23:17 +020093
94#ifdef DYNAMIC_LUA
Bram Moolenaar2334b6d2010-07-22 21:32:16 +020095
Bram Moolenaar4f974752019-02-17 17:44:42 +010096#ifndef MSWIN
Bram Moolenaar2334b6d2010-07-22 21:32:16 +020097# include <dlfcn.h>
98# define HANDLE void*
99# define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL)
100# define symbol_from_dll dlsym
101# define close_dll dlclose
102#else
Bram Moolenaarebbcb822010-10-23 14:02:54 +0200103# define load_dll vimLoadLib
Bram Moolenaar2334b6d2010-07-22 21:32:16 +0200104# define symbol_from_dll GetProcAddress
105# define close_dll FreeLibrary
106#endif
107
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100108// lauxlib
Bram Moolenaar1dced572012-04-05 16:54:08 +0200109#if LUA_VERSION_NUM <= 501
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200110#define luaL_register dll_luaL_register
Bram Moolenaar1dced572012-04-05 16:54:08 +0200111#define luaL_prepbuffer dll_luaL_prepbuffer
112#define luaL_openlib dll_luaL_openlib
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200113#define luaL_typerror dll_luaL_typerror
Bram Moolenaar1dced572012-04-05 16:54:08 +0200114#define luaL_loadfile dll_luaL_loadfile
115#define luaL_loadbuffer dll_luaL_loadbuffer
116#else
117#define luaL_prepbuffsize dll_luaL_prepbuffsize
118#define luaL_setfuncs dll_luaL_setfuncs
119#define luaL_loadfilex dll_luaL_loadfilex
120#define luaL_loadbufferx dll_luaL_loadbufferx
121#define luaL_argerror dll_luaL_argerror
122#endif
Bram Moolenaar5551b132020-07-14 21:54:28 +0200123#if LUA_VERSION_NUM >= 504
124#define luaL_typeerror dll_luaL_typeerror
125#endif
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +0200126#define luaL_checkany dll_luaL_checkany
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200127#define luaL_checklstring dll_luaL_checklstring
128#define luaL_checkinteger dll_luaL_checkinteger
129#define luaL_optinteger dll_luaL_optinteger
130#define luaL_checktype dll_luaL_checktype
131#define luaL_error dll_luaL_error
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200132#define luaL_newstate dll_luaL_newstate
133#define luaL_buffinit dll_luaL_buffinit
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200134#define luaL_addlstring dll_luaL_addlstring
135#define luaL_pushresult dll_luaL_pushresult
Bram Moolenaardf1643a2020-05-17 18:53:27 +0200136#define luaL_loadstring dll_luaL_loadstring
Bram Moolenaar1e4c7d02020-06-25 20:56:42 +0200137#define luaL_ref dll_luaL_ref
138#define luaL_unref dll_luaL_unref
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100139// lua
Bram Moolenaar1dced572012-04-05 16:54:08 +0200140#if LUA_VERSION_NUM <= 501
141#define lua_tonumber dll_lua_tonumber
142#define lua_tointeger dll_lua_tointeger
143#define lua_call dll_lua_call
144#define lua_pcall dll_lua_pcall
145#else
146#define lua_tonumberx dll_lua_tonumberx
147#define lua_tointegerx dll_lua_tointegerx
148#define lua_callk dll_lua_callk
149#define lua_pcallk dll_lua_pcallk
150#define lua_getglobal dll_lua_getglobal
151#define lua_setglobal dll_lua_setglobal
Bram Moolenaar1dced572012-04-05 16:54:08 +0200152#endif
Bram Moolenaar1f860d82015-06-27 18:36:16 +0200153#if LUA_VERSION_NUM <= 502
154#define lua_replace dll_lua_replace
155#define lua_remove dll_lua_remove
156#endif
157#if LUA_VERSION_NUM >= 503
158#define lua_rotate dll_lua_rotate
159#define lua_copy dll_lua_copy
160#endif
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +0200161#define lua_typename dll_lua_typename
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200162#define lua_close dll_lua_close
163#define lua_gettop dll_lua_gettop
164#define lua_settop dll_lua_settop
165#define lua_pushvalue dll_lua_pushvalue
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200166#define lua_isnumber dll_lua_isnumber
167#define lua_isstring dll_lua_isstring
168#define lua_type dll_lua_type
169#define lua_rawequal dll_lua_rawequal
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200170#define lua_toboolean dll_lua_toboolean
171#define lua_tolstring dll_lua_tolstring
172#define lua_touserdata dll_lua_touserdata
173#define lua_pushnil dll_lua_pushnil
174#define lua_pushnumber dll_lua_pushnumber
175#define lua_pushinteger dll_lua_pushinteger
176#define lua_pushlstring dll_lua_pushlstring
177#define lua_pushstring dll_lua_pushstring
178#define lua_pushfstring dll_lua_pushfstring
179#define lua_pushcclosure dll_lua_pushcclosure
180#define lua_pushboolean dll_lua_pushboolean
181#define lua_pushlightuserdata dll_lua_pushlightuserdata
182#define lua_getfield dll_lua_getfield
183#define lua_rawget dll_lua_rawget
Bram Moolenaar1dced572012-04-05 16:54:08 +0200184#define lua_rawgeti dll_lua_rawgeti
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200185#define lua_createtable dll_lua_createtable
Bram Moolenaar830e3582018-08-21 14:23:35 +0200186#if LUA_VERSION_NUM >= 504
187 #define lua_newuserdatauv dll_lua_newuserdatauv
188#else
189 #define lua_newuserdata dll_lua_newuserdata
190#endif
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200191#define lua_getmetatable dll_lua_getmetatable
192#define lua_setfield dll_lua_setfield
193#define lua_rawset dll_lua_rawset
194#define lua_rawseti dll_lua_rawseti
195#define lua_setmetatable dll_lua_setmetatable
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +0200196#define lua_next dll_lua_next
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100197// libs
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200198#define luaopen_base dll_luaopen_base
199#define luaopen_table dll_luaopen_table
200#define luaopen_string dll_luaopen_string
201#define luaopen_math dll_luaopen_math
Bram Moolenaar16c98f92010-07-28 22:46:08 +0200202#define luaopen_io dll_luaopen_io
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200203#define luaopen_os dll_luaopen_os
204#define luaopen_package dll_luaopen_package
205#define luaopen_debug dll_luaopen_debug
Bram Moolenaar16c98f92010-07-28 22:46:08 +0200206#define luaL_openlibs dll_luaL_openlibs
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200207
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100208// lauxlib
Bram Moolenaar1dced572012-04-05 16:54:08 +0200209#if LUA_VERSION_NUM <= 501
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200210void (*dll_luaL_register) (lua_State *L, const char *libname, const luaL_Reg *l);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200211char *(*dll_luaL_prepbuffer) (luaL_Buffer *B);
212void (*dll_luaL_openlib) (lua_State *L, const char *libname, const luaL_Reg *l, int nup);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200213int (*dll_luaL_typerror) (lua_State *L, int narg, const char *tname);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200214int (*dll_luaL_loadfile) (lua_State *L, const char *filename);
215int (*dll_luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, const char *name);
216#else
217char *(*dll_luaL_prepbuffsize) (luaL_Buffer *B, size_t sz);
218void (*dll_luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
219int (*dll_luaL_loadfilex) (lua_State *L, const char *filename, const char *mode);
220int (*dll_luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode);
221int (*dll_luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
222#endif
Bram Moolenaar5551b132020-07-14 21:54:28 +0200223#if LUA_VERSION_NUM >= 504
224int (*dll_luaL_typeerror) (lua_State *L, int narg, const char *tname);
225#endif
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +0200226void (*dll_luaL_checkany) (lua_State *L, int narg);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200227const char *(*dll_luaL_checklstring) (lua_State *L, int numArg, size_t *l);
228lua_Integer (*dll_luaL_checkinteger) (lua_State *L, int numArg);
229lua_Integer (*dll_luaL_optinteger) (lua_State *L, int nArg, lua_Integer def);
230void (*dll_luaL_checktype) (lua_State *L, int narg, int t);
231int (*dll_luaL_error) (lua_State *L, const char *fmt, ...);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200232lua_State *(*dll_luaL_newstate) (void);
233void (*dll_luaL_buffinit) (lua_State *L, luaL_Buffer *B);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200234void (*dll_luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
235void (*dll_luaL_pushresult) (luaL_Buffer *B);
Bram Moolenaardf1643a2020-05-17 18:53:27 +0200236int (*dll_luaL_loadstring) (lua_State *L, const char *s);
Bram Moolenaar1e4c7d02020-06-25 20:56:42 +0200237int (*dll_luaL_ref) (lua_State *L, int idx);
238#if LUA_VERSION_NUM <= 502
239void (*dll_luaL_unref) (lua_State *L, int idx, int n);
240#else
241void (*dll_luaL_unref) (lua_State *L, int idx, lua_Integer n);
242#endif
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100243// lua
Bram Moolenaar1dced572012-04-05 16:54:08 +0200244#if LUA_VERSION_NUM <= 501
245lua_Number (*dll_lua_tonumber) (lua_State *L, int idx);
246lua_Integer (*dll_lua_tointeger) (lua_State *L, int idx);
247void (*dll_lua_call) (lua_State *L, int nargs, int nresults);
248int (*dll_lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
249#else
250lua_Number (*dll_lua_tonumberx) (lua_State *L, int idx, int *isnum);
251lua_Integer (*dll_lua_tointegerx) (lua_State *L, int idx, int *isnum);
252void (*dll_lua_callk) (lua_State *L, int nargs, int nresults, int ctx,
Bram Moolenaardb913952012-06-29 12:54:53 +0200253 lua_CFunction k);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200254int (*dll_lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc,
Bram Moolenaardb913952012-06-29 12:54:53 +0200255 int ctx, lua_CFunction k);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200256void (*dll_lua_getglobal) (lua_State *L, const char *var);
257void (*dll_lua_setglobal) (lua_State *L, const char *var);
Bram Moolenaar1f860d82015-06-27 18:36:16 +0200258#endif
259#if LUA_VERSION_NUM <= 502
260void (*dll_lua_replace) (lua_State *L, int idx);
261void (*dll_lua_remove) (lua_State *L, int idx);
262#endif
263#if LUA_VERSION_NUM >= 503
264void (*dll_lua_rotate) (lua_State *L, int idx, int n);
Bram Moolenaar9514b1f2015-06-25 18:27:32 +0200265void (*dll_lua_copy) (lua_State *L, int fromidx, int toidx);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200266#endif
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +0200267const char *(*dll_lua_typename) (lua_State *L, int tp);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200268void (*dll_lua_close) (lua_State *L);
269int (*dll_lua_gettop) (lua_State *L);
270void (*dll_lua_settop) (lua_State *L, int idx);
271void (*dll_lua_pushvalue) (lua_State *L, int idx);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200272int (*dll_lua_isnumber) (lua_State *L, int idx);
273int (*dll_lua_isstring) (lua_State *L, int idx);
274int (*dll_lua_type) (lua_State *L, int idx);
275int (*dll_lua_rawequal) (lua_State *L, int idx1, int idx2);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200276int (*dll_lua_toboolean) (lua_State *L, int idx);
277const char *(*dll_lua_tolstring) (lua_State *L, int idx, size_t *len);
278void *(*dll_lua_touserdata) (lua_State *L, int idx);
279void (*dll_lua_pushnil) (lua_State *L);
280void (*dll_lua_pushnumber) (lua_State *L, lua_Number n);
281void (*dll_lua_pushinteger) (lua_State *L, lua_Integer n);
282void (*dll_lua_pushlstring) (lua_State *L, const char *s, size_t l);
283void (*dll_lua_pushstring) (lua_State *L, const char *s);
284const char *(*dll_lua_pushfstring) (lua_State *L, const char *fmt, ...);
285void (*dll_lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
286void (*dll_lua_pushboolean) (lua_State *L, int b);
287void (*dll_lua_pushlightuserdata) (lua_State *L, void *p);
288void (*dll_lua_getfield) (lua_State *L, int idx, const char *k);
Bram Moolenaar17413672018-07-14 20:49:42 +0200289#if LUA_VERSION_NUM <= 502
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200290void (*dll_lua_rawget) (lua_State *L, int idx);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200291void (*dll_lua_rawgeti) (lua_State *L, int idx, int n);
Bram Moolenaar17413672018-07-14 20:49:42 +0200292#else
293int (*dll_lua_rawget) (lua_State *L, int idx);
294int (*dll_lua_rawgeti) (lua_State *L, int idx, lua_Integer n);
295#endif
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200296void (*dll_lua_createtable) (lua_State *L, int narr, int nrec);
Bram Moolenaar830e3582018-08-21 14:23:35 +0200297#if LUA_VERSION_NUM >= 504
298void *(*dll_lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue);
299#else
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200300void *(*dll_lua_newuserdata) (lua_State *L, size_t sz);
Bram Moolenaar830e3582018-08-21 14:23:35 +0200301#endif
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200302int (*dll_lua_getmetatable) (lua_State *L, int objindex);
303void (*dll_lua_setfield) (lua_State *L, int idx, const char *k);
304void (*dll_lua_rawset) (lua_State *L, int idx);
Bram Moolenaar17413672018-07-14 20:49:42 +0200305#if LUA_VERSION_NUM <= 502
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200306void (*dll_lua_rawseti) (lua_State *L, int idx, int n);
Bram Moolenaar17413672018-07-14 20:49:42 +0200307#else
308void (*dll_lua_rawseti) (lua_State *L, int idx, lua_Integer n);
309#endif
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200310int (*dll_lua_setmetatable) (lua_State *L, int objindex);
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +0200311int (*dll_lua_next) (lua_State *L, int idx);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100312// libs
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200313int (*dll_luaopen_base) (lua_State *L);
314int (*dll_luaopen_table) (lua_State *L);
315int (*dll_luaopen_string) (lua_State *L);
316int (*dll_luaopen_math) (lua_State *L);
Bram Moolenaar16c98f92010-07-28 22:46:08 +0200317int (*dll_luaopen_io) (lua_State *L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200318int (*dll_luaopen_os) (lua_State *L);
319int (*dll_luaopen_package) (lua_State *L);
320int (*dll_luaopen_debug) (lua_State *L);
Bram Moolenaar16c98f92010-07-28 22:46:08 +0200321void (*dll_luaL_openlibs) (lua_State *L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200322
323typedef void **luaV_function;
324typedef struct {
325 const char *name;
326 luaV_function func;
327} luaV_Reg;
328
329static const luaV_Reg luaV_dll[] = {
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100330 // lauxlib
Bram Moolenaar1dced572012-04-05 16:54:08 +0200331#if LUA_VERSION_NUM <= 501
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200332 {"luaL_register", (luaV_function) &dll_luaL_register},
Bram Moolenaar1dced572012-04-05 16:54:08 +0200333 {"luaL_prepbuffer", (luaV_function) &dll_luaL_prepbuffer},
334 {"luaL_openlib", (luaV_function) &dll_luaL_openlib},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200335 {"luaL_typerror", (luaV_function) &dll_luaL_typerror},
Bram Moolenaar1dced572012-04-05 16:54:08 +0200336 {"luaL_loadfile", (luaV_function) &dll_luaL_loadfile},
337 {"luaL_loadbuffer", (luaV_function) &dll_luaL_loadbuffer},
338#else
339 {"luaL_prepbuffsize", (luaV_function) &dll_luaL_prepbuffsize},
340 {"luaL_setfuncs", (luaV_function) &dll_luaL_setfuncs},
341 {"luaL_loadfilex", (luaV_function) &dll_luaL_loadfilex},
342 {"luaL_loadbufferx", (luaV_function) &dll_luaL_loadbufferx},
343 {"luaL_argerror", (luaV_function) &dll_luaL_argerror},
344#endif
Bram Moolenaar5551b132020-07-14 21:54:28 +0200345#if LUA_VERSION_NUM >= 504
346 {"luaL_typeerror", (luaV_function) &dll_luaL_typeerror},
347#endif
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +0200348 {"luaL_checkany", (luaV_function) &dll_luaL_checkany},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200349 {"luaL_checklstring", (luaV_function) &dll_luaL_checklstring},
350 {"luaL_checkinteger", (luaV_function) &dll_luaL_checkinteger},
351 {"luaL_optinteger", (luaV_function) &dll_luaL_optinteger},
352 {"luaL_checktype", (luaV_function) &dll_luaL_checktype},
353 {"luaL_error", (luaV_function) &dll_luaL_error},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200354 {"luaL_newstate", (luaV_function) &dll_luaL_newstate},
355 {"luaL_buffinit", (luaV_function) &dll_luaL_buffinit},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200356 {"luaL_addlstring", (luaV_function) &dll_luaL_addlstring},
357 {"luaL_pushresult", (luaV_function) &dll_luaL_pushresult},
Bram Moolenaardf1643a2020-05-17 18:53:27 +0200358 {"luaL_loadstring", (luaV_function) &dll_luaL_loadstring},
Bram Moolenaar1e4c7d02020-06-25 20:56:42 +0200359 {"luaL_ref", (luaV_function) &dll_luaL_ref},
360 {"luaL_unref", (luaV_function) &dll_luaL_unref},
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100361 // lua
Bram Moolenaar1dced572012-04-05 16:54:08 +0200362#if LUA_VERSION_NUM <= 501
363 {"lua_tonumber", (luaV_function) &dll_lua_tonumber},
364 {"lua_tointeger", (luaV_function) &dll_lua_tointeger},
365 {"lua_call", (luaV_function) &dll_lua_call},
366 {"lua_pcall", (luaV_function) &dll_lua_pcall},
367#else
368 {"lua_tonumberx", (luaV_function) &dll_lua_tonumberx},
369 {"lua_tointegerx", (luaV_function) &dll_lua_tointegerx},
370 {"lua_callk", (luaV_function) &dll_lua_callk},
371 {"lua_pcallk", (luaV_function) &dll_lua_pcallk},
372 {"lua_getglobal", (luaV_function) &dll_lua_getglobal},
373 {"lua_setglobal", (luaV_function) &dll_lua_setglobal},
Bram Moolenaar1dced572012-04-05 16:54:08 +0200374#endif
Bram Moolenaar1f860d82015-06-27 18:36:16 +0200375#if LUA_VERSION_NUM <= 502
376 {"lua_replace", (luaV_function) &dll_lua_replace},
377 {"lua_remove", (luaV_function) &dll_lua_remove},
378#endif
379#if LUA_VERSION_NUM >= 503
380 {"lua_rotate", (luaV_function) &dll_lua_rotate},
381 {"lua_copy", (luaV_function) &dll_lua_copy},
382#endif
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +0200383 {"lua_typename", (luaV_function) &dll_lua_typename},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200384 {"lua_close", (luaV_function) &dll_lua_close},
385 {"lua_gettop", (luaV_function) &dll_lua_gettop},
386 {"lua_settop", (luaV_function) &dll_lua_settop},
387 {"lua_pushvalue", (luaV_function) &dll_lua_pushvalue},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200388 {"lua_isnumber", (luaV_function) &dll_lua_isnumber},
389 {"lua_isstring", (luaV_function) &dll_lua_isstring},
390 {"lua_type", (luaV_function) &dll_lua_type},
391 {"lua_rawequal", (luaV_function) &dll_lua_rawequal},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200392 {"lua_toboolean", (luaV_function) &dll_lua_toboolean},
393 {"lua_tolstring", (luaV_function) &dll_lua_tolstring},
394 {"lua_touserdata", (luaV_function) &dll_lua_touserdata},
395 {"lua_pushnil", (luaV_function) &dll_lua_pushnil},
396 {"lua_pushnumber", (luaV_function) &dll_lua_pushnumber},
397 {"lua_pushinteger", (luaV_function) &dll_lua_pushinteger},
398 {"lua_pushlstring", (luaV_function) &dll_lua_pushlstring},
399 {"lua_pushstring", (luaV_function) &dll_lua_pushstring},
400 {"lua_pushfstring", (luaV_function) &dll_lua_pushfstring},
401 {"lua_pushcclosure", (luaV_function) &dll_lua_pushcclosure},
402 {"lua_pushboolean", (luaV_function) &dll_lua_pushboolean},
403 {"lua_pushlightuserdata", (luaV_function) &dll_lua_pushlightuserdata},
404 {"lua_getfield", (luaV_function) &dll_lua_getfield},
405 {"lua_rawget", (luaV_function) &dll_lua_rawget},
Bram Moolenaar1dced572012-04-05 16:54:08 +0200406 {"lua_rawgeti", (luaV_function) &dll_lua_rawgeti},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200407 {"lua_createtable", (luaV_function) &dll_lua_createtable},
Bram Moolenaar830e3582018-08-21 14:23:35 +0200408#if LUA_VERSION_NUM >= 504
409 {"lua_newuserdatauv", (luaV_function) &dll_lua_newuserdatauv},
410#else
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200411 {"lua_newuserdata", (luaV_function) &dll_lua_newuserdata},
Bram Moolenaar830e3582018-08-21 14:23:35 +0200412#endif
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200413 {"lua_getmetatable", (luaV_function) &dll_lua_getmetatable},
414 {"lua_setfield", (luaV_function) &dll_lua_setfield},
415 {"lua_rawset", (luaV_function) &dll_lua_rawset},
416 {"lua_rawseti", (luaV_function) &dll_lua_rawseti},
417 {"lua_setmetatable", (luaV_function) &dll_lua_setmetatable},
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +0200418 {"lua_next", (luaV_function) &dll_lua_next},
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100419 // libs
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200420 {"luaopen_base", (luaV_function) &dll_luaopen_base},
421 {"luaopen_table", (luaV_function) &dll_luaopen_table},
422 {"luaopen_string", (luaV_function) &dll_luaopen_string},
423 {"luaopen_math", (luaV_function) &dll_luaopen_math},
Bram Moolenaar16c98f92010-07-28 22:46:08 +0200424 {"luaopen_io", (luaV_function) &dll_luaopen_io},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200425 {"luaopen_os", (luaV_function) &dll_luaopen_os},
426 {"luaopen_package", (luaV_function) &dll_luaopen_package},
427 {"luaopen_debug", (luaV_function) &dll_luaopen_debug},
Bram Moolenaar16c98f92010-07-28 22:46:08 +0200428 {"luaL_openlibs", (luaV_function) &dll_luaL_openlibs},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200429 {NULL, NULL}
430};
431
Bram Moolenaar2334b6d2010-07-22 21:32:16 +0200432static HANDLE hinstLua = NULL;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200433
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200434 static int
435lua_link_init(char *libname, int verbose)
436{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200437 const luaV_Reg *reg;
438 if (hinstLua) return OK;
Bram Moolenaar2334b6d2010-07-22 21:32:16 +0200439 hinstLua = load_dll(libname);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200440 if (!hinstLua)
441 {
442 if (verbose)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100443 semsg(_(e_loadlib), libname);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200444 return FAIL;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200445 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200446 for (reg = luaV_dll; reg->func; reg++)
447 {
Bram Moolenaar2334b6d2010-07-22 21:32:16 +0200448 if ((*reg->func = symbol_from_dll(hinstLua, reg->name)) == NULL)
449 {
450 close_dll(hinstLua);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200451 hinstLua = 0;
452 if (verbose)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100453 semsg(_(e_loadfunc), reg->name);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200454 return FAIL;
455 }
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200456 }
457 return OK;
458}
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100459#endif // DYNAMIC_LUA
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200460
Bram Moolenaard90b6c02016-08-28 18:10:45 +0200461#if defined(DYNAMIC_LUA) || defined(PROTO)
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200462 int
463lua_enabled(int verbose)
464{
Bram Moolenaar25e4fcd2016-01-09 14:57:47 +0100465 return lua_link_init((char *)p_luadll, verbose) == OK;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200466}
Bram Moolenaard90b6c02016-08-28 18:10:45 +0200467#endif
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200468
Bram Moolenaar5551b132020-07-14 21:54:28 +0200469#if LUA_VERSION_NUM > 501 && LUA_VERSION_NUM < 504
Bram Moolenaar1dced572012-04-05 16:54:08 +0200470 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100471luaL_typeerror(lua_State *L, int narg, const char *tname)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200472{
473 const char *msg = lua_pushfstring(L, "%s expected, got %s",
Bram Moolenaardb913952012-06-29 12:54:53 +0200474 tname, luaL_typename(L, narg));
Bram Moolenaar1dced572012-04-05 16:54:08 +0200475 return luaL_argerror(L, narg, msg);
476}
477#endif
478
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200479
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100480// ======= Internal =======
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200481
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200482 static void
483luaV_newmetatable(lua_State *L, const char *tname)
484{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200485 lua_newtable(L);
486 lua_pushlightuserdata(L, (void *) tname);
487 lua_pushvalue(L, -2);
488 lua_rawset(L, LUA_REGISTRYINDEX);
489}
490
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200491 static void *
492luaV_toudata(lua_State *L, int ud, const char *tname)
493{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200494 void *p = lua_touserdata(L, ud);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200495
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100496 if (p != NULL) // value is userdata?
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200497 {
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100498 if (lua_getmetatable(L, ud)) // does it have a metatable?
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200499 {
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100500 luaV_getfield(L, tname); // get metatable
501 if (lua_rawequal(L, -1, -2)) // MTs match?
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200502 {
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100503 lua_pop(L, 2); // MTs
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200504 return p;
505 }
506 }
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200507 }
508 return NULL;
509}
510
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200511 static void *
Bram Moolenaar1dced572012-04-05 16:54:08 +0200512luaV_checkcache(lua_State *L, void *p)
513{
514 luaV_getudata(L, p);
515 if (lua_isnil(L, -1)) luaL_error(L, "invalid object");
516 lua_pop(L, 1);
517 return p;
518}
519
520#define luaV_unbox(L,luatyp,ud) (*((luatyp *) lua_touserdata((L),(ud))))
521
522#define luaV_checkvalid(L,luatyp,ud) \
523 luaV_checkcache((L), (void *) luaV_unbox((L),luatyp,(ud)))
524
525 static void *
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200526luaV_checkudata(lua_State *L, int ud, const char *tname)
527{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200528 void *p = luaV_toudata(L, ud, tname);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200529 if (p == NULL) luaL_typeerror(L, ud, tname);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200530 return p;
531}
532
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200533 static void
534luaV_pushtypval(lua_State *L, typval_T *tv)
535{
Bram Moolenaar1dced572012-04-05 16:54:08 +0200536 if (tv == NULL)
537 {
538 lua_pushnil(L);
539 return;
540 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200541 switch (tv->v_type)
542 {
543 case VAR_STRING:
Bram Moolenaard04da7c2012-10-14 03:41:59 +0200544 lua_pushstring(L, tv->vval.v_string == NULL
545 ? "" : (char *)tv->vval.v_string);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200546 break;
547 case VAR_NUMBER:
548 lua_pushinteger(L, (int) tv->vval.v_number);
549 break;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200550#ifdef FEAT_FLOAT
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200551 case VAR_FLOAT:
552 lua_pushnumber(L, (lua_Number) tv->vval.v_float);
553 break;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200554#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +0200555 case VAR_LIST:
556 luaV_pushlist(L, tv->vval.v_list);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200557 break;
Bram Moolenaar1dced572012-04-05 16:54:08 +0200558 case VAR_DICT:
559 luaV_pushdict(L, tv->vval.v_dict);
560 break;
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +0100561 case VAR_BOOL:
Bram Moolenaar520e1e42016-01-23 19:46:28 +0100562 case VAR_SPECIAL:
563 if (tv->vval.v_number <= VVAL_TRUE)
564 lua_pushinteger(L, (int) tv->vval.v_number);
565 else
566 lua_pushnil(L);
567 break;
Bram Moolenaarca06da92018-07-01 15:12:05 +0200568 case VAR_FUNC:
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100569 luaV_pushfuncref(L, tv->vval.v_string);
Bram Moolenaarca06da92018-07-01 15:12:05 +0200570 break;
Bram Moolenaar86c3a212021-03-08 19:50:24 +0100571 case VAR_PARTIAL:
572 // TODO: handle partial arguments
573 luaV_pushfuncref(L, partial_name(tv->vval.v_partial));
574 break;
575
Bram Moolenaarb7828692019-03-23 13:57:02 +0100576 case VAR_BLOB:
577 luaV_pushblob(L, tv->vval.v_blob);
578 break;
Bram Moolenaar1dced572012-04-05 16:54:08 +0200579 default:
580 lua_pushnil(L);
581 }
582}
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200583
Bram Moolenaarca06da92018-07-01 15:12:05 +0200584/*
585 * Converts lua value at 'pos' to typval 'tv'.
586 * Returns OK or FAIL.
587 */
588 static int
589luaV_totypval(lua_State *L, int pos, typval_T *tv)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200590{
Bram Moolenaarca06da92018-07-01 15:12:05 +0200591 int status = OK;
592
Bram Moolenaara9a8e5f2020-07-02 21:17:57 +0200593 tv->v_lock = 0;
594
Bram Moolenaarca06da92018-07-01 15:12:05 +0200595 switch (lua_type(L, pos))
596 {
Bram Moolenaar1dced572012-04-05 16:54:08 +0200597 case LUA_TBOOLEAN:
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +0100598 tv->v_type = VAR_BOOL;
Bram Moolenaar1dced572012-04-05 16:54:08 +0200599 tv->vval.v_number = (varnumber_T) lua_toboolean(L, pos);
600 break;
Bram Moolenaar9067cd62019-01-01 00:41:54 +0100601 case LUA_TNIL:
602 tv->v_type = VAR_SPECIAL;
603 tv->vval.v_number = VVAL_NULL;
604 break;
Bram Moolenaar1dced572012-04-05 16:54:08 +0200605 case LUA_TSTRING:
606 tv->v_type = VAR_STRING;
607 tv->vval.v_string = vim_strsave((char_u *) lua_tostring(L, pos));
608 break;
609 case LUA_TNUMBER:
610#ifdef FEAT_FLOAT
Bram Moolenaareb04f082020-05-17 14:32:35 +0200611 {
612 const lua_Number n = lua_tonumber(L, pos);
613
614 if (n > (lua_Number)INT64_MAX || n < (lua_Number)INT64_MIN
615 || ((lua_Number)((varnumber_T)n)) != n)
616 {
617 tv->v_type = VAR_FLOAT;
618 tv->vval.v_float = (float_T)n;
619 }
620 else
621 {
622 tv->v_type = VAR_NUMBER;
623 tv->vval.v_number = (varnumber_T)n;
624 }
625 }
Bram Moolenaar1dced572012-04-05 16:54:08 +0200626#else
627 tv->v_type = VAR_NUMBER;
628 tv->vval.v_number = (varnumber_T) lua_tointeger(L, pos);
629#endif
630 break;
Bram Moolenaar801ab062020-06-25 19:27:56 +0200631 case LUA_TFUNCTION:
632 {
633 char_u *name;
Bram Moolenaar066e7da2020-07-18 12:50:35 +0200634 luaV_CFuncState *state;
635
Bram Moolenaar801ab062020-06-25 19:27:56 +0200636 lua_pushvalue(L, pos);
Bram Moolenaar066e7da2020-07-18 12:50:35 +0200637 state = ALLOC_CLEAR_ONE(luaV_CFuncState);
Bram Moolenaar801ab062020-06-25 19:27:56 +0200638 state->lua_funcref = luaL_ref(L, LUA_REGISTRYINDEX);
639 state->L = L;
640 state->lua_tableref = LUA_NOREF;
641 name = register_cfunc(&luaV_call_lua_func,
642 &luaV_call_lua_func_free, state);
643 tv->v_type = VAR_FUNC;
644 tv->vval.v_string = vim_strsave(name);
645 break;
646 }
647 case LUA_TTABLE:
648 {
Bram Moolenaar066e7da2020-07-18 12:50:35 +0200649 int lua_tableref;
650
Bram Moolenaar801ab062020-06-25 19:27:56 +0200651 lua_pushvalue(L, pos);
Bram Moolenaar066e7da2020-07-18 12:50:35 +0200652 lua_tableref = luaL_ref(L, LUA_REGISTRYINDEX);
Bram Moolenaar801ab062020-06-25 19:27:56 +0200653 if (lua_getmetatable(L, pos)) {
654 lua_getfield(L, -1, LUA___CALL);
655 if (lua_isfunction(L, -1)) {
656 char_u *name;
657 int lua_funcref = luaL_ref(L, LUA_REGISTRYINDEX);
658 luaV_CFuncState *state = ALLOC_CLEAR_ONE(luaV_CFuncState);
Bram Moolenaar066e7da2020-07-18 12:50:35 +0200659
Bram Moolenaar801ab062020-06-25 19:27:56 +0200660 state->lua_funcref = lua_funcref;
661 state->L = L;
662 state->lua_tableref = lua_tableref;
663 name = register_cfunc(&luaV_call_lua_func,
664 &luaV_call_lua_func_free, state);
665 tv->v_type = VAR_FUNC;
666 tv->vval.v_string = vim_strsave(name);
667 break;
668 }
669 }
670 tv->v_type = VAR_NUMBER;
671 tv->vval.v_number = 0;
672 status = FAIL;
673 break;
674 }
Bram Moolenaarca06da92018-07-01 15:12:05 +0200675 case LUA_TUSERDATA:
676 {
Bram Moolenaar1dced572012-04-05 16:54:08 +0200677 void *p = lua_touserdata(L, pos);
Bram Moolenaarca06da92018-07-01 15:12:05 +0200678
Bram Moolenaarb7828692019-03-23 13:57:02 +0100679 if (lua_getmetatable(L, pos)) // has metatable?
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200680 {
Bram Moolenaarb7828692019-03-23 13:57:02 +0100681 // check list
Bram Moolenaar1dced572012-04-05 16:54:08 +0200682 luaV_getfield(L, LUAVIM_LIST);
683 if (lua_rawequal(L, -1, -2))
Bram Moolenaar2334b6d2010-07-22 21:32:16 +0200684 {
Bram Moolenaar1dced572012-04-05 16:54:08 +0200685 tv->v_type = VAR_LIST;
686 tv->vval.v_list = *((luaV_List *) p);
687 ++tv->vval.v_list->lv_refcount;
Bram Moolenaarb7828692019-03-23 13:57:02 +0100688 lua_pop(L, 2); // MTs
Bram Moolenaarca06da92018-07-01 15:12:05 +0200689 break;
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200690 }
Bram Moolenaarb7828692019-03-23 13:57:02 +0100691 // check dict
Bram Moolenaar1dced572012-04-05 16:54:08 +0200692 luaV_getfield(L, LUAVIM_DICT);
693 if (lua_rawequal(L, -1, -3))
694 {
695 tv->v_type = VAR_DICT;
696 tv->vval.v_dict = *((luaV_Dict *) p);
697 ++tv->vval.v_dict->dv_refcount;
Bram Moolenaarb7828692019-03-23 13:57:02 +0100698 lua_pop(L, 3); // MTs
Bram Moolenaarca06da92018-07-01 15:12:05 +0200699 break;
Bram Moolenaar1dced572012-04-05 16:54:08 +0200700 }
Bram Moolenaarb7828692019-03-23 13:57:02 +0100701 // check blob
702 luaV_getfield(L, LUAVIM_BLOB);
Bram Moolenaarca06da92018-07-01 15:12:05 +0200703 if (lua_rawequal(L, -1, -4))
704 {
Bram Moolenaarb7828692019-03-23 13:57:02 +0100705 tv->v_type = VAR_BLOB;
706 tv->vval.v_blob = *((luaV_Blob *) p);
707 ++tv->vval.v_blob->bv_refcount;
708 lua_pop(L, 4); // MTs
709 break;
710 }
711 // check funcref
712 luaV_getfield(L, LUAVIM_FUNCREF);
713 if (lua_rawequal(L, -1, -5))
714 {
Bram Moolenaarca06da92018-07-01 15:12:05 +0200715 luaV_Funcref *f = (luaV_Funcref *) p;
Bram Moolenaar066e7da2020-07-18 12:50:35 +0200716
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100717 func_ref(f->name);
718 tv->v_type = VAR_FUNC;
719 tv->vval.v_string = vim_strsave(f->name);
Bram Moolenaarb7828692019-03-23 13:57:02 +0100720 lua_pop(L, 5); // MTs
Bram Moolenaarca06da92018-07-01 15:12:05 +0200721 break;
722 }
Bram Moolenaarb7828692019-03-23 13:57:02 +0100723 lua_pop(L, 4); // MTs
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200724 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200725 }
Bram Moolenaarb7828692019-03-23 13:57:02 +0100726 // FALLTHROUGH
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200727 default:
Bram Moolenaar1dced572012-04-05 16:54:08 +0200728 tv->v_type = VAR_NUMBER;
729 tv->vval.v_number = 0;
Bram Moolenaarca06da92018-07-01 15:12:05 +0200730 status = FAIL;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200731 }
Bram Moolenaarca06da92018-07-01 15:12:05 +0200732 return status;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200733}
734
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100735/*
736 * similar to luaL_addlstring, but replaces \0 with \n if toline and
737 * \n with \0 otherwise
738 */
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200739 static void
740luaV_addlstring(luaL_Buffer *b, const char *s, size_t l, int toline)
741{
742 while (l--)
743 {
744 if (*s == '\0' && toline)
745 luaL_addchar(b, '\n');
746 else if (*s == '\n' && !toline)
747 luaL_addchar(b, '\0');
748 else
749 luaL_addchar(b, *s);
750 s++;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200751 }
752}
753
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200754 static void
755luaV_pushline(lua_State *L, buf_T *buf, linenr_T n)
756{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200757 const char *s = (const char *) ml_get_buf(buf, n, FALSE);
758 luaL_Buffer b;
759 luaL_buffinit(L, &b);
760 luaV_addlstring(&b, s, strlen(s), 0);
761 luaL_pushresult(&b);
762}
763
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200764 static char_u *
765luaV_toline(lua_State *L, int pos)
766{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200767 size_t l;
768 const char *s = lua_tolstring(L, pos, &l);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200769
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200770 luaL_Buffer b;
771 luaL_buffinit(L, &b);
772 luaV_addlstring(&b, s, l, 1);
773 luaL_pushresult(&b);
774 return (char_u *) lua_tostring(L, -1);
775}
776
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100777/*
778 * pops a string s from the top of the stack and calls mf(t) for pieces t of
779 * s separated by newlines
780 */
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200781 static void
782luaV_msgfunc(lua_State *L, msgfunc_T mf)
783{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200784 luaL_Buffer b;
785 size_t l;
786 const char *p, *s = lua_tolstring(L, -1, &l);
787 luaL_buffinit(L, &b);
788 luaV_addlstring(&b, s, l, 0);
789 luaL_pushresult(&b);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100790 // break string
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200791 p = s = lua_tolstring(L, -1, &l);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200792 while (l--)
793 {
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100794 if (*p++ == '\0') // break?
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200795 {
Bram Moolenaarc8970b92020-10-26 20:18:08 +0100796 mf((char *)s);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200797 s = p;
798 }
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200799 }
Bram Moolenaarc8970b92020-10-26 20:18:08 +0100800 mf((char *)s);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100801 lua_pop(L, 2); // original and modified strings
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200802}
803
Bram Moolenaar1dced572012-04-05 16:54:08 +0200804#define luaV_newtype(typ,tname,luatyp,luatname) \
805 static luatyp * \
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100806 luaV_new##tname(lua_State *L, typ *obj) \
Bram Moolenaar1dced572012-04-05 16:54:08 +0200807 { \
808 luatyp *o = (luatyp *) lua_newuserdata(L, sizeof(luatyp)); \
809 *o = obj; \
810 luaV_setudata(L, obj); /* cache[obj] = udata */ \
811 luaV_getfield(L, luatname); \
812 lua_setmetatable(L, -2); \
813 return o; \
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200814 }
Bram Moolenaar1dced572012-04-05 16:54:08 +0200815
816#define luaV_pushtype(typ,tname,luatyp) \
817 static luatyp * \
Bram Moolenaarca06da92018-07-01 15:12:05 +0200818 luaV_push##tname(lua_State *L, typ *obj) \
Bram Moolenaar1dced572012-04-05 16:54:08 +0200819 { \
820 luatyp *o = NULL; \
821 if (obj == NULL) \
822 lua_pushnil(L); \
823 else { \
824 luaV_getudata(L, obj); \
825 if (lua_isnil(L, -1)) /* not interned? */ \
826 { \
827 lua_pop(L, 1); \
828 o = luaV_new##tname(L, obj); \
829 } \
830 else \
831 o = (luatyp *) lua_touserdata(L, -1); \
832 } \
833 return o; \
834 }
835
836#define luaV_type_tostring(tname,luatname) \
837 static int \
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100838 luaV_##tname##_tostring(lua_State *L) \
Bram Moolenaar1dced572012-04-05 16:54:08 +0200839 { \
840 lua_pushfstring(L, "%s: %p", luatname, lua_touserdata(L, 1)); \
841 return 1; \
842 }
843
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100844// ======= List type =======
Bram Moolenaar1dced572012-04-05 16:54:08 +0200845
846 static luaV_List *
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100847luaV_newlist(lua_State *L, list_T *lis)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200848{
849 luaV_List *l = (luaV_List *) lua_newuserdata(L, sizeof(luaV_List));
850 *l = lis;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100851 lis->lv_refcount++; // reference in Lua
852 luaV_setudata(L, lis); // cache[lis] = udata
Bram Moolenaar1dced572012-04-05 16:54:08 +0200853 luaV_getfield(L, LUAVIM_LIST);
854 lua_setmetatable(L, -2);
855 return l;
856}
857
858luaV_pushtype(list_T, list, luaV_List)
859luaV_type_tostring(list, LUAVIM_LIST)
860
861 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100862luaV_list_len(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200863{
864 list_T *l = luaV_unbox(L, luaV_List, 1);
Bram Moolenaarb7828692019-03-23 13:57:02 +0100865 lua_pushinteger(L, (int) list_len(l));
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200866 return 1;
867}
868
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200869 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100870luaV_list_iter(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200871{
872 listitem_T *li = (listitem_T *) lua_touserdata(L, lua_upvalueindex(2));
873 if (li == NULL) return 0;
874 luaV_pushtypval(L, &li->li_tv);
875 lua_pushlightuserdata(L, (void *) li->li_next);
876 lua_replace(L, lua_upvalueindex(2));
877 return 1;
878}
879
880 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100881luaV_list_call(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200882{
883 list_T *l = luaV_unbox(L, luaV_List, 1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100884 lua_pushvalue(L, lua_upvalueindex(1)); // pass cache table along
Bram Moolenaar1dced572012-04-05 16:54:08 +0200885 lua_pushlightuserdata(L, (void *) l->lv_first);
886 lua_pushcclosure(L, luaV_list_iter, 2);
887 return 1;
888}
889
890 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100891luaV_list_index(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200892{
893 list_T *l = luaV_unbox(L, luaV_List, 1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100894 if (lua_isnumber(L, 2)) // list item?
Bram Moolenaar1dced572012-04-05 16:54:08 +0200895 {
Bram Moolenaarbd846172020-06-27 12:32:57 +0200896 long n = (long) luaL_checkinteger(L, 2);
897 listitem_T *li;
898
899 // Lua array index starts with 1 while Vim uses 0, subtract 1 to
900 // normalize.
901 n -= 1;
902 li = list_find(l, n);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200903 if (li == NULL)
904 lua_pushnil(L);
905 else
906 luaV_pushtypval(L, &li->li_tv);
907 }
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100908 else if (lua_isstring(L, 2)) // method?
Bram Moolenaar1dced572012-04-05 16:54:08 +0200909 {
910 const char *s = lua_tostring(L, 2);
911 if (strncmp(s, "add", 3) == 0
Bram Moolenaarb3766472013-04-15 13:49:21 +0200912 || strncmp(s, "insert", 6) == 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200913 {
914 lua_getmetatable(L, 1);
915 lua_getfield(L, -1, s);
916 }
917 else
918 lua_pushnil(L);
919 }
920 else
921 lua_pushnil(L);
922 return 1;
923}
924
925 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100926luaV_list_newindex(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200927{
928 list_T *l = luaV_unbox(L, luaV_List, 1);
929 long n = (long) luaL_checkinteger(L, 2);
930 listitem_T *li;
Bram Moolenaarbd846172020-06-27 12:32:57 +0200931
932 // Lua array index starts with 1 while Vim uses 0, subtract 1 to normalize.
933 n -= 1;
934
Bram Moolenaar1dced572012-04-05 16:54:08 +0200935 if (l->lv_lock)
936 luaL_error(L, "list is locked");
937 li = list_find(l, n);
Bram Moolenaara1f9f862020-06-28 22:41:26 +0200938 if (li == NULL)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200939 {
Bram Moolenaara1f9f862020-06-28 22:41:26 +0200940 if (!lua_isnil(L, 3))
941 {
942 typval_T v;
943 luaV_checktypval(L, 3, &v, "inserting list item");
944 if (list_insert_tv(l, &v, li) == FAIL)
945 luaL_error(L, "failed to add item to list");
946 clear_tv(&v);
947 }
Bram Moolenaar1dced572012-04-05 16:54:08 +0200948 }
949 else
950 {
Bram Moolenaara1f9f862020-06-28 22:41:26 +0200951 if (lua_isnil(L, 3)) // remove?
952 {
953 vimlist_remove(l, li, li);
954 listitem_free(l, li);
955 }
956 else
957 {
958 typval_T v;
959 luaV_checktypval(L, 3, &v, "setting list item");
960 clear_tv(&li->li_tv);
Bram Moolenaare49b8e82020-07-01 13:52:55 +0200961 li->li_tv = v;
Bram Moolenaara1f9f862020-06-28 22:41:26 +0200962 }
Bram Moolenaar1dced572012-04-05 16:54:08 +0200963 }
964 return 0;
965}
966
967 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100968luaV_list_add(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200969{
970 luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST);
971 list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis);
Bram Moolenaarb3766472013-04-15 13:49:21 +0200972 typval_T v;
Bram Moolenaar1dced572012-04-05 16:54:08 +0200973 if (l->lv_lock)
974 luaL_error(L, "list is locked");
Bram Moolenaarb3766472013-04-15 13:49:21 +0200975 lua_settop(L, 2);
Bram Moolenaarca06da92018-07-01 15:12:05 +0200976 luaV_checktypval(L, 2, &v, "adding list item");
Bram Moolenaarb3766472013-04-15 13:49:21 +0200977 if (list_append_tv(l, &v) == FAIL)
Bram Moolenaarca06da92018-07-01 15:12:05 +0200978 luaL_error(L, "failed to add item to list");
Bram Moolenaarb3766472013-04-15 13:49:21 +0200979 clear_tv(&v);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200980 lua_settop(L, 1);
981 return 1;
982}
983
984 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100985luaV_list_insert(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200986{
987 luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST);
988 list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis);
Bram Moolenaar46538ee2015-02-17 16:28:55 +0100989 long pos = (long) luaL_optinteger(L, 3, 0);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200990 listitem_T *li = NULL;
991 typval_T v;
992 if (l->lv_lock)
993 luaL_error(L, "list is locked");
994 if (pos < l->lv_len)
995 {
996 li = list_find(l, pos);
997 if (li == NULL)
998 luaL_error(L, "invalid position");
999 }
1000 lua_settop(L, 2);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001001 luaV_checktypval(L, 2, &v, "inserting list item");
Bram Moolenaarb3766472013-04-15 13:49:21 +02001002 if (list_insert_tv(l, &v, li) == FAIL)
Bram Moolenaarca06da92018-07-01 15:12:05 +02001003 luaL_error(L, "failed to add item to list");
Bram Moolenaarb3766472013-04-15 13:49:21 +02001004 clear_tv(&v);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001005 lua_settop(L, 1);
1006 return 1;
1007}
1008
1009static const luaL_Reg luaV_List_mt[] = {
1010 {"__tostring", luaV_list_tostring},
Bram Moolenaar1dced572012-04-05 16:54:08 +02001011 {"__len", luaV_list_len},
1012 {"__call", luaV_list_call},
1013 {"__index", luaV_list_index},
1014 {"__newindex", luaV_list_newindex},
1015 {"add", luaV_list_add},
1016 {"insert", luaV_list_insert},
1017 {NULL, NULL}
1018};
1019
1020
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001021// ======= Dict type =======
Bram Moolenaar1dced572012-04-05 16:54:08 +02001022
1023 static luaV_Dict *
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001024luaV_newdict(lua_State *L, dict_T *dic)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001025{
1026 luaV_Dict *d = (luaV_Dict *) lua_newuserdata(L, sizeof(luaV_Dict));
1027 *d = dic;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001028 dic->dv_refcount++; // reference in Lua
1029 luaV_setudata(L, dic); // cache[dic] = udata
Bram Moolenaar1dced572012-04-05 16:54:08 +02001030 luaV_getfield(L, LUAVIM_DICT);
1031 lua_setmetatable(L, -2);
1032 return d;
1033}
1034
1035luaV_pushtype(dict_T, dict, luaV_Dict)
1036luaV_type_tostring(dict, LUAVIM_DICT)
1037
1038 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001039luaV_dict_len(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001040{
1041 dict_T *d = luaV_unbox(L, luaV_Dict, 1);
Bram Moolenaarb7828692019-03-23 13:57:02 +01001042 lua_pushinteger(L, (int) dict_len(d));
Bram Moolenaar1dced572012-04-05 16:54:08 +02001043 return 1;
1044}
1045
1046 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001047luaV_dict_iter(lua_State *L UNUSED)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001048{
Bram Moolenaarfeeaa682013-02-14 22:19:51 +01001049#ifdef FEAT_EVAL
Bram Moolenaar1dced572012-04-05 16:54:08 +02001050 hashitem_T *hi = (hashitem_T *) lua_touserdata(L, lua_upvalueindex(2));
1051 int n = lua_tointeger(L, lua_upvalueindex(3));
1052 dictitem_T *di;
1053 if (n <= 0) return 0;
1054 while (HASHITEM_EMPTY(hi)) hi++;
1055 di = dict_lookup(hi);
1056 lua_pushstring(L, (char *) hi->hi_key);
1057 luaV_pushtypval(L, &di->di_tv);
1058 lua_pushlightuserdata(L, (void *) (hi + 1));
1059 lua_replace(L, lua_upvalueindex(2));
1060 lua_pushinteger(L, n - 1);
1061 lua_replace(L, lua_upvalueindex(3));
1062 return 2;
Bram Moolenaarfeeaa682013-02-14 22:19:51 +01001063#else
1064 return 0;
1065#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +02001066}
1067
1068 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001069luaV_dict_call(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001070{
1071 dict_T *d = luaV_unbox(L, luaV_Dict, 1);
1072 hashtab_T *ht = &d->dv_hashtab;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001073 lua_pushvalue(L, lua_upvalueindex(1)); // pass cache table along
Bram Moolenaar1dced572012-04-05 16:54:08 +02001074 lua_pushlightuserdata(L, (void *) ht->ht_array);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001075 lua_pushinteger(L, ht->ht_used); // # remaining items
Bram Moolenaar1dced572012-04-05 16:54:08 +02001076 lua_pushcclosure(L, luaV_dict_iter, 3);
1077 return 1;
1078}
1079
1080 static int
Bram Moolenaarca06da92018-07-01 15:12:05 +02001081luaV_dict_index(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001082{
1083 dict_T *d = luaV_unbox(L, luaV_Dict, 1);
1084 char_u *key = (char_u *) luaL_checkstring(L, 2);
1085 dictitem_T *di = dict_find(d, key, -1);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001086
Bram Moolenaar1dced572012-04-05 16:54:08 +02001087 if (di == NULL)
1088 lua_pushnil(L);
1089 else
Bram Moolenaarca06da92018-07-01 15:12:05 +02001090 {
Bram Moolenaar1dced572012-04-05 16:54:08 +02001091 luaV_pushtypval(L, &di->di_tv);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001092 if (di->di_tv.v_type == VAR_FUNC) // funcref?
Bram Moolenaarca06da92018-07-01 15:12:05 +02001093 {
1094 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, -1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001095 f->self = d; // keep "self" reference
Bram Moolenaarca06da92018-07-01 15:12:05 +02001096 d->dv_refcount++;
1097 }
1098 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02001099 return 1;
1100}
1101
1102 static int
Bram Moolenaarca06da92018-07-01 15:12:05 +02001103luaV_dict_newindex(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001104{
1105 dict_T *d = luaV_unbox(L, luaV_Dict, 1);
1106 char_u *key = (char_u *) luaL_checkstring(L, 2);
1107 dictitem_T *di;
Bram Moolenaare49b8e82020-07-01 13:52:55 +02001108 typval_T tv;
Bram Moolenaar713bf9e92019-03-16 16:38:41 +01001109
Bram Moolenaar1dced572012-04-05 16:54:08 +02001110 if (d->dv_lock)
1111 luaL_error(L, "dict is locked");
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001112 if (key == NULL)
1113 return 0;
1114 if (*key == NUL)
Bram Moolenaarca06da92018-07-01 15:12:05 +02001115 luaL_error(L, "empty key");
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001116 if (!lua_isnil(L, 3)) // read value?
Bram Moolenaar17413672018-07-14 20:49:42 +02001117 {
Bram Moolenaare49b8e82020-07-01 13:52:55 +02001118 luaV_checktypval(L, 3, &tv, "setting dict item");
1119 if (d->dv_scope == VAR_DEF_SCOPE && tv.v_type == VAR_FUNC)
1120 {
1121 clear_tv(&tv);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001122 luaL_error(L, "cannot assign funcref to builtin scope");
Bram Moolenaare49b8e82020-07-01 13:52:55 +02001123 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02001124 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02001125 di = dict_find(d, key, -1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001126 if (di == NULL) // non-existing key?
Bram Moolenaar1dced572012-04-05 16:54:08 +02001127 {
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001128 if (lua_isnil(L, 3))
1129 return 0;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001130 di = dictitem_alloc(key);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001131 if (di == NULL)
Bram Moolenaare49b8e82020-07-01 13:52:55 +02001132 {
1133 clear_tv(&tv);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001134 return 0;
Bram Moolenaare49b8e82020-07-01 13:52:55 +02001135 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02001136 if (dict_add(d, di) == FAIL)
1137 {
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001138 vim_free(di);
Bram Moolenaare49b8e82020-07-01 13:52:55 +02001139 clear_tv(&tv);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001140 return 0;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001141 }
1142 }
1143 else
1144 clear_tv(&di->di_tv);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001145 if (lua_isnil(L, 3)) // remove?
Bram Moolenaar1dced572012-04-05 16:54:08 +02001146 {
1147 hashitem_T *hi = hash_find(&d->dv_hashtab, di->di_key);
1148 hash_remove(&d->dv_hashtab, hi);
1149 dictitem_free(di);
1150 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02001151 else
Bram Moolenaare49b8e82020-07-01 13:52:55 +02001152 di->di_tv = tv;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001153 return 0;
1154}
1155
1156static const luaL_Reg luaV_Dict_mt[] = {
1157 {"__tostring", luaV_dict_tostring},
Bram Moolenaar1dced572012-04-05 16:54:08 +02001158 {"__len", luaV_dict_len},
1159 {"__call", luaV_dict_call},
1160 {"__index", luaV_dict_index},
1161 {"__newindex", luaV_dict_newindex},
1162 {NULL, NULL}
1163};
1164
1165
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001166// ======= Blob type =======
Bram Moolenaarb7828692019-03-23 13:57:02 +01001167
1168 static luaV_Blob *
1169luaV_newblob(lua_State *L, blob_T *blo)
1170{
1171 luaV_Blob *b = (luaV_Blob *) lua_newuserdata(L, sizeof(luaV_Blob));
1172 *b = blo;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001173 blo->bv_refcount++; // reference in Lua
1174 luaV_setudata(L, blo); // cache[blo] = udata
Bram Moolenaarb7828692019-03-23 13:57:02 +01001175 luaV_getfield(L, LUAVIM_BLOB);
1176 lua_setmetatable(L, -2);
1177 return b;
1178}
1179
1180luaV_pushtype(blob_T, blob, luaV_Blob)
1181luaV_type_tostring(blob, LUAVIM_BLOB)
1182
1183 static int
1184luaV_blob_gc(lua_State *L)
1185{
1186 blob_T *b = luaV_unbox(L, luaV_Blob, 1);
1187 blob_unref(b);
1188 return 0;
1189}
1190
1191 static int
1192luaV_blob_len(lua_State *L)
1193{
1194 blob_T *b = luaV_unbox(L, luaV_Blob, 1);
1195 lua_pushinteger(L, (int) blob_len(b));
1196 return 1;
1197}
1198
1199 static int
1200luaV_blob_index(lua_State *L)
1201{
1202 blob_T *b = luaV_unbox(L, luaV_Blob, 1);
1203 if (lua_isnumber(L, 2))
1204 {
1205 int idx = luaL_checkinteger(L, 2);
1206 if (idx < blob_len(b))
1207 lua_pushnumber(L, (lua_Number) blob_get(b, idx));
1208 else
1209 lua_pushnil(L);
1210 }
1211 else if (lua_isstring(L, 2))
1212 {
1213 const char *s = lua_tostring(L, 2);
1214 if (strncmp(s, "add", 3) == 0)
1215 {
1216 lua_getmetatable(L, 1);
1217 lua_getfield(L, -1, s);
1218 }
1219 else
1220 lua_pushnil(L);
1221 }
1222 else
1223 lua_pushnil(L);
1224 return 1;
1225}
1226
1227 static int
1228luaV_blob_newindex(lua_State *L)
1229{
1230 blob_T *b = luaV_unbox(L, luaV_Blob, 1);
1231 if (b->bv_lock)
1232 luaL_error(L, "blob is locked");
1233 if (lua_isnumber(L, 2))
1234 {
1235 long len = blob_len(b);
1236 int idx = luaL_checkinteger(L, 2);
1237 int val = luaL_checkinteger(L, 3);
1238 if (idx < len || (idx == len && ga_grow(&b->bv_ga, 1) == OK))
1239 {
1240 blob_set(b, idx, (char_u) val);
1241 if (idx == len)
1242 ++b->bv_ga.ga_len;
1243 }
1244 else
1245 luaL_error(L, "index out of range");
1246 }
1247 return 0;
1248}
1249
1250 static int
1251luaV_blob_add(lua_State *L)
1252{
1253 luaV_Blob *blo = luaV_checkudata(L, 1, LUAVIM_BLOB);
1254 blob_T *b = (blob_T *) luaV_checkcache(L, (void *) *blo);
1255 if (b->bv_lock)
1256 luaL_error(L, "blob is locked");
1257 lua_settop(L, 2);
1258 if (!lua_isstring(L, 2))
1259 luaL_error(L, "string expected, got %s", luaL_typename(L, 2));
1260 else
1261 {
1262 size_t i, l = 0;
1263 const char *s = lua_tolstring(L, 2, &l);
1264
Bram Moolenaar5f1d3ae2020-02-11 22:37:35 +01001265 if (ga_grow(&b->bv_ga, (int)l) == OK)
Bram Moolenaar6fb5c972019-03-26 21:44:20 +01001266 for (i = 0; i < l; ++i)
1267 ga_append(&b->bv_ga, s[i]);
Bram Moolenaarb7828692019-03-23 13:57:02 +01001268 }
1269 lua_settop(L, 1);
1270 return 1;
1271}
1272
1273static const luaL_Reg luaV_Blob_mt[] = {
1274 {"__tostring", luaV_blob_tostring},
1275 {"__gc", luaV_blob_gc},
1276 {"__len", luaV_blob_len},
1277 {"__index", luaV_blob_index},
1278 {"__newindex", luaV_blob_newindex},
1279 {"add", luaV_blob_add},
1280 {NULL, NULL}
1281};
1282
1283
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001284// ======= Funcref type =======
Bram Moolenaarca06da92018-07-01 15:12:05 +02001285
1286 static luaV_Funcref *
1287luaV_newfuncref(lua_State *L, char_u *name)
1288{
1289 luaV_Funcref *f = (luaV_Funcref *)lua_newuserdata(L, sizeof(luaV_Funcref));
1290
1291 if (name != NULL)
1292 {
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001293 func_ref(name);
1294 f->name = vim_strsave(name);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001295 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02001296 f->self = NULL;
1297 luaV_getfield(L, LUAVIM_FUNCREF);
1298 lua_setmetatable(L, -2);
1299 return f;
1300}
1301
1302 static luaV_Funcref *
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001303luaV_pushfuncref(lua_State *L, char_u *name)
Bram Moolenaarca06da92018-07-01 15:12:05 +02001304{
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001305 return luaV_newfuncref(L, name);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001306}
1307
1308
1309luaV_type_tostring(funcref, LUAVIM_FUNCREF)
1310
1311 static int
1312luaV_funcref_gc(lua_State *L)
1313{
1314 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
1315
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001316 func_unref(f->name);
1317 vim_free(f->name);
1318 // NOTE: Don't call "dict_unref(f->self)", because the dict of "f->self"
1319 // will be (or has been already) freed by Vim's garbage collection.
Bram Moolenaarca06da92018-07-01 15:12:05 +02001320 return 0;
1321}
1322
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001323// equivalent to string(funcref)
Bram Moolenaarca06da92018-07-01 15:12:05 +02001324 static int
1325luaV_funcref_len(lua_State *L)
1326{
1327 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
1328
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001329 lua_pushstring(L, (const char *) f->name);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001330 return 1;
1331}
1332
1333 static int
1334luaV_funcref_call(lua_State *L)
1335{
1336 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001337 int i, n = lua_gettop(L) - 1; // #args
1338 int status = FAIL;
1339 typval_T args;
1340 typval_T rettv;
Bram Moolenaarca06da92018-07-01 15:12:05 +02001341
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001342 args.v_type = VAR_LIST;
1343 args.vval.v_list = list_alloc();
1344 rettv.v_type = VAR_UNKNOWN; // as in clear_tv
1345 if (args.vval.v_list != NULL)
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001346 {
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001347 typval_T v;
1348
Bram Moolenaar17413672018-07-14 20:49:42 +02001349 for (i = 0; i < n; i++)
1350 {
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001351 luaV_checktypval(L, i + 2, &v, "calling funcref");
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001352 list_append_tv(args.vval.v_list, &v);
Bram Moolenaar713bf9e92019-03-16 16:38:41 +01001353 clear_tv(&v);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001354 }
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001355 status = func_call(f->name, &args, NULL, f->self, &rettv);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001356 if (status == OK)
1357 luaV_pushtypval(L, &rettv);
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001358 clear_tv(&args);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001359 clear_tv(&rettv);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001360 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02001361 if (status != OK)
1362 luaL_error(L, "cannot call funcref");
1363 return 1;
1364}
1365
1366static const luaL_Reg luaV_Funcref_mt[] = {
1367 {"__tostring", luaV_funcref_tostring},
1368 {"__gc", luaV_funcref_gc},
1369 {"__len", luaV_funcref_len},
1370 {"__call", luaV_funcref_call},
1371 {NULL, NULL}
1372};
1373
1374
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001375// ======= Buffer type =======
Bram Moolenaar1dced572012-04-05 16:54:08 +02001376
1377luaV_newtype(buf_T, buffer, luaV_Buffer, LUAVIM_BUFFER)
1378luaV_pushtype(buf_T, buffer, luaV_Buffer)
1379luaV_type_tostring(buffer, LUAVIM_BUFFER)
1380
1381 static int
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001382luaV_buffer_len(lua_State *L)
1383{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001384 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
1385 lua_pushinteger(L, b->b_ml.ml_line_count);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001386 return 1;
1387}
1388
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001389 static int
1390luaV_buffer_call(lua_State *L)
1391{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001392 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001393 lua_settop(L, 1);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001394 set_curbuf(b, DOBUF_SPLIT);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001395 return 1;
1396}
1397
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001398 static int
1399luaV_buffer_index(lua_State *L)
1400{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001401 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001402 linenr_T n = (linenr_T) lua_tointeger(L, 2);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001403 if (n > 0 && n <= b->b_ml.ml_line_count)
1404 luaV_pushline(L, b, n);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001405 else if (lua_isstring(L, 2))
1406 {
1407 const char *s = lua_tostring(L, 2);
1408 if (strncmp(s, "name", 4) == 0)
Bram Moolenaarfe08df42018-07-07 23:07:41 +02001409 lua_pushstring(L, (b->b_sfname == NULL)
1410 ? "" : (char *) b->b_sfname);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001411 else if (strncmp(s, "fname", 5) == 0)
Bram Moolenaarfe08df42018-07-07 23:07:41 +02001412 lua_pushstring(L, (b->b_ffname == NULL)
1413 ? "" : (char *) b->b_ffname);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001414 else if (strncmp(s, "number", 6) == 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001415 lua_pushinteger(L, b->b_fnum);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001416 // methods
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001417 else if (strncmp(s, "insert", 6) == 0
1418 || strncmp(s, "next", 4) == 0
1419 || strncmp(s, "previous", 8) == 0
1420 || strncmp(s, "isvalid", 7) == 0)
1421 {
1422 lua_getmetatable(L, 1);
1423 lua_getfield(L, -1, s);
1424 }
1425 else
1426 lua_pushnil(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001427 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001428 else
1429 lua_pushnil(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001430 return 1;
1431}
1432
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001433 static int
1434luaV_buffer_newindex(lua_State *L)
1435{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001436 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001437 linenr_T n = (linenr_T) luaL_checkinteger(L, 2);
1438#ifdef HAVE_SANDBOX
1439 luaV_checksandbox(L);
1440#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +02001441 if (n < 1 || n > b->b_ml.ml_line_count)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001442 luaL_error(L, "invalid line number");
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001443 if (lua_isnil(L, 3)) // delete line
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001444 {
1445 buf_T *buf = curbuf;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001446 curbuf = b;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001447 if (u_savedel(n, 1L) == FAIL)
1448 {
1449 curbuf = buf;
1450 luaL_error(L, "cannot save undo information");
1451 }
Bram Moolenaarca70c072020-05-30 20:30:46 +02001452 else if (ml_delete(n) == FAIL)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001453 {
1454 curbuf = buf;
1455 luaL_error(L, "cannot delete line");
1456 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02001457 else
1458 {
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001459 deleted_lines_mark(n, 1L);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001460 if (b == curwin->w_buffer) // fix cursor in current window?
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001461 {
1462 if (curwin->w_cursor.lnum >= n)
1463 {
1464 if (curwin->w_cursor.lnum > n)
1465 {
1466 curwin->w_cursor.lnum -= 1;
1467 check_cursor_col();
1468 }
Bram Moolenaare49b8e82020-07-01 13:52:55 +02001469 else
1470 check_cursor();
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001471 changed_cline_bef_curs();
1472 }
1473 invalidate_botline();
1474 }
1475 }
1476 curbuf = buf;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001477 }
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001478 else if (lua_isstring(L, 3)) // update line
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001479 {
1480 buf_T *buf = curbuf;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001481 curbuf = b;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001482 if (u_savesub(n) == FAIL)
1483 {
1484 curbuf = buf;
1485 luaL_error(L, "cannot save undo information");
1486 }
1487 else if (ml_replace(n, luaV_toline(L, 3), TRUE) == FAIL)
1488 {
1489 curbuf = buf;
1490 luaL_error(L, "cannot replace line");
1491 }
1492 else changed_bytes(n, 0);
1493 curbuf = buf;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001494 if (b == curwin->w_buffer)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001495 check_cursor_col();
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001496 }
1497 else
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001498 luaL_error(L, "wrong argument to change line");
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001499 return 0;
1500}
1501
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001502 static int
1503luaV_buffer_insert(lua_State *L)
1504{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001505 luaV_Buffer *lb = luaV_checkudata(L, 1, LUAVIM_BUFFER);
1506 buf_T *b = (buf_T *) luaV_checkcache(L, (void *) *lb);
1507 linenr_T last = b->b_ml.ml_line_count;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001508 linenr_T n = (linenr_T) luaL_optinteger(L, 3, last);
1509 buf_T *buf;
1510 luaL_checktype(L, 2, LUA_TSTRING);
1511#ifdef HAVE_SANDBOX
1512 luaV_checksandbox(L);
1513#endif
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001514 // fix insertion line
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001515 if (n < 0) n = 0;
1516 if (n > last) n = last;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001517 // insert
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001518 buf = curbuf;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001519 curbuf = b;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001520 if (u_save(n, n + 1) == FAIL)
1521 {
1522 curbuf = buf;
1523 luaL_error(L, "cannot save undo information");
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001524 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001525 else if (ml_append(n, luaV_toline(L, 2), 0, FALSE) == FAIL)
1526 {
1527 curbuf = buf;
1528 luaL_error(L, "cannot insert line");
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001529 }
1530 else
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001531 appended_lines_mark(n, 1L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001532 curbuf = buf;
1533 update_screen(VALID);
1534 return 0;
1535}
1536
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001537 static int
1538luaV_buffer_next(lua_State *L)
1539{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001540 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001541 buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b);
1542 luaV_pushbuffer(L, buf->b_next);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001543 return 1;
1544}
1545
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001546 static int
1547luaV_buffer_previous(lua_State *L)
1548{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001549 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001550 buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b);
1551 luaV_pushbuffer(L, buf->b_prev);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001552 return 1;
1553}
1554
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001555 static int
1556luaV_buffer_isvalid(lua_State *L)
1557{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001558 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001559 luaV_getudata(L, *b);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001560 lua_pushboolean(L, !lua_isnil(L, -1));
1561 return 1;
1562}
1563
1564static const luaL_Reg luaV_Buffer_mt[] = {
1565 {"__tostring", luaV_buffer_tostring},
1566 {"__len", luaV_buffer_len},
1567 {"__call", luaV_buffer_call},
1568 {"__index", luaV_buffer_index},
1569 {"__newindex", luaV_buffer_newindex},
1570 {"insert", luaV_buffer_insert},
1571 {"next", luaV_buffer_next},
1572 {"previous", luaV_buffer_previous},
1573 {"isvalid", luaV_buffer_isvalid},
1574 {NULL, NULL}
1575};
1576
1577
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001578// ======= Window type =======
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001579
Bram Moolenaar1dced572012-04-05 16:54:08 +02001580luaV_newtype(win_T, window, luaV_Window, LUAVIM_WINDOW)
1581luaV_pushtype(win_T, window, luaV_Window)
1582luaV_type_tostring(window, LUAVIM_WINDOW)
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001583
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001584 static int
1585luaV_window_call(lua_State *L)
1586{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001587 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001588 lua_settop(L, 1);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001589 win_goto(w);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001590 return 1;
1591}
1592
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001593 static int
1594luaV_window_index(lua_State *L)
1595{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001596 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001597 const char *s = luaL_checkstring(L, 2);
1598 if (strncmp(s, "buffer", 6) == 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001599 luaV_pushbuffer(L, w->w_buffer);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001600 else if (strncmp(s, "line", 4) == 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001601 lua_pushinteger(L, w->w_cursor.lnum);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001602 else if (strncmp(s, "col", 3) == 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001603 lua_pushinteger(L, w->w_cursor.col + 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001604 else if (strncmp(s, "width", 5) == 0)
Bram Moolenaar02631462017-09-22 15:20:32 +02001605 lua_pushinteger(L, w->w_width);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001606 else if (strncmp(s, "height", 6) == 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001607 lua_pushinteger(L, w->w_height);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001608 // methods
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001609 else if (strncmp(s, "next", 4) == 0
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001610 || strncmp(s, "previous", 8) == 0
1611 || strncmp(s, "isvalid", 7) == 0)
1612 {
1613 lua_getmetatable(L, 1);
1614 lua_getfield(L, -1, s);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001615 }
1616 else
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001617 lua_pushnil(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001618 return 1;
1619}
1620
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001621 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001622luaV_window_newindex(lua_State *L)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001623{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001624 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001625 const char *s = luaL_checkstring(L, 2);
1626 int v = luaL_checkinteger(L, 3);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001627 if (strncmp(s, "line", 4) == 0)
1628 {
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001629#ifdef HAVE_SANDBOX
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001630 luaV_checksandbox(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001631#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +02001632 if (v < 1 || v > w->w_buffer->b_ml.ml_line_count)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001633 luaL_error(L, "line out of range");
Bram Moolenaar1dced572012-04-05 16:54:08 +02001634 w->w_cursor.lnum = v;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001635 update_screen(VALID);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001636 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001637 else if (strncmp(s, "col", 3) == 0)
1638 {
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001639#ifdef HAVE_SANDBOX
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001640 luaV_checksandbox(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001641#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +02001642 w->w_cursor.col = v - 1;
Bram Moolenaar53901442018-07-25 22:02:36 +02001643 w->w_set_curswant = TRUE;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001644 update_screen(VALID);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001645 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001646 else if (strncmp(s, "width", 5) == 0)
1647 {
1648 win_T *win = curwin;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001649#ifdef FEAT_GUI
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001650 need_mouse_correct = TRUE;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001651#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +02001652 curwin = w;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001653 win_setwidth(v);
1654 curwin = win;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001655 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001656 else if (strncmp(s, "height", 6) == 0)
1657 {
1658 win_T *win = curwin;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001659#ifdef FEAT_GUI
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001660 need_mouse_correct = TRUE;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001661#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +02001662 curwin = w;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001663 win_setheight(v);
1664 curwin = win;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001665 }
1666 else
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001667 luaL_error(L, "invalid window property: `%s'", s);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001668 return 0;
1669}
1670
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001671 static int
1672luaV_window_next(lua_State *L)
1673{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001674 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001675 win_T *win = (win_T *) luaV_checkcache(L, (void *) *w);
1676 luaV_pushwindow(L, win->w_next);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001677 return 1;
1678}
1679
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001680 static int
1681luaV_window_previous(lua_State *L)
1682{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001683 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001684 win_T *win = (win_T *) luaV_checkcache(L, (void *) *w);
1685 luaV_pushwindow(L, win->w_prev);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001686 return 1;
1687}
1688
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001689 static int
1690luaV_window_isvalid(lua_State *L)
1691{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001692 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001693 luaV_getudata(L, *w);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001694 lua_pushboolean(L, !lua_isnil(L, -1));
1695 return 1;
1696}
1697
1698static const luaL_Reg luaV_Window_mt[] = {
1699 {"__tostring", luaV_window_tostring},
1700 {"__call", luaV_window_call},
1701 {"__index", luaV_window_index},
1702 {"__newindex", luaV_window_newindex},
1703 {"next", luaV_window_next},
1704 {"previous", luaV_window_previous},
1705 {"isvalid", luaV_window_isvalid},
1706 {NULL, NULL}
1707};
1708
1709
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001710// ======= Vim module =======
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001711
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001712 static int
1713luaV_print(lua_State *L)
1714{
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001715 int i, n = lua_gettop(L); // nargs
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001716 const char *s;
1717 size_t l;
1718 luaL_Buffer b;
1719 luaL_buffinit(L, &b);
1720 lua_getglobal(L, "tostring");
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001721 for (i = 1; i <= n; i++)
1722 {
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001723 lua_pushvalue(L, -1); // tostring
1724 lua_pushvalue(L, i); // arg
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001725 lua_call(L, 1, 1);
1726 s = lua_tolstring(L, -1, &l);
1727 if (s == NULL)
1728 return luaL_error(L, "cannot convert to string");
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001729 if (i > 1) luaL_addchar(&b, ' '); // use space instead of tab
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001730 luaV_addlstring(&b, s, l, 0);
1731 lua_pop(L, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001732 }
1733 luaL_pushresult(&b);
Bram Moolenaarb98678a2019-10-19 15:18:44 +02001734 if (!got_int)
1735 luaV_msg(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001736 return 0;
1737}
1738
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001739 static int
Bram Moolenaar38e2b062011-09-21 17:15:39 +02001740luaV_debug(lua_State *L)
1741{
1742 lua_settop(L, 0);
1743 lua_getglobal(L, "vim");
1744 lua_getfield(L, -1, "eval");
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001745 lua_remove(L, -2); // vim.eval at position 1
Bram Moolenaar38e2b062011-09-21 17:15:39 +02001746 for (;;)
1747 {
1748 const char *input;
1749 size_t l;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001750 lua_pushvalue(L, 1); // vim.eval
Bram Moolenaar38e2b062011-09-21 17:15:39 +02001751 lua_pushliteral(L, "input('lua_debug> ')");
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001752 lua_call(L, 1, 1); // return string
Bram Moolenaar38e2b062011-09-21 17:15:39 +02001753 input = lua_tolstring(L, -1, &l);
1754 if (l == 0 || strcmp(input, "cont") == 0)
1755 return 0;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001756 msg_putchar('\n'); // avoid outputting on input line
Bram Moolenaar38e2b062011-09-21 17:15:39 +02001757 if (luaL_loadbuffer(L, input, l, "=(debug command)")
1758 || lua_pcall(L, 0, 0, 0))
1759 luaV_emsg(L);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001760 lua_settop(L, 1); // remove eventual returns, but keep vim.eval
Bram Moolenaar38e2b062011-09-21 17:15:39 +02001761 }
1762}
1763
1764 static int
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001765luaV_command(lua_State *L)
1766{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001767 do_cmdline_cmd((char_u *) luaL_checkstring(L, 1));
1768 update_screen(VALID);
1769 return 0;
1770}
1771
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001772 static int
1773luaV_eval(lua_State *L)
1774{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001775 typval_T *tv = eval_expr((char_u *) luaL_checkstring(L, 1), NULL);
1776 if (tv == NULL) luaL_error(L, "invalid expression");
1777 luaV_pushtypval(L, tv);
Bram Moolenaarb3766472013-04-15 13:49:21 +02001778 free_tv(tv);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001779 return 1;
1780}
1781
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001782 static int
Bram Moolenaar0d2e4fc2010-07-18 12:35:47 +02001783luaV_beep(lua_State *L UNUSED)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001784{
Bram Moolenaar165bc692015-07-21 17:53:25 +02001785 vim_beep(BO_LANG);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001786 return 0;
1787}
1788
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001789 static int
1790luaV_line(lua_State *L)
1791{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001792 luaV_pushline(L, curbuf, curwin->w_cursor.lnum);
1793 return 1;
1794}
1795
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001796 static int
Bram Moolenaar1dced572012-04-05 16:54:08 +02001797luaV_list(lua_State *L)
1798{
Bram Moolenaarca06da92018-07-01 15:12:05 +02001799 list_T *l;
1800 int initarg = !lua_isnoneornil(L, 1);
1801
1802 if (initarg && lua_type(L, 1) != LUA_TTABLE)
1803 luaL_error(L, "table expected, got %s", luaL_typename(L, 1));
1804 l = list_alloc();
Bram Moolenaar1dced572012-04-05 16:54:08 +02001805 if (l == NULL)
1806 lua_pushnil(L);
1807 else
Bram Moolenaarca06da92018-07-01 15:12:05 +02001808 {
Bram Moolenaar1dced572012-04-05 16:54:08 +02001809 luaV_newlist(L, l);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001810 if (initarg) // traverse table to init list
Bram Moolenaar17413672018-07-14 20:49:42 +02001811 {
Bram Moolenaarca06da92018-07-01 15:12:05 +02001812 int notnil, i = 0;
1813 typval_T v;
Bram Moolenaar17413672018-07-14 20:49:42 +02001814 do
1815 {
Bram Moolenaarca06da92018-07-01 15:12:05 +02001816 lua_rawgeti(L, 1, ++i);
1817 notnil = !lua_isnil(L, -1);
Bram Moolenaar17413672018-07-14 20:49:42 +02001818 if (notnil)
1819 {
Bram Moolenaarca06da92018-07-01 15:12:05 +02001820 luaV_checktypval(L, -1, &v, "vim.list");
1821 list_append_tv(l, &v);
Bram Moolenaar713bf9e92019-03-16 16:38:41 +01001822 clear_tv(&v);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001823 }
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001824 lua_pop(L, 1); // value
Bram Moolenaarca06da92018-07-01 15:12:05 +02001825 } while (notnil);
1826 }
1827 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02001828 return 1;
1829}
1830
1831 static int
1832luaV_dict(lua_State *L)
1833{
Bram Moolenaarca06da92018-07-01 15:12:05 +02001834 dict_T *d;
1835 int initarg = !lua_isnoneornil(L, 1);
1836
1837 if (initarg && lua_type(L, 1) != LUA_TTABLE)
1838 luaL_error(L, "table expected, got %s", luaL_typename(L, 1));
1839 d = dict_alloc();
Bram Moolenaar1dced572012-04-05 16:54:08 +02001840 if (d == NULL)
1841 lua_pushnil(L);
1842 else
Bram Moolenaarca06da92018-07-01 15:12:05 +02001843 {
Bram Moolenaar1dced572012-04-05 16:54:08 +02001844 luaV_newdict(L, d);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001845 if (initarg) // traverse table to init dict
Bram Moolenaarca06da92018-07-01 15:12:05 +02001846 {
1847 lua_pushnil(L);
1848 while (lua_next(L, 1))
1849 {
1850 char_u *key;
1851 dictitem_T *di;
1852 typval_T v;
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001853
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001854 lua_pushvalue(L, -2); // dup key in case it's a number
Bram Moolenaarca06da92018-07-01 15:12:05 +02001855 key = (char_u *) lua_tostring(L, -1);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001856 if (key == NULL)
1857 {
1858 lua_pushnil(L);
1859 return 1;
1860 }
1861 if (*key == NUL)
Bram Moolenaarca06da92018-07-01 15:12:05 +02001862 luaL_error(L, "table has empty key");
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001863 luaV_checktypval(L, -2, &v, "vim.dict"); // value
Bram Moolenaarca06da92018-07-01 15:12:05 +02001864 di = dictitem_alloc(key);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001865 if (di == NULL || dict_add(d, di) == FAIL)
1866 {
Bram Moolenaarca06da92018-07-01 15:12:05 +02001867 vim_free(di);
1868 lua_pushnil(L);
1869 return 1;
1870 }
Bram Moolenaare49b8e82020-07-01 13:52:55 +02001871 di->di_tv = v;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001872 lua_pop(L, 2); // key copy and value
Bram Moolenaarca06da92018-07-01 15:12:05 +02001873 }
1874 }
1875 }
1876 return 1;
1877}
1878
1879 static int
Bram Moolenaarb7828692019-03-23 13:57:02 +01001880luaV_blob(lua_State *L)
1881{
1882 blob_T *b;
1883 int initarg = !lua_isnoneornil(L, 1);
1884
1885 if (initarg && !lua_isstring(L, 1))
1886 luaL_error(L, "string expected, got %s", luaL_typename(L, 1));
1887 b = blob_alloc();
1888 if (b == NULL)
1889 lua_pushnil(L);
1890 else
1891 {
1892 luaV_newblob(L, b);
1893 if (initarg)
1894 {
1895 size_t i, l = 0;
1896 const char *s = lua_tolstring(L, 1, &l);
1897
Bram Moolenaar5f1d3ae2020-02-11 22:37:35 +01001898 if (ga_grow(&b->bv_ga, (int)l) == OK)
Bram Moolenaar6fb5c972019-03-26 21:44:20 +01001899 for (i = 0; i < l; ++i)
1900 ga_append(&b->bv_ga, s[i]);
Bram Moolenaarb7828692019-03-23 13:57:02 +01001901 }
1902 }
1903 return 1;
1904}
1905
1906 static int
Bram Moolenaarca06da92018-07-01 15:12:05 +02001907luaV_funcref(lua_State *L)
1908{
1909 const char *name = luaL_checkstring(L, 1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001910 // note: not checking if function exists (needs function_exists)
Bram Moolenaarca06da92018-07-01 15:12:05 +02001911 if (name == NULL || *name == NUL || VIM_ISDIGIT(*name))
1912 luaL_error(L, "invalid function name: %s", name);
1913 luaV_newfuncref(L, (char_u *) name);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001914 return 1;
1915}
1916
1917 static int
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001918luaV_buffer(lua_State *L)
1919{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001920 buf_T *buf;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001921 if (lua_isstring(L, 1)) // get by number or name?
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001922 {
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001923 if (lua_isnumber(L, 1)) // by number?
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001924 {
1925 int n = lua_tointeger(L, 1);
Bram Moolenaar29323592016-07-24 22:04:11 +02001926 FOR_ALL_BUFFERS(buf)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001927 if (buf->b_fnum == n) break;
1928 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02001929 else // by name
1930 {
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001931 size_t l;
1932 const char *s = lua_tolstring(L, 1, &l);
Bram Moolenaar29323592016-07-24 22:04:11 +02001933 FOR_ALL_BUFFERS(buf)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001934 {
1935 if (buf->b_ffname == NULL || buf->b_sfname == NULL)
1936 {
1937 if (l == 0) break;
1938 }
Bram Moolenaar0d2e4fc2010-07-18 12:35:47 +02001939 else if (strncmp(s, (char *)buf->b_ffname, l) == 0
1940 || strncmp(s, (char *)buf->b_sfname, l) == 0)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001941 break;
1942 }
1943 }
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001944 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02001945 else
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001946 buf = (lua_toboolean(L, 1)) ? firstbuf : curbuf; // first buffer?
Bram Moolenaar1dced572012-04-05 16:54:08 +02001947 luaV_pushbuffer(L, buf);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001948 return 1;
1949}
1950
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001951 static int
1952luaV_window(lua_State *L)
1953{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001954 win_T *win;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001955 if (lua_isnumber(L, 1)) // get by number?
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001956 {
1957 int n = lua_tointeger(L, 1);
1958 for (win = firstwin; win != NULL; win = win->w_next, n--)
1959 if (n == 1) break;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001960 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02001961 else
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001962 win = (lua_toboolean(L, 1)) ? firstwin : curwin; // first window?
Bram Moolenaar1dced572012-04-05 16:54:08 +02001963 luaV_pushwindow(L, win);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001964 return 1;
1965}
1966
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001967 static int
1968luaV_open(lua_State *L)
1969{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001970 char_u *s = NULL;
1971#ifdef HAVE_SANDBOX
1972 luaV_checksandbox(L);
1973#endif
1974 if (lua_isstring(L, 1)) s = (char_u *) lua_tostring(L, 1);
Bram Moolenaarfa263a52011-12-08 16:00:16 +01001975 luaV_pushbuffer(L, buflist_new(s, NULL, 1L, BLN_LISTED));
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001976 return 1;
1977}
1978
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001979 static int
Bram Moolenaar1dced572012-04-05 16:54:08 +02001980luaV_type(lua_State *L)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001981{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001982 luaL_checkany(L, 1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001983 if (lua_type(L, 1) == LUA_TUSERDATA) // check vim udata?
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001984 {
Bram Moolenaar1dced572012-04-05 16:54:08 +02001985 lua_settop(L, 1);
1986 if (lua_getmetatable(L, 1))
1987 {
1988 luaV_getfield(L, LUAVIM_LIST);
1989 if (lua_rawequal(L, -1, 2))
1990 {
1991 lua_pushstring(L, "list");
1992 return 1;
1993 }
1994 luaV_getfield(L, LUAVIM_DICT);
1995 if (lua_rawequal(L, -1, 2))
1996 {
1997 lua_pushstring(L, "dict");
1998 return 1;
1999 }
Bram Moolenaarb7828692019-03-23 13:57:02 +01002000 luaV_getfield(L, LUAVIM_BLOB);
2001 if (lua_rawequal(L, -1, 2))
2002 {
2003 lua_pushstring(L, "blob");
2004 return 1;
2005 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02002006 luaV_getfield(L, LUAVIM_FUNCREF);
2007 if (lua_rawequal(L, -1, 2))
2008 {
2009 lua_pushstring(L, "funcref");
2010 return 1;
2011 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02002012 luaV_getfield(L, LUAVIM_BUFFER);
2013 if (lua_rawequal(L, -1, 2))
2014 {
2015 lua_pushstring(L, "buffer");
2016 return 1;
2017 }
2018 luaV_getfield(L, LUAVIM_WINDOW);
2019 if (lua_rawequal(L, -1, 2))
2020 {
2021 lua_pushstring(L, "window");
2022 return 1;
2023 }
2024 }
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002025 }
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002026 lua_pushstring(L, luaL_typename(L, 1)); // fallback
Bram Moolenaar1dced572012-04-05 16:54:08 +02002027 return 1;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002028}
2029
Bram Moolenaareb04f082020-05-17 14:32:35 +02002030 static int
2031luaV_call(lua_State *L)
2032{
2033 int argc = lua_gettop(L) - 1;
2034 size_t funcname_len;
2035 char_u *funcname;
2036 char *error = NULL;
2037 typval_T rettv;
2038 typval_T argv[MAX_FUNC_ARGS + 1];
2039 int i = 0;
2040
2041 if (argc > MAX_FUNC_ARGS)
2042 return luaL_error(L, "Function called with too many arguments");
2043
2044 funcname = (char_u *)luaL_checklstring(L, 1, &funcname_len);
2045
2046 for (; i < argc; i++)
2047 {
2048 if (luaV_totypval(L, i + 2, &argv[i]) == FAIL)
2049 {
2050 error = "lua: cannot convert value";
2051 goto free_vim_args;
2052 }
2053 }
2054
2055 argv[argc].v_type = VAR_UNKNOWN;
2056
2057 if (call_vim_function(funcname, argc, argv, &rettv) == FAIL)
2058 {
2059 error = "lua: call_vim_function failed";
2060 goto free_vim_args;
2061 }
2062
2063 luaV_pushtypval(L, &rettv);
2064 clear_tv(&rettv);
2065
2066free_vim_args:
2067 while (i > 0)
2068 clear_tv(&argv[--i]);
2069
2070 if (error == NULL)
2071 return 1;
2072 else
2073 return luaL_error(L, error);
2074}
2075
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002076static const luaL_Reg luaV_module[] = {
2077 {"command", luaV_command},
2078 {"eval", luaV_eval},
2079 {"beep", luaV_beep},
2080 {"line", luaV_line},
Bram Moolenaar1dced572012-04-05 16:54:08 +02002081 {"list", luaV_list},
2082 {"dict", luaV_dict},
Bram Moolenaarb7828692019-03-23 13:57:02 +01002083 {"blob", luaV_blob},
Bram Moolenaarca06da92018-07-01 15:12:05 +02002084 {"funcref", luaV_funcref},
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002085 {"buffer", luaV_buffer},
2086 {"window", luaV_window},
2087 {"open", luaV_open},
Bram Moolenaar1dced572012-04-05 16:54:08 +02002088 {"type", luaV_type},
Bram Moolenaareb04f082020-05-17 14:32:35 +02002089 {"call", luaV_call},
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002090 {NULL, NULL}
2091};
2092
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002093/*
2094 * for freeing list, dict, buffer and window objects; lightuserdata as arg
2095 */
Bram Moolenaar1dced572012-04-05 16:54:08 +02002096 static int
2097luaV_free(lua_State *L)
2098{
2099 lua_pushnil(L);
2100 luaV_setudata(L, lua_touserdata(L, 1));
2101 return 0;
2102}
2103
2104 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002105luaV_luaeval(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +02002106{
2107 luaL_Buffer b;
2108 size_t l;
2109 const char *str = lua_tolstring(L, 1, &l);
2110 typval_T *arg = (typval_T *) lua_touserdata(L, 2);
2111 typval_T *rettv = (typval_T *) lua_touserdata(L, 3);
2112 luaL_buffinit(L, &b);
2113 luaL_addlstring(&b, LUAVIM_EVALHEADER, sizeof(LUAVIM_EVALHEADER) - 1);
2114 luaL_addlstring(&b, str, l);
2115 luaL_pushresult(&b);
2116 str = lua_tolstring(L, -1, &l);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002117 if (luaL_loadbuffer(L, str, l, LUAVIM_EVALNAME)) // compile error?
Bram Moolenaar1dced572012-04-05 16:54:08 +02002118 {
2119 luaV_emsg(L);
2120 return 0;
2121 }
2122 luaV_pushtypval(L, arg);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002123 if (lua_pcall(L, 1, 1, 0)) // running error?
Bram Moolenaar1dced572012-04-05 16:54:08 +02002124 {
2125 luaV_emsg(L);
2126 return 0;
2127 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02002128 if (luaV_totypval(L, -1, rettv) == FAIL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002129 emsg("luaeval: cannot convert value");
Bram Moolenaarf554a322015-02-04 23:08:01 +01002130 return 0;
Bram Moolenaar1dced572012-04-05 16:54:08 +02002131}
2132
2133 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002134luaV_setref(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +02002135{
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002136 int copyID = lua_tointeger(L, 1);
2137 int abort = FALSE;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01002138
Bram Moolenaar1dced572012-04-05 16:54:08 +02002139 luaV_getfield(L, LUAVIM_LIST);
2140 luaV_getfield(L, LUAVIM_DICT);
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002141 luaV_getfield(L, LUAVIM_FUNCREF);
Bram Moolenaar1dced572012-04-05 16:54:08 +02002142 lua_pushnil(L);
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002143 // traverse cache table
Bram Moolenaarb84634d2015-02-04 22:02:37 +01002144 while (!abort && lua_next(L, lua_upvalueindex(1)) != 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +02002145 {
2146 lua_getmetatable(L, -1);
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002147 if (lua_rawequal(L, -1, 2)) // list?
Bram Moolenaar1dced572012-04-05 16:54:08 +02002148 {
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002149 list_T *l = (list_T *)lua_touserdata(L, 5); // key
2150
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02002151 abort = set_ref_in_list(l, copyID);
Bram Moolenaar1dced572012-04-05 16:54:08 +02002152 }
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002153 else if (lua_rawequal(L, -1, 3)) // dict?
Bram Moolenaar1dced572012-04-05 16:54:08 +02002154 {
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002155 dict_T *d = (dict_T *)lua_touserdata(L, 5); // key
2156
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02002157 abort = set_ref_in_dict(d, copyID);
Bram Moolenaar1dced572012-04-05 16:54:08 +02002158 }
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002159 else if (lua_rawequal(L, -1, 4)) // funcref?
2160 {
2161 luaV_Funcref *f = (luaV_Funcref *)lua_touserdata(L, 5); // key
2162
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02002163 abort = set_ref_in_dict(f->self, copyID);
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002164 }
2165 lua_pop(L, 2); // metatable and value
Bram Moolenaar1dced572012-04-05 16:54:08 +02002166 }
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01002167 lua_pushinteger(L, abort);
Bram Moolenaarf554a322015-02-04 23:08:01 +01002168 return 1;
Bram Moolenaar1dced572012-04-05 16:54:08 +02002169}
2170
Bram Moolenaareb04f082020-05-17 14:32:35 +02002171#define LUA_VIM_FN_CODE \
Bram Moolenaar788fbb42020-05-31 14:08:12 +02002172 "vim.fn = setmetatable({}, {\n"\
2173 " __index = function (t, key)\n"\
2174 " local function _fn(...)\n"\
2175 " return vim.call(key, ...)\n"\
2176 " end\n"\
2177 " t[key] = _fn\n"\
2178 " return _fn\n"\
2179 " end\n"\
2180 " })"
2181
2182#define LUA_VIM_UPDATE_PACKAGE_PATHS \
2183 "local last_vim_paths = {}\n"\
2184 "vim._update_package_paths = function ()\n"\
2185 " local cur_vim_paths = {}\n"\
2186 " local function split(s, delimiter)\n"\
2187 " result = {}\n"\
2188 " for match in (s..delimiter):gmatch(\"(.-)\"..delimiter) do\n"\
2189 " table.insert(result, match)\n"\
2190 " end\n"\
2191 " return result\n"\
2192 " end\n"\
2193 " local rtps = split(vim.eval('&runtimepath'), ',')\n"\
2194 " local sep = package.config:sub(1, 1)\n"\
2195 " for _, key in ipairs({'path', 'cpath'}) do\n"\
2196 " local orig_str = package[key] .. ';'\n"\
2197 " local pathtrails_ordered = {}\n"\
2198 " -- Note: ignores trailing item without trailing `;`. Not using something\n"\
2199 " -- simpler in order to preserve empty items (stand for default path).\n"\
2200 " local orig = {}\n"\
2201 " for s in orig_str:gmatch('[^;]*;') do\n"\
2202 " s = s:sub(1, -2) -- Strip trailing semicolon\n"\
2203 " orig[#orig + 1] = s\n"\
2204 " end\n"\
2205 " if key == 'path' then\n"\
2206 " -- /?.lua and /?/init.lua\n"\
2207 " pathtrails_ordered = {sep .. '?.lua', sep .. '?' .. sep .. 'init.lua'}\n"\
2208 " else\n"\
2209 " local pathtrails = {}\n"\
2210 " for _, s in ipairs(orig) do\n"\
2211 " -- Find out path patterns. pathtrail should contain something like\n"\
2212 " -- /?.so, \?.dll. This allows not to bother determining what correct\n"\
2213 " -- suffixes are.\n"\
2214 " local pathtrail = s:match('[/\\\\][^/\\\\]*%?.*$')\n"\
2215 " if pathtrail and not pathtrails[pathtrail] then\n"\
2216 " pathtrails[pathtrail] = true\n"\
2217 " pathtrails_ordered[#pathtrails_ordered + 1] = pathtrail\n"\
2218 " end\n"\
2219 " end\n"\
2220 " end\n"\
2221 " local new = {}\n"\
2222 " for _, rtp in ipairs(rtps) do\n"\
2223 " if not rtp:match(';') then\n"\
2224 " for _, pathtrail in pairs(pathtrails_ordered) do\n"\
2225 " local new_path = rtp .. sep .. 'lua' .. pathtrail\n"\
2226 " -- Always keep paths from &runtimepath at the start:\n"\
2227 " -- append them here disregarding orig possibly containing one of them.\n"\
2228 " new[#new + 1] = new_path\n"\
2229 " cur_vim_paths[new_path] = true\n"\
2230 " end\n"\
2231 " end\n"\
2232 " end\n"\
2233 " for _, orig_path in ipairs(orig) do\n"\
2234 " -- Handle removing obsolete paths originating from &runtimepath: such\n"\
2235 " -- paths either belong to cur_nvim_paths and were already added above or\n"\
2236 " -- to last_nvim_paths and should not be added at all if corresponding\n"\
2237 " -- entry was removed from &runtimepath list.\n"\
2238 " if not (cur_vim_paths[orig_path] or last_vim_paths[orig_path]) then\n"\
2239 " new[#new + 1] = orig_path\n"\
2240 " end\n"\
2241 " end\n"\
2242 " package[key] = table.concat(new, ';')\n"\
2243 " end\n"\
2244 " last_vim_paths = cur_vim_paths\n"\
2245 "end"
Bram Moolenaareb04f082020-05-17 14:32:35 +02002246
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002247 static int
2248luaopen_vim(lua_State *L)
2249{
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002250 // set cache table
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002251 lua_newtable(L);
2252 lua_newtable(L);
Bram Moolenaar1dced572012-04-05 16:54:08 +02002253 lua_pushstring(L, "v");
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002254 lua_setfield(L, -2, "__mode");
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002255 lua_setmetatable(L, -2); // cache is weak-valued
2256 // print
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002257 lua_pushcfunction(L, luaV_print);
2258 lua_setglobal(L, "print");
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002259 // debug.debug
Bram Moolenaar38e2b062011-09-21 17:15:39 +02002260 lua_getglobal(L, "debug");
2261 lua_pushcfunction(L, luaV_debug);
2262 lua_setfield(L, -2, "debug");
2263 lua_pop(L, 1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002264 // free
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002265 lua_pushlightuserdata(L, (void *) LUAVIM_FREE);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002266 lua_pushvalue(L, 1); // cache table
Bram Moolenaar1dced572012-04-05 16:54:08 +02002267 lua_pushcclosure(L, luaV_free, 1);
2268 lua_rawset(L, LUA_REGISTRYINDEX);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002269 // luaeval
Bram Moolenaar1dced572012-04-05 16:54:08 +02002270 lua_pushlightuserdata(L, (void *) LUAVIM_LUAEVAL);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002271 lua_pushvalue(L, 1); // cache table
Bram Moolenaar1dced572012-04-05 16:54:08 +02002272 lua_pushcclosure(L, luaV_luaeval, 1);
2273 lua_rawset(L, LUA_REGISTRYINDEX);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002274 // setref
Bram Moolenaar1dced572012-04-05 16:54:08 +02002275 lua_pushlightuserdata(L, (void *) LUAVIM_SETREF);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002276 lua_pushvalue(L, 1); // cache table
Bram Moolenaar1dced572012-04-05 16:54:08 +02002277 lua_pushcclosure(L, luaV_setref, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002278 lua_rawset(L, LUA_REGISTRYINDEX);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002279 // register
Bram Moolenaar1dced572012-04-05 16:54:08 +02002280 luaV_newmetatable(L, LUAVIM_LIST);
2281 lua_pushvalue(L, 1);
2282 luaV_openlib(L, luaV_List_mt, 1);
2283 luaV_newmetatable(L, LUAVIM_DICT);
2284 lua_pushvalue(L, 1);
2285 luaV_openlib(L, luaV_Dict_mt, 1);
Bram Moolenaarb7828692019-03-23 13:57:02 +01002286 luaV_newmetatable(L, LUAVIM_BLOB);
2287 lua_pushvalue(L, 1);
2288 luaV_openlib(L, luaV_Blob_mt, 1);
Bram Moolenaarca06da92018-07-01 15:12:05 +02002289 luaV_newmetatable(L, LUAVIM_FUNCREF);
2290 lua_pushvalue(L, 1);
2291 luaV_openlib(L, luaV_Funcref_mt, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002292 luaV_newmetatable(L, LUAVIM_BUFFER);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002293 lua_pushvalue(L, 1); // cache table
Bram Moolenaar1dced572012-04-05 16:54:08 +02002294 luaV_openlib(L, luaV_Buffer_mt, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002295 luaV_newmetatable(L, LUAVIM_WINDOW);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002296 lua_pushvalue(L, 1); // cache table
Bram Moolenaar1dced572012-04-05 16:54:08 +02002297 luaV_openlib(L, luaV_Window_mt, 1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002298 lua_newtable(L); // vim table
2299 lua_pushvalue(L, 1); // cache table
Bram Moolenaar1dced572012-04-05 16:54:08 +02002300 luaV_openlib(L, luaV_module, 1);
2301 lua_setglobal(L, LUAVIM_NAME);
Bram Moolenaareb04f082020-05-17 14:32:35 +02002302 // custom code
Bram Moolenaar9309eb22020-05-17 16:53:56 +02002303 (void)luaL_dostring(L, LUA_VIM_FN_CODE);
Bram Moolenaar788fbb42020-05-31 14:08:12 +02002304 (void)luaL_dostring(L, LUA_VIM_UPDATE_PACKAGE_PATHS);
2305
2306 lua_getglobal(L, "vim");
2307 lua_getfield(L, -1, "_update_package_paths");
2308
2309 if (lua_pcall(L, 0, 0, 0))
2310 luaV_emsg(L);
2311
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002312 return 0;
2313}
2314
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002315 static lua_State *
2316luaV_newstate(void)
2317{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002318 lua_State *L = luaL_newstate();
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002319 luaL_openlibs(L); // core libs
2320 lua_pushcfunction(L, luaopen_vim); // vim
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002321 lua_call(L, 0, 0);
2322 return L;
2323}
2324
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002325 static void
2326luaV_setrange(lua_State *L, int line1, int line2)
2327{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002328 lua_getglobal(L, LUAVIM_NAME);
2329 lua_pushinteger(L, line1);
2330 lua_setfield(L, -2, "firstline");
2331 lua_pushinteger(L, line2);
2332 lua_setfield(L, -2, "lastline");
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002333 lua_pop(L, 1); // vim table
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002334}
2335
2336
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002337// ======= Interface =======
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002338
2339static lua_State *L = NULL;
2340
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002341 static int
Bram Moolenaar1dced572012-04-05 16:54:08 +02002342lua_isopen(void)
Bram Moolenaar2bd6a1b2010-08-12 22:14:01 +02002343{
2344 return L != NULL;
2345}
2346
2347 static int
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002348lua_init(void)
2349{
Bram Moolenaar1dced572012-04-05 16:54:08 +02002350 if (!lua_isopen())
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002351 {
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002352#ifdef DYNAMIC_LUA
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002353 if (!lua_enabled(TRUE))
2354 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002355 emsg(_("Lua library cannot be loaded."));
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002356 return FAIL;
2357 }
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002358#endif
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002359 L = luaV_newstate();
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002360 }
2361 return OK;
2362}
2363
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002364 void
2365lua_end(void)
2366{
Bram Moolenaar1dced572012-04-05 16:54:08 +02002367 if (lua_isopen())
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002368 {
2369 lua_close(L);
2370 L = NULL;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002371 }
2372}
2373
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002374/*
2375 * ex commands
2376 */
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002377 void
2378ex_lua(exarg_T *eap)
2379{
Bram Moolenaarc8970b92020-10-26 20:18:08 +01002380 char *script = (char *)script_get(eap, eap->arg);
2381
2382 if (!eap->skip && lua_init() == OK)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002383 {
Bram Moolenaarc8970b92020-10-26 20:18:08 +01002384 char *s = script != NULL ? script : (char *)eap->arg;
2385
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002386 luaV_setrange(L, eap->line1, eap->line2);
2387 if (luaL_loadbuffer(L, s, strlen(s), LUAVIM_CHUNKNAME)
2388 || lua_pcall(L, 0, 0, 0))
2389 luaV_emsg(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002390 }
Bram Moolenaarc8970b92020-10-26 20:18:08 +01002391 if (script != NULL)
2392 vim_free(script);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002393}
2394
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002395 void
2396ex_luado(exarg_T *eap)
2397{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002398 linenr_T l;
2399 const char *s = (const char *) eap->arg;
2400 luaL_Buffer b;
2401 size_t len;
Bram Moolenaard58f03b2017-01-29 22:48:45 +01002402 buf_T *was_curbuf = curbuf;
2403
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002404 if (lua_init() == FAIL) return;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002405 if (u_save(eap->line1 - 1, eap->line2 + 1) == FAIL)
2406 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002407 emsg(_("cannot save undo information"));
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002408 return;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002409 }
2410 luaV_setrange(L, eap->line1, eap->line2);
2411 luaL_buffinit(L, &b);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002412 luaL_addlstring(&b, "return function(line, linenr) ", 30); // header
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002413 luaL_addlstring(&b, s, strlen(s));
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002414 luaL_addlstring(&b, " end", 4); // footer
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002415 luaL_pushresult(&b);
2416 s = lua_tolstring(L, -1, &len);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002417 if (luaL_loadbuffer(L, s, len, LUAVIM_CHUNKNAME))
2418 {
2419 luaV_emsg(L);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002420 lua_pop(L, 1); // function body
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002421 return;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002422 }
2423 lua_call(L, 0, 1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002424 lua_replace(L, -2); // function -> body
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002425 for (l = eap->line1; l <= eap->line2; l++)
2426 {
Bram Moolenaare49b8e82020-07-01 13:52:55 +02002427 // Check the line number, the command may have deleted lines.
Bram Moolenaard58f03b2017-01-29 22:48:45 +01002428 if (l > curbuf->b_ml.ml_line_count)
2429 break;
2430
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002431 lua_pushvalue(L, -1); // function
2432 luaV_pushline(L, curbuf, l); // current line as arg
2433 lua_pushinteger(L, l); // current line number as arg
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +02002434 if (lua_pcall(L, 2, 1, 0))
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002435 {
2436 luaV_emsg(L);
2437 break;
2438 }
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002439 // Catch the command switching to another buffer.
Bram Moolenaard58f03b2017-01-29 22:48:45 +01002440 if (curbuf != was_curbuf)
2441 break;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002442 if (lua_isstring(L, -1)) // update line?
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002443 {
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002444#ifdef HAVE_SANDBOX
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002445 luaV_checksandbox(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002446#endif
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002447 ml_replace(l, luaV_toline(L, -1), TRUE);
2448 changed_bytes(l, 0);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002449 lua_pop(L, 1); // result from luaV_toline
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002450 }
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002451 lua_pop(L, 1); // line
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002452 }
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002453 lua_pop(L, 1); // function
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002454 check_cursor();
2455 update_screen(NOT_VALID);
2456}
2457
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002458 void
2459ex_luafile(exarg_T *eap)
2460{
2461 if (lua_init() == FAIL)
2462 return;
2463 if (!eap->skip)
2464 {
2465 luaV_setrange(L, eap->line1, eap->line2);
2466 if (luaL_loadfile(L, (char *) eap->arg) || lua_pcall(L, 0, 0, 0))
2467 luaV_emsg(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002468 }
2469}
2470
Bram Moolenaar1dced572012-04-05 16:54:08 +02002471#define luaV_freetype(typ,tname) \
2472 void \
2473 lua_##tname##_free(typ *o) \
2474 { \
2475 if (!lua_isopen()) return; \
2476 luaV_getfield(L, LUAVIM_FREE); \
2477 lua_pushlightuserdata(L, (void *) o); \
2478 lua_call(L, 1, 0); \
2479 }
2480
2481luaV_freetype(buf_T, buffer)
2482luaV_freetype(win_T, window)
2483
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002484 void
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002485do_luaeval(char_u *str, typval_T *arg, typval_T *rettv)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002486{
Bram Moolenaar1dced572012-04-05 16:54:08 +02002487 lua_init();
2488 luaV_getfield(L, LUAVIM_LUAEVAL);
2489 lua_pushstring(L, (char *) str);
2490 lua_pushlightuserdata(L, (void *) arg);
2491 lua_pushlightuserdata(L, (void *) rettv);
2492 lua_call(L, 3, 0);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002493}
2494
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01002495 int
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002496set_ref_in_lua(int copyID)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002497{
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01002498 int aborted = 0;
2499
2500 if (lua_isopen())
2501 {
2502 luaV_getfield(L, LUAVIM_SETREF);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002503 // call the function with 1 arg, getting 1 result back
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01002504 lua_pushinteger(L, copyID);
2505 lua_call(L, 1, 1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002506 // get the result
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01002507 aborted = lua_tointeger(L, -1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002508 // pop result off the stack
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01002509 lua_pop(L, 1);
2510 }
2511 return aborted;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002512}
2513
Bram Moolenaar788fbb42020-05-31 14:08:12 +02002514 void
2515update_package_paths_in_lua()
2516{
2517 if (lua_isopen())
2518 {
2519 lua_getglobal(L, "vim");
2520 lua_getfield(L, -1, "_update_package_paths");
2521
2522 if (lua_pcall(L, 0, 0, 0))
2523 luaV_emsg(L);
2524 }
2525}
2526
Bram Moolenaar801ab062020-06-25 19:27:56 +02002527/*
2528 * Native C function callback
2529 */
2530 static int
2531luaV_call_lua_func(
2532 int argcount,
2533 typval_T *argvars,
2534 typval_T *rettv,
2535 void *state)
2536{
2537 int i;
2538 int luaargcount = argcount;
2539 luaV_CFuncState *funcstate = (luaV_CFuncState*)state;
2540 lua_rawgeti(funcstate->L, LUA_REGISTRYINDEX, funcstate->lua_funcref);
2541
2542 if (funcstate->lua_tableref != LUA_NOREF)
2543 {
2544 // First arg for metatable __call method is a table
2545 luaargcount += 1;
2546 lua_rawgeti(funcstate->L, LUA_REGISTRYINDEX, funcstate->lua_tableref);
2547 }
2548
2549 for (i = 0; i < argcount; ++i)
2550 luaV_pushtypval(funcstate->L, &argvars[i]);
2551
2552 if (lua_pcall(funcstate->L, luaargcount, 1, 0))
2553 {
2554 luaV_emsg(funcstate->L);
2555 return FCERR_OTHER;
2556 }
2557
2558 luaV_checktypval(funcstate->L, -1, rettv, "get return value");
2559 return FCERR_NONE;
2560}
2561
2562/*
2563 * Free up any lua references held by the func state.
2564 */
2565 static void
2566luaV_call_lua_func_free(void *state)
2567{
2568 luaV_CFuncState *funcstate = (luaV_CFuncState*)state;
2569 luaL_unref(L, LUA_REGISTRYINDEX, funcstate->lua_funcref);
2570 funcstate->L = NULL;
2571 if (funcstate->lua_tableref != LUA_NOREF)
2572 luaL_unref(L, LUA_REGISTRYINDEX, funcstate->lua_tableref);
2573 VIM_CLEAR(funcstate);
2574}
2575
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002576#endif