blob: f25c47b53400ee768af06d47feec37138b5e63a4 [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 Moolenaar0ba04292010-07-14 23:23:17 +020036typedef void (*msgfunc_T)(char_u *);
37
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 Moolenaarb7828692019-03-23 13:57:02 +0100571 case VAR_BLOB:
572 luaV_pushblob(L, tv->vval.v_blob);
573 break;
Bram Moolenaar1dced572012-04-05 16:54:08 +0200574 default:
575 lua_pushnil(L);
576 }
577}
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200578
Bram Moolenaarca06da92018-07-01 15:12:05 +0200579/*
580 * Converts lua value at 'pos' to typval 'tv'.
581 * Returns OK or FAIL.
582 */
583 static int
584luaV_totypval(lua_State *L, int pos, typval_T *tv)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200585{
Bram Moolenaarca06da92018-07-01 15:12:05 +0200586 int status = OK;
587
Bram Moolenaara9a8e5f2020-07-02 21:17:57 +0200588 tv->v_lock = 0;
589
Bram Moolenaarca06da92018-07-01 15:12:05 +0200590 switch (lua_type(L, pos))
591 {
Bram Moolenaar1dced572012-04-05 16:54:08 +0200592 case LUA_TBOOLEAN:
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +0100593 tv->v_type = VAR_BOOL;
Bram Moolenaar1dced572012-04-05 16:54:08 +0200594 tv->vval.v_number = (varnumber_T) lua_toboolean(L, pos);
595 break;
Bram Moolenaar9067cd62019-01-01 00:41:54 +0100596 case LUA_TNIL:
597 tv->v_type = VAR_SPECIAL;
598 tv->vval.v_number = VVAL_NULL;
599 break;
Bram Moolenaar1dced572012-04-05 16:54:08 +0200600 case LUA_TSTRING:
601 tv->v_type = VAR_STRING;
602 tv->vval.v_string = vim_strsave((char_u *) lua_tostring(L, pos));
603 break;
604 case LUA_TNUMBER:
605#ifdef FEAT_FLOAT
Bram Moolenaareb04f082020-05-17 14:32:35 +0200606 {
607 const lua_Number n = lua_tonumber(L, pos);
608
609 if (n > (lua_Number)INT64_MAX || n < (lua_Number)INT64_MIN
610 || ((lua_Number)((varnumber_T)n)) != n)
611 {
612 tv->v_type = VAR_FLOAT;
613 tv->vval.v_float = (float_T)n;
614 }
615 else
616 {
617 tv->v_type = VAR_NUMBER;
618 tv->vval.v_number = (varnumber_T)n;
619 }
620 }
Bram Moolenaar1dced572012-04-05 16:54:08 +0200621#else
622 tv->v_type = VAR_NUMBER;
623 tv->vval.v_number = (varnumber_T) lua_tointeger(L, pos);
624#endif
625 break;
Bram Moolenaar801ab062020-06-25 19:27:56 +0200626 case LUA_TFUNCTION:
627 {
628 char_u *name;
629 lua_pushvalue(L, pos);
630 luaV_CFuncState *state = ALLOC_CLEAR_ONE(luaV_CFuncState);
631 state->lua_funcref = luaL_ref(L, LUA_REGISTRYINDEX);
632 state->L = L;
633 state->lua_tableref = LUA_NOREF;
634 name = register_cfunc(&luaV_call_lua_func,
635 &luaV_call_lua_func_free, state);
636 tv->v_type = VAR_FUNC;
637 tv->vval.v_string = vim_strsave(name);
638 break;
639 }
640 case LUA_TTABLE:
641 {
642 lua_pushvalue(L, pos);
643 int lua_tableref = luaL_ref(L, LUA_REGISTRYINDEX);
644 if (lua_getmetatable(L, pos)) {
645 lua_getfield(L, -1, LUA___CALL);
646 if (lua_isfunction(L, -1)) {
647 char_u *name;
648 int lua_funcref = luaL_ref(L, LUA_REGISTRYINDEX);
649 luaV_CFuncState *state = ALLOC_CLEAR_ONE(luaV_CFuncState);
650 state->lua_funcref = lua_funcref;
651 state->L = L;
652 state->lua_tableref = lua_tableref;
653 name = register_cfunc(&luaV_call_lua_func,
654 &luaV_call_lua_func_free, state);
655 tv->v_type = VAR_FUNC;
656 tv->vval.v_string = vim_strsave(name);
657 break;
658 }
659 }
660 tv->v_type = VAR_NUMBER;
661 tv->vval.v_number = 0;
662 status = FAIL;
663 break;
664 }
Bram Moolenaarca06da92018-07-01 15:12:05 +0200665 case LUA_TUSERDATA:
666 {
Bram Moolenaar1dced572012-04-05 16:54:08 +0200667 void *p = lua_touserdata(L, pos);
Bram Moolenaarca06da92018-07-01 15:12:05 +0200668
Bram Moolenaarb7828692019-03-23 13:57:02 +0100669 if (lua_getmetatable(L, pos)) // has metatable?
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200670 {
Bram Moolenaarb7828692019-03-23 13:57:02 +0100671 // check list
Bram Moolenaar1dced572012-04-05 16:54:08 +0200672 luaV_getfield(L, LUAVIM_LIST);
673 if (lua_rawequal(L, -1, -2))
Bram Moolenaar2334b6d2010-07-22 21:32:16 +0200674 {
Bram Moolenaar1dced572012-04-05 16:54:08 +0200675 tv->v_type = VAR_LIST;
676 tv->vval.v_list = *((luaV_List *) p);
677 ++tv->vval.v_list->lv_refcount;
Bram Moolenaarb7828692019-03-23 13:57:02 +0100678 lua_pop(L, 2); // MTs
Bram Moolenaarca06da92018-07-01 15:12:05 +0200679 break;
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200680 }
Bram Moolenaarb7828692019-03-23 13:57:02 +0100681 // check dict
Bram Moolenaar1dced572012-04-05 16:54:08 +0200682 luaV_getfield(L, LUAVIM_DICT);
683 if (lua_rawequal(L, -1, -3))
684 {
685 tv->v_type = VAR_DICT;
686 tv->vval.v_dict = *((luaV_Dict *) p);
687 ++tv->vval.v_dict->dv_refcount;
Bram Moolenaarb7828692019-03-23 13:57:02 +0100688 lua_pop(L, 3); // MTs
Bram Moolenaarca06da92018-07-01 15:12:05 +0200689 break;
Bram Moolenaar1dced572012-04-05 16:54:08 +0200690 }
Bram Moolenaarb7828692019-03-23 13:57:02 +0100691 // check blob
692 luaV_getfield(L, LUAVIM_BLOB);
Bram Moolenaarca06da92018-07-01 15:12:05 +0200693 if (lua_rawequal(L, -1, -4))
694 {
Bram Moolenaarb7828692019-03-23 13:57:02 +0100695 tv->v_type = VAR_BLOB;
696 tv->vval.v_blob = *((luaV_Blob *) p);
697 ++tv->vval.v_blob->bv_refcount;
698 lua_pop(L, 4); // MTs
699 break;
700 }
701 // check funcref
702 luaV_getfield(L, LUAVIM_FUNCREF);
703 if (lua_rawequal(L, -1, -5))
704 {
Bram Moolenaarca06da92018-07-01 15:12:05 +0200705 luaV_Funcref *f = (luaV_Funcref *) p;
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100706 func_ref(f->name);
707 tv->v_type = VAR_FUNC;
708 tv->vval.v_string = vim_strsave(f->name);
Bram Moolenaarb7828692019-03-23 13:57:02 +0100709 lua_pop(L, 5); // MTs
Bram Moolenaarca06da92018-07-01 15:12:05 +0200710 break;
711 }
Bram Moolenaarb7828692019-03-23 13:57:02 +0100712 lua_pop(L, 4); // MTs
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200713 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200714 }
Bram Moolenaarb7828692019-03-23 13:57:02 +0100715 // FALLTHROUGH
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200716 default:
Bram Moolenaar1dced572012-04-05 16:54:08 +0200717 tv->v_type = VAR_NUMBER;
718 tv->vval.v_number = 0;
Bram Moolenaarca06da92018-07-01 15:12:05 +0200719 status = FAIL;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200720 }
Bram Moolenaarca06da92018-07-01 15:12:05 +0200721 return status;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200722}
723
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100724/*
725 * similar to luaL_addlstring, but replaces \0 with \n if toline and
726 * \n with \0 otherwise
727 */
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200728 static void
729luaV_addlstring(luaL_Buffer *b, const char *s, size_t l, int toline)
730{
731 while (l--)
732 {
733 if (*s == '\0' && toline)
734 luaL_addchar(b, '\n');
735 else if (*s == '\n' && !toline)
736 luaL_addchar(b, '\0');
737 else
738 luaL_addchar(b, *s);
739 s++;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200740 }
741}
742
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200743 static void
744luaV_pushline(lua_State *L, buf_T *buf, linenr_T n)
745{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200746 const char *s = (const char *) ml_get_buf(buf, n, FALSE);
747 luaL_Buffer b;
748 luaL_buffinit(L, &b);
749 luaV_addlstring(&b, s, strlen(s), 0);
750 luaL_pushresult(&b);
751}
752
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200753 static char_u *
754luaV_toline(lua_State *L, int pos)
755{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200756 size_t l;
757 const char *s = lua_tolstring(L, pos, &l);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200758
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200759 luaL_Buffer b;
760 luaL_buffinit(L, &b);
761 luaV_addlstring(&b, s, l, 1);
762 luaL_pushresult(&b);
763 return (char_u *) lua_tostring(L, -1);
764}
765
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100766/*
767 * pops a string s from the top of the stack and calls mf(t) for pieces t of
768 * s separated by newlines
769 */
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200770 static void
771luaV_msgfunc(lua_State *L, msgfunc_T mf)
772{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200773 luaL_Buffer b;
774 size_t l;
775 const char *p, *s = lua_tolstring(L, -1, &l);
776 luaL_buffinit(L, &b);
777 luaV_addlstring(&b, s, l, 0);
778 luaL_pushresult(&b);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100779 // break string
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200780 p = s = lua_tolstring(L, -1, &l);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200781 while (l--)
782 {
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100783 if (*p++ == '\0') // break?
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200784 {
785 mf((char_u *) s);
786 s = p;
787 }
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200788 }
789 mf((char_u *) s);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100790 lua_pop(L, 2); // original and modified strings
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200791}
792
Bram Moolenaar1dced572012-04-05 16:54:08 +0200793#define luaV_newtype(typ,tname,luatyp,luatname) \
794 static luatyp * \
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100795 luaV_new##tname(lua_State *L, typ *obj) \
Bram Moolenaar1dced572012-04-05 16:54:08 +0200796 { \
797 luatyp *o = (luatyp *) lua_newuserdata(L, sizeof(luatyp)); \
798 *o = obj; \
799 luaV_setudata(L, obj); /* cache[obj] = udata */ \
800 luaV_getfield(L, luatname); \
801 lua_setmetatable(L, -2); \
802 return o; \
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200803 }
Bram Moolenaar1dced572012-04-05 16:54:08 +0200804
805#define luaV_pushtype(typ,tname,luatyp) \
806 static luatyp * \
Bram Moolenaarca06da92018-07-01 15:12:05 +0200807 luaV_push##tname(lua_State *L, typ *obj) \
Bram Moolenaar1dced572012-04-05 16:54:08 +0200808 { \
809 luatyp *o = NULL; \
810 if (obj == NULL) \
811 lua_pushnil(L); \
812 else { \
813 luaV_getudata(L, obj); \
814 if (lua_isnil(L, -1)) /* not interned? */ \
815 { \
816 lua_pop(L, 1); \
817 o = luaV_new##tname(L, obj); \
818 } \
819 else \
820 o = (luatyp *) lua_touserdata(L, -1); \
821 } \
822 return o; \
823 }
824
825#define luaV_type_tostring(tname,luatname) \
826 static int \
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100827 luaV_##tname##_tostring(lua_State *L) \
Bram Moolenaar1dced572012-04-05 16:54:08 +0200828 { \
829 lua_pushfstring(L, "%s: %p", luatname, lua_touserdata(L, 1)); \
830 return 1; \
831 }
832
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100833// ======= List type =======
Bram Moolenaar1dced572012-04-05 16:54:08 +0200834
835 static luaV_List *
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100836luaV_newlist(lua_State *L, list_T *lis)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200837{
838 luaV_List *l = (luaV_List *) lua_newuserdata(L, sizeof(luaV_List));
839 *l = lis;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100840 lis->lv_refcount++; // reference in Lua
841 luaV_setudata(L, lis); // cache[lis] = udata
Bram Moolenaar1dced572012-04-05 16:54:08 +0200842 luaV_getfield(L, LUAVIM_LIST);
843 lua_setmetatable(L, -2);
844 return l;
845}
846
847luaV_pushtype(list_T, list, luaV_List)
848luaV_type_tostring(list, LUAVIM_LIST)
849
850 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100851luaV_list_len(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200852{
853 list_T *l = luaV_unbox(L, luaV_List, 1);
Bram Moolenaarb7828692019-03-23 13:57:02 +0100854 lua_pushinteger(L, (int) list_len(l));
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200855 return 1;
856}
857
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200858 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100859luaV_list_iter(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200860{
861 listitem_T *li = (listitem_T *) lua_touserdata(L, lua_upvalueindex(2));
862 if (li == NULL) return 0;
863 luaV_pushtypval(L, &li->li_tv);
864 lua_pushlightuserdata(L, (void *) li->li_next);
865 lua_replace(L, lua_upvalueindex(2));
866 return 1;
867}
868
869 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100870luaV_list_call(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200871{
872 list_T *l = luaV_unbox(L, luaV_List, 1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100873 lua_pushvalue(L, lua_upvalueindex(1)); // pass cache table along
Bram Moolenaar1dced572012-04-05 16:54:08 +0200874 lua_pushlightuserdata(L, (void *) l->lv_first);
875 lua_pushcclosure(L, luaV_list_iter, 2);
876 return 1;
877}
878
879 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100880luaV_list_index(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200881{
882 list_T *l = luaV_unbox(L, luaV_List, 1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100883 if (lua_isnumber(L, 2)) // list item?
Bram Moolenaar1dced572012-04-05 16:54:08 +0200884 {
Bram Moolenaarbd846172020-06-27 12:32:57 +0200885 long n = (long) luaL_checkinteger(L, 2);
886 listitem_T *li;
887
888 // Lua array index starts with 1 while Vim uses 0, subtract 1 to
889 // normalize.
890 n -= 1;
891 li = list_find(l, n);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200892 if (li == NULL)
893 lua_pushnil(L);
894 else
895 luaV_pushtypval(L, &li->li_tv);
896 }
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100897 else if (lua_isstring(L, 2)) // method?
Bram Moolenaar1dced572012-04-05 16:54:08 +0200898 {
899 const char *s = lua_tostring(L, 2);
900 if (strncmp(s, "add", 3) == 0
Bram Moolenaarb3766472013-04-15 13:49:21 +0200901 || strncmp(s, "insert", 6) == 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200902 {
903 lua_getmetatable(L, 1);
904 lua_getfield(L, -1, s);
905 }
906 else
907 lua_pushnil(L);
908 }
909 else
910 lua_pushnil(L);
911 return 1;
912}
913
914 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100915luaV_list_newindex(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200916{
917 list_T *l = luaV_unbox(L, luaV_List, 1);
918 long n = (long) luaL_checkinteger(L, 2);
919 listitem_T *li;
Bram Moolenaarbd846172020-06-27 12:32:57 +0200920
921 // Lua array index starts with 1 while Vim uses 0, subtract 1 to normalize.
922 n -= 1;
923
Bram Moolenaar1dced572012-04-05 16:54:08 +0200924 if (l->lv_lock)
925 luaL_error(L, "list is locked");
926 li = list_find(l, n);
Bram Moolenaara1f9f862020-06-28 22:41:26 +0200927 if (li == NULL)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200928 {
Bram Moolenaara1f9f862020-06-28 22:41:26 +0200929 if (!lua_isnil(L, 3))
930 {
931 typval_T v;
932 luaV_checktypval(L, 3, &v, "inserting list item");
933 if (list_insert_tv(l, &v, li) == FAIL)
934 luaL_error(L, "failed to add item to list");
935 clear_tv(&v);
936 }
Bram Moolenaar1dced572012-04-05 16:54:08 +0200937 }
938 else
939 {
Bram Moolenaara1f9f862020-06-28 22:41:26 +0200940 if (lua_isnil(L, 3)) // remove?
941 {
942 vimlist_remove(l, li, li);
943 listitem_free(l, li);
944 }
945 else
946 {
947 typval_T v;
948 luaV_checktypval(L, 3, &v, "setting list item");
949 clear_tv(&li->li_tv);
Bram Moolenaare49b8e82020-07-01 13:52:55 +0200950 li->li_tv = v;
Bram Moolenaara1f9f862020-06-28 22:41:26 +0200951 }
Bram Moolenaar1dced572012-04-05 16:54:08 +0200952 }
953 return 0;
954}
955
956 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100957luaV_list_add(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200958{
959 luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST);
960 list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis);
Bram Moolenaarb3766472013-04-15 13:49:21 +0200961 typval_T v;
Bram Moolenaar1dced572012-04-05 16:54:08 +0200962 if (l->lv_lock)
963 luaL_error(L, "list is locked");
Bram Moolenaarb3766472013-04-15 13:49:21 +0200964 lua_settop(L, 2);
Bram Moolenaarca06da92018-07-01 15:12:05 +0200965 luaV_checktypval(L, 2, &v, "adding list item");
Bram Moolenaarb3766472013-04-15 13:49:21 +0200966 if (list_append_tv(l, &v) == FAIL)
Bram Moolenaarca06da92018-07-01 15:12:05 +0200967 luaL_error(L, "failed to add item to list");
Bram Moolenaarb3766472013-04-15 13:49:21 +0200968 clear_tv(&v);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200969 lua_settop(L, 1);
970 return 1;
971}
972
973 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100974luaV_list_insert(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200975{
976 luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST);
977 list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis);
Bram Moolenaar46538ee2015-02-17 16:28:55 +0100978 long pos = (long) luaL_optinteger(L, 3, 0);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200979 listitem_T *li = NULL;
980 typval_T v;
981 if (l->lv_lock)
982 luaL_error(L, "list is locked");
983 if (pos < l->lv_len)
984 {
985 li = list_find(l, pos);
986 if (li == NULL)
987 luaL_error(L, "invalid position");
988 }
989 lua_settop(L, 2);
Bram Moolenaarca06da92018-07-01 15:12:05 +0200990 luaV_checktypval(L, 2, &v, "inserting list item");
Bram Moolenaarb3766472013-04-15 13:49:21 +0200991 if (list_insert_tv(l, &v, li) == FAIL)
Bram Moolenaarca06da92018-07-01 15:12:05 +0200992 luaL_error(L, "failed to add item to list");
Bram Moolenaarb3766472013-04-15 13:49:21 +0200993 clear_tv(&v);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200994 lua_settop(L, 1);
995 return 1;
996}
997
998static const luaL_Reg luaV_List_mt[] = {
999 {"__tostring", luaV_list_tostring},
Bram Moolenaar1dced572012-04-05 16:54:08 +02001000 {"__len", luaV_list_len},
1001 {"__call", luaV_list_call},
1002 {"__index", luaV_list_index},
1003 {"__newindex", luaV_list_newindex},
1004 {"add", luaV_list_add},
1005 {"insert", luaV_list_insert},
1006 {NULL, NULL}
1007};
1008
1009
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001010// ======= Dict type =======
Bram Moolenaar1dced572012-04-05 16:54:08 +02001011
1012 static luaV_Dict *
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001013luaV_newdict(lua_State *L, dict_T *dic)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001014{
1015 luaV_Dict *d = (luaV_Dict *) lua_newuserdata(L, sizeof(luaV_Dict));
1016 *d = dic;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001017 dic->dv_refcount++; // reference in Lua
1018 luaV_setudata(L, dic); // cache[dic] = udata
Bram Moolenaar1dced572012-04-05 16:54:08 +02001019 luaV_getfield(L, LUAVIM_DICT);
1020 lua_setmetatable(L, -2);
1021 return d;
1022}
1023
1024luaV_pushtype(dict_T, dict, luaV_Dict)
1025luaV_type_tostring(dict, LUAVIM_DICT)
1026
1027 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001028luaV_dict_len(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001029{
1030 dict_T *d = luaV_unbox(L, luaV_Dict, 1);
Bram Moolenaarb7828692019-03-23 13:57:02 +01001031 lua_pushinteger(L, (int) dict_len(d));
Bram Moolenaar1dced572012-04-05 16:54:08 +02001032 return 1;
1033}
1034
1035 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001036luaV_dict_iter(lua_State *L UNUSED)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001037{
Bram Moolenaarfeeaa682013-02-14 22:19:51 +01001038#ifdef FEAT_EVAL
Bram Moolenaar1dced572012-04-05 16:54:08 +02001039 hashitem_T *hi = (hashitem_T *) lua_touserdata(L, lua_upvalueindex(2));
1040 int n = lua_tointeger(L, lua_upvalueindex(3));
1041 dictitem_T *di;
1042 if (n <= 0) return 0;
1043 while (HASHITEM_EMPTY(hi)) hi++;
1044 di = dict_lookup(hi);
1045 lua_pushstring(L, (char *) hi->hi_key);
1046 luaV_pushtypval(L, &di->di_tv);
1047 lua_pushlightuserdata(L, (void *) (hi + 1));
1048 lua_replace(L, lua_upvalueindex(2));
1049 lua_pushinteger(L, n - 1);
1050 lua_replace(L, lua_upvalueindex(3));
1051 return 2;
Bram Moolenaarfeeaa682013-02-14 22:19:51 +01001052#else
1053 return 0;
1054#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +02001055}
1056
1057 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001058luaV_dict_call(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001059{
1060 dict_T *d = luaV_unbox(L, luaV_Dict, 1);
1061 hashtab_T *ht = &d->dv_hashtab;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001062 lua_pushvalue(L, lua_upvalueindex(1)); // pass cache table along
Bram Moolenaar1dced572012-04-05 16:54:08 +02001063 lua_pushlightuserdata(L, (void *) ht->ht_array);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001064 lua_pushinteger(L, ht->ht_used); // # remaining items
Bram Moolenaar1dced572012-04-05 16:54:08 +02001065 lua_pushcclosure(L, luaV_dict_iter, 3);
1066 return 1;
1067}
1068
1069 static int
Bram Moolenaarca06da92018-07-01 15:12:05 +02001070luaV_dict_index(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001071{
1072 dict_T *d = luaV_unbox(L, luaV_Dict, 1);
1073 char_u *key = (char_u *) luaL_checkstring(L, 2);
1074 dictitem_T *di = dict_find(d, key, -1);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001075
Bram Moolenaar1dced572012-04-05 16:54:08 +02001076 if (di == NULL)
1077 lua_pushnil(L);
1078 else
Bram Moolenaarca06da92018-07-01 15:12:05 +02001079 {
Bram Moolenaar1dced572012-04-05 16:54:08 +02001080 luaV_pushtypval(L, &di->di_tv);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001081 if (di->di_tv.v_type == VAR_FUNC) // funcref?
Bram Moolenaarca06da92018-07-01 15:12:05 +02001082 {
1083 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, -1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001084 f->self = d; // keep "self" reference
Bram Moolenaarca06da92018-07-01 15:12:05 +02001085 d->dv_refcount++;
1086 }
1087 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02001088 return 1;
1089}
1090
1091 static int
Bram Moolenaarca06da92018-07-01 15:12:05 +02001092luaV_dict_newindex(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001093{
1094 dict_T *d = luaV_unbox(L, luaV_Dict, 1);
1095 char_u *key = (char_u *) luaL_checkstring(L, 2);
1096 dictitem_T *di;
Bram Moolenaare49b8e82020-07-01 13:52:55 +02001097 typval_T tv;
Bram Moolenaar713bf9e92019-03-16 16:38:41 +01001098
Bram Moolenaar1dced572012-04-05 16:54:08 +02001099 if (d->dv_lock)
1100 luaL_error(L, "dict is locked");
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001101 if (key == NULL)
1102 return 0;
1103 if (*key == NUL)
Bram Moolenaarca06da92018-07-01 15:12:05 +02001104 luaL_error(L, "empty key");
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001105 if (!lua_isnil(L, 3)) // read value?
Bram Moolenaar17413672018-07-14 20:49:42 +02001106 {
Bram Moolenaare49b8e82020-07-01 13:52:55 +02001107 luaV_checktypval(L, 3, &tv, "setting dict item");
1108 if (d->dv_scope == VAR_DEF_SCOPE && tv.v_type == VAR_FUNC)
1109 {
1110 clear_tv(&tv);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001111 luaL_error(L, "cannot assign funcref to builtin scope");
Bram Moolenaare49b8e82020-07-01 13:52:55 +02001112 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02001113 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02001114 di = dict_find(d, key, -1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001115 if (di == NULL) // non-existing key?
Bram Moolenaar1dced572012-04-05 16:54:08 +02001116 {
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001117 if (lua_isnil(L, 3))
1118 return 0;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001119 di = dictitem_alloc(key);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001120 if (di == NULL)
Bram Moolenaare49b8e82020-07-01 13:52:55 +02001121 {
1122 clear_tv(&tv);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001123 return 0;
Bram Moolenaare49b8e82020-07-01 13:52:55 +02001124 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02001125 if (dict_add(d, di) == FAIL)
1126 {
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001127 vim_free(di);
Bram Moolenaare49b8e82020-07-01 13:52:55 +02001128 clear_tv(&tv);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001129 return 0;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001130 }
1131 }
1132 else
1133 clear_tv(&di->di_tv);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001134 if (lua_isnil(L, 3)) // remove?
Bram Moolenaar1dced572012-04-05 16:54:08 +02001135 {
1136 hashitem_T *hi = hash_find(&d->dv_hashtab, di->di_key);
1137 hash_remove(&d->dv_hashtab, hi);
1138 dictitem_free(di);
1139 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02001140 else
Bram Moolenaare49b8e82020-07-01 13:52:55 +02001141 di->di_tv = tv;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001142 return 0;
1143}
1144
1145static const luaL_Reg luaV_Dict_mt[] = {
1146 {"__tostring", luaV_dict_tostring},
Bram Moolenaar1dced572012-04-05 16:54:08 +02001147 {"__len", luaV_dict_len},
1148 {"__call", luaV_dict_call},
1149 {"__index", luaV_dict_index},
1150 {"__newindex", luaV_dict_newindex},
1151 {NULL, NULL}
1152};
1153
1154
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001155// ======= Blob type =======
Bram Moolenaarb7828692019-03-23 13:57:02 +01001156
1157 static luaV_Blob *
1158luaV_newblob(lua_State *L, blob_T *blo)
1159{
1160 luaV_Blob *b = (luaV_Blob *) lua_newuserdata(L, sizeof(luaV_Blob));
1161 *b = blo;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001162 blo->bv_refcount++; // reference in Lua
1163 luaV_setudata(L, blo); // cache[blo] = udata
Bram Moolenaarb7828692019-03-23 13:57:02 +01001164 luaV_getfield(L, LUAVIM_BLOB);
1165 lua_setmetatable(L, -2);
1166 return b;
1167}
1168
1169luaV_pushtype(blob_T, blob, luaV_Blob)
1170luaV_type_tostring(blob, LUAVIM_BLOB)
1171
1172 static int
1173luaV_blob_gc(lua_State *L)
1174{
1175 blob_T *b = luaV_unbox(L, luaV_Blob, 1);
1176 blob_unref(b);
1177 return 0;
1178}
1179
1180 static int
1181luaV_blob_len(lua_State *L)
1182{
1183 blob_T *b = luaV_unbox(L, luaV_Blob, 1);
1184 lua_pushinteger(L, (int) blob_len(b));
1185 return 1;
1186}
1187
1188 static int
1189luaV_blob_index(lua_State *L)
1190{
1191 blob_T *b = luaV_unbox(L, luaV_Blob, 1);
1192 if (lua_isnumber(L, 2))
1193 {
1194 int idx = luaL_checkinteger(L, 2);
1195 if (idx < blob_len(b))
1196 lua_pushnumber(L, (lua_Number) blob_get(b, idx));
1197 else
1198 lua_pushnil(L);
1199 }
1200 else if (lua_isstring(L, 2))
1201 {
1202 const char *s = lua_tostring(L, 2);
1203 if (strncmp(s, "add", 3) == 0)
1204 {
1205 lua_getmetatable(L, 1);
1206 lua_getfield(L, -1, s);
1207 }
1208 else
1209 lua_pushnil(L);
1210 }
1211 else
1212 lua_pushnil(L);
1213 return 1;
1214}
1215
1216 static int
1217luaV_blob_newindex(lua_State *L)
1218{
1219 blob_T *b = luaV_unbox(L, luaV_Blob, 1);
1220 if (b->bv_lock)
1221 luaL_error(L, "blob is locked");
1222 if (lua_isnumber(L, 2))
1223 {
1224 long len = blob_len(b);
1225 int idx = luaL_checkinteger(L, 2);
1226 int val = luaL_checkinteger(L, 3);
1227 if (idx < len || (idx == len && ga_grow(&b->bv_ga, 1) == OK))
1228 {
1229 blob_set(b, idx, (char_u) val);
1230 if (idx == len)
1231 ++b->bv_ga.ga_len;
1232 }
1233 else
1234 luaL_error(L, "index out of range");
1235 }
1236 return 0;
1237}
1238
1239 static int
1240luaV_blob_add(lua_State *L)
1241{
1242 luaV_Blob *blo = luaV_checkudata(L, 1, LUAVIM_BLOB);
1243 blob_T *b = (blob_T *) luaV_checkcache(L, (void *) *blo);
1244 if (b->bv_lock)
1245 luaL_error(L, "blob is locked");
1246 lua_settop(L, 2);
1247 if (!lua_isstring(L, 2))
1248 luaL_error(L, "string expected, got %s", luaL_typename(L, 2));
1249 else
1250 {
1251 size_t i, l = 0;
1252 const char *s = lua_tolstring(L, 2, &l);
1253
Bram Moolenaar5f1d3ae2020-02-11 22:37:35 +01001254 if (ga_grow(&b->bv_ga, (int)l) == OK)
Bram Moolenaar6fb5c972019-03-26 21:44:20 +01001255 for (i = 0; i < l; ++i)
1256 ga_append(&b->bv_ga, s[i]);
Bram Moolenaarb7828692019-03-23 13:57:02 +01001257 }
1258 lua_settop(L, 1);
1259 return 1;
1260}
1261
1262static const luaL_Reg luaV_Blob_mt[] = {
1263 {"__tostring", luaV_blob_tostring},
1264 {"__gc", luaV_blob_gc},
1265 {"__len", luaV_blob_len},
1266 {"__index", luaV_blob_index},
1267 {"__newindex", luaV_blob_newindex},
1268 {"add", luaV_blob_add},
1269 {NULL, NULL}
1270};
1271
1272
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001273// ======= Funcref type =======
Bram Moolenaarca06da92018-07-01 15:12:05 +02001274
1275 static luaV_Funcref *
1276luaV_newfuncref(lua_State *L, char_u *name)
1277{
1278 luaV_Funcref *f = (luaV_Funcref *)lua_newuserdata(L, sizeof(luaV_Funcref));
1279
1280 if (name != NULL)
1281 {
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001282 func_ref(name);
1283 f->name = vim_strsave(name);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001284 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02001285 f->self = NULL;
1286 luaV_getfield(L, LUAVIM_FUNCREF);
1287 lua_setmetatable(L, -2);
1288 return f;
1289}
1290
1291 static luaV_Funcref *
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001292luaV_pushfuncref(lua_State *L, char_u *name)
Bram Moolenaarca06da92018-07-01 15:12:05 +02001293{
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001294 return luaV_newfuncref(L, name);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001295}
1296
1297
1298luaV_type_tostring(funcref, LUAVIM_FUNCREF)
1299
1300 static int
1301luaV_funcref_gc(lua_State *L)
1302{
1303 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
1304
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001305 func_unref(f->name);
1306 vim_free(f->name);
1307 // NOTE: Don't call "dict_unref(f->self)", because the dict of "f->self"
1308 // will be (or has been already) freed by Vim's garbage collection.
Bram Moolenaarca06da92018-07-01 15:12:05 +02001309 return 0;
1310}
1311
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001312// equivalent to string(funcref)
Bram Moolenaarca06da92018-07-01 15:12:05 +02001313 static int
1314luaV_funcref_len(lua_State *L)
1315{
1316 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
1317
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001318 lua_pushstring(L, (const char *) f->name);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001319 return 1;
1320}
1321
1322 static int
1323luaV_funcref_call(lua_State *L)
1324{
1325 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001326 int i, n = lua_gettop(L) - 1; // #args
1327 int status = FAIL;
1328 typval_T args;
1329 typval_T rettv;
Bram Moolenaarca06da92018-07-01 15:12:05 +02001330
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001331 args.v_type = VAR_LIST;
1332 args.vval.v_list = list_alloc();
1333 rettv.v_type = VAR_UNKNOWN; // as in clear_tv
1334 if (args.vval.v_list != NULL)
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001335 {
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001336 typval_T v;
1337
Bram Moolenaar17413672018-07-14 20:49:42 +02001338 for (i = 0; i < n; i++)
1339 {
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001340 luaV_checktypval(L, i + 2, &v, "calling funcref");
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001341 list_append_tv(args.vval.v_list, &v);
Bram Moolenaar713bf9e92019-03-16 16:38:41 +01001342 clear_tv(&v);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001343 }
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001344 status = func_call(f->name, &args, NULL, f->self, &rettv);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001345 if (status == OK)
1346 luaV_pushtypval(L, &rettv);
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001347 clear_tv(&args);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001348 clear_tv(&rettv);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001349 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02001350 if (status != OK)
1351 luaL_error(L, "cannot call funcref");
1352 return 1;
1353}
1354
1355static const luaL_Reg luaV_Funcref_mt[] = {
1356 {"__tostring", luaV_funcref_tostring},
1357 {"__gc", luaV_funcref_gc},
1358 {"__len", luaV_funcref_len},
1359 {"__call", luaV_funcref_call},
1360 {NULL, NULL}
1361};
1362
1363
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001364// ======= Buffer type =======
Bram Moolenaar1dced572012-04-05 16:54:08 +02001365
1366luaV_newtype(buf_T, buffer, luaV_Buffer, LUAVIM_BUFFER)
1367luaV_pushtype(buf_T, buffer, luaV_Buffer)
1368luaV_type_tostring(buffer, LUAVIM_BUFFER)
1369
1370 static int
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001371luaV_buffer_len(lua_State *L)
1372{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001373 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
1374 lua_pushinteger(L, b->b_ml.ml_line_count);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001375 return 1;
1376}
1377
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001378 static int
1379luaV_buffer_call(lua_State *L)
1380{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001381 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001382 lua_settop(L, 1);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001383 set_curbuf(b, DOBUF_SPLIT);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001384 return 1;
1385}
1386
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001387 static int
1388luaV_buffer_index(lua_State *L)
1389{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001390 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001391 linenr_T n = (linenr_T) lua_tointeger(L, 2);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001392 if (n > 0 && n <= b->b_ml.ml_line_count)
1393 luaV_pushline(L, b, n);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001394 else if (lua_isstring(L, 2))
1395 {
1396 const char *s = lua_tostring(L, 2);
1397 if (strncmp(s, "name", 4) == 0)
Bram Moolenaarfe08df42018-07-07 23:07:41 +02001398 lua_pushstring(L, (b->b_sfname == NULL)
1399 ? "" : (char *) b->b_sfname);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001400 else if (strncmp(s, "fname", 5) == 0)
Bram Moolenaarfe08df42018-07-07 23:07:41 +02001401 lua_pushstring(L, (b->b_ffname == NULL)
1402 ? "" : (char *) b->b_ffname);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001403 else if (strncmp(s, "number", 6) == 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001404 lua_pushinteger(L, b->b_fnum);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001405 // methods
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001406 else if (strncmp(s, "insert", 6) == 0
1407 || strncmp(s, "next", 4) == 0
1408 || strncmp(s, "previous", 8) == 0
1409 || strncmp(s, "isvalid", 7) == 0)
1410 {
1411 lua_getmetatable(L, 1);
1412 lua_getfield(L, -1, s);
1413 }
1414 else
1415 lua_pushnil(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001416 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001417 else
1418 lua_pushnil(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001419 return 1;
1420}
1421
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001422 static int
1423luaV_buffer_newindex(lua_State *L)
1424{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001425 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001426 linenr_T n = (linenr_T) luaL_checkinteger(L, 2);
1427#ifdef HAVE_SANDBOX
1428 luaV_checksandbox(L);
1429#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +02001430 if (n < 1 || n > b->b_ml.ml_line_count)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001431 luaL_error(L, "invalid line number");
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001432 if (lua_isnil(L, 3)) // delete line
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001433 {
1434 buf_T *buf = curbuf;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001435 curbuf = b;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001436 if (u_savedel(n, 1L) == FAIL)
1437 {
1438 curbuf = buf;
1439 luaL_error(L, "cannot save undo information");
1440 }
Bram Moolenaarca70c072020-05-30 20:30:46 +02001441 else if (ml_delete(n) == FAIL)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001442 {
1443 curbuf = buf;
1444 luaL_error(L, "cannot delete line");
1445 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02001446 else
1447 {
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001448 deleted_lines_mark(n, 1L);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001449 if (b == curwin->w_buffer) // fix cursor in current window?
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001450 {
1451 if (curwin->w_cursor.lnum >= n)
1452 {
1453 if (curwin->w_cursor.lnum > n)
1454 {
1455 curwin->w_cursor.lnum -= 1;
1456 check_cursor_col();
1457 }
Bram Moolenaare49b8e82020-07-01 13:52:55 +02001458 else
1459 check_cursor();
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001460 changed_cline_bef_curs();
1461 }
1462 invalidate_botline();
1463 }
1464 }
1465 curbuf = buf;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001466 }
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001467 else if (lua_isstring(L, 3)) // update line
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001468 {
1469 buf_T *buf = curbuf;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001470 curbuf = b;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001471 if (u_savesub(n) == FAIL)
1472 {
1473 curbuf = buf;
1474 luaL_error(L, "cannot save undo information");
1475 }
1476 else if (ml_replace(n, luaV_toline(L, 3), TRUE) == FAIL)
1477 {
1478 curbuf = buf;
1479 luaL_error(L, "cannot replace line");
1480 }
1481 else changed_bytes(n, 0);
1482 curbuf = buf;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001483 if (b == curwin->w_buffer)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001484 check_cursor_col();
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001485 }
1486 else
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001487 luaL_error(L, "wrong argument to change line");
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001488 return 0;
1489}
1490
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001491 static int
1492luaV_buffer_insert(lua_State *L)
1493{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001494 luaV_Buffer *lb = luaV_checkudata(L, 1, LUAVIM_BUFFER);
1495 buf_T *b = (buf_T *) luaV_checkcache(L, (void *) *lb);
1496 linenr_T last = b->b_ml.ml_line_count;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001497 linenr_T n = (linenr_T) luaL_optinteger(L, 3, last);
1498 buf_T *buf;
1499 luaL_checktype(L, 2, LUA_TSTRING);
1500#ifdef HAVE_SANDBOX
1501 luaV_checksandbox(L);
1502#endif
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001503 // fix insertion line
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001504 if (n < 0) n = 0;
1505 if (n > last) n = last;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001506 // insert
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001507 buf = curbuf;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001508 curbuf = b;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001509 if (u_save(n, n + 1) == FAIL)
1510 {
1511 curbuf = buf;
1512 luaL_error(L, "cannot save undo information");
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001513 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001514 else if (ml_append(n, luaV_toline(L, 2), 0, FALSE) == FAIL)
1515 {
1516 curbuf = buf;
1517 luaL_error(L, "cannot insert line");
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001518 }
1519 else
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001520 appended_lines_mark(n, 1L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001521 curbuf = buf;
1522 update_screen(VALID);
1523 return 0;
1524}
1525
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001526 static int
1527luaV_buffer_next(lua_State *L)
1528{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001529 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001530 buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b);
1531 luaV_pushbuffer(L, buf->b_next);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001532 return 1;
1533}
1534
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001535 static int
1536luaV_buffer_previous(lua_State *L)
1537{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001538 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001539 buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b);
1540 luaV_pushbuffer(L, buf->b_prev);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001541 return 1;
1542}
1543
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001544 static int
1545luaV_buffer_isvalid(lua_State *L)
1546{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001547 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001548 luaV_getudata(L, *b);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001549 lua_pushboolean(L, !lua_isnil(L, -1));
1550 return 1;
1551}
1552
1553static const luaL_Reg luaV_Buffer_mt[] = {
1554 {"__tostring", luaV_buffer_tostring},
1555 {"__len", luaV_buffer_len},
1556 {"__call", luaV_buffer_call},
1557 {"__index", luaV_buffer_index},
1558 {"__newindex", luaV_buffer_newindex},
1559 {"insert", luaV_buffer_insert},
1560 {"next", luaV_buffer_next},
1561 {"previous", luaV_buffer_previous},
1562 {"isvalid", luaV_buffer_isvalid},
1563 {NULL, NULL}
1564};
1565
1566
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001567// ======= Window type =======
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001568
Bram Moolenaar1dced572012-04-05 16:54:08 +02001569luaV_newtype(win_T, window, luaV_Window, LUAVIM_WINDOW)
1570luaV_pushtype(win_T, window, luaV_Window)
1571luaV_type_tostring(window, LUAVIM_WINDOW)
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001572
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001573 static int
1574luaV_window_call(lua_State *L)
1575{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001576 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001577 lua_settop(L, 1);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001578 win_goto(w);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001579 return 1;
1580}
1581
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001582 static int
1583luaV_window_index(lua_State *L)
1584{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001585 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001586 const char *s = luaL_checkstring(L, 2);
1587 if (strncmp(s, "buffer", 6) == 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001588 luaV_pushbuffer(L, w->w_buffer);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001589 else if (strncmp(s, "line", 4) == 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001590 lua_pushinteger(L, w->w_cursor.lnum);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001591 else if (strncmp(s, "col", 3) == 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001592 lua_pushinteger(L, w->w_cursor.col + 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001593 else if (strncmp(s, "width", 5) == 0)
Bram Moolenaar02631462017-09-22 15:20:32 +02001594 lua_pushinteger(L, w->w_width);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001595 else if (strncmp(s, "height", 6) == 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001596 lua_pushinteger(L, w->w_height);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001597 // methods
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001598 else if (strncmp(s, "next", 4) == 0
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001599 || strncmp(s, "previous", 8) == 0
1600 || strncmp(s, "isvalid", 7) == 0)
1601 {
1602 lua_getmetatable(L, 1);
1603 lua_getfield(L, -1, s);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001604 }
1605 else
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001606 lua_pushnil(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001607 return 1;
1608}
1609
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001610 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001611luaV_window_newindex(lua_State *L)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001612{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001613 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001614 const char *s = luaL_checkstring(L, 2);
1615 int v = luaL_checkinteger(L, 3);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001616 if (strncmp(s, "line", 4) == 0)
1617 {
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001618#ifdef HAVE_SANDBOX
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001619 luaV_checksandbox(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001620#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +02001621 if (v < 1 || v > w->w_buffer->b_ml.ml_line_count)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001622 luaL_error(L, "line out of range");
Bram Moolenaar1dced572012-04-05 16:54:08 +02001623 w->w_cursor.lnum = v;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001624 update_screen(VALID);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001625 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001626 else if (strncmp(s, "col", 3) == 0)
1627 {
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001628#ifdef HAVE_SANDBOX
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001629 luaV_checksandbox(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001630#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +02001631 w->w_cursor.col = v - 1;
Bram Moolenaar53901442018-07-25 22:02:36 +02001632 w->w_set_curswant = TRUE;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001633 update_screen(VALID);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001634 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001635 else if (strncmp(s, "width", 5) == 0)
1636 {
1637 win_T *win = curwin;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001638#ifdef FEAT_GUI
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001639 need_mouse_correct = TRUE;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001640#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +02001641 curwin = w;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001642 win_setwidth(v);
1643 curwin = win;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001644 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001645 else if (strncmp(s, "height", 6) == 0)
1646 {
1647 win_T *win = curwin;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001648#ifdef FEAT_GUI
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001649 need_mouse_correct = TRUE;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001650#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +02001651 curwin = w;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001652 win_setheight(v);
1653 curwin = win;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001654 }
1655 else
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001656 luaL_error(L, "invalid window property: `%s'", s);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001657 return 0;
1658}
1659
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001660 static int
1661luaV_window_next(lua_State *L)
1662{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001663 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001664 win_T *win = (win_T *) luaV_checkcache(L, (void *) *w);
1665 luaV_pushwindow(L, win->w_next);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001666 return 1;
1667}
1668
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001669 static int
1670luaV_window_previous(lua_State *L)
1671{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001672 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001673 win_T *win = (win_T *) luaV_checkcache(L, (void *) *w);
1674 luaV_pushwindow(L, win->w_prev);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001675 return 1;
1676}
1677
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001678 static int
1679luaV_window_isvalid(lua_State *L)
1680{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001681 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001682 luaV_getudata(L, *w);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001683 lua_pushboolean(L, !lua_isnil(L, -1));
1684 return 1;
1685}
1686
1687static const luaL_Reg luaV_Window_mt[] = {
1688 {"__tostring", luaV_window_tostring},
1689 {"__call", luaV_window_call},
1690 {"__index", luaV_window_index},
1691 {"__newindex", luaV_window_newindex},
1692 {"next", luaV_window_next},
1693 {"previous", luaV_window_previous},
1694 {"isvalid", luaV_window_isvalid},
1695 {NULL, NULL}
1696};
1697
1698
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001699// ======= Vim module =======
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001700
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001701 static int
1702luaV_print(lua_State *L)
1703{
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001704 int i, n = lua_gettop(L); // nargs
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001705 const char *s;
1706 size_t l;
1707 luaL_Buffer b;
1708 luaL_buffinit(L, &b);
1709 lua_getglobal(L, "tostring");
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001710 for (i = 1; i <= n; i++)
1711 {
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001712 lua_pushvalue(L, -1); // tostring
1713 lua_pushvalue(L, i); // arg
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001714 lua_call(L, 1, 1);
1715 s = lua_tolstring(L, -1, &l);
1716 if (s == NULL)
1717 return luaL_error(L, "cannot convert to string");
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001718 if (i > 1) luaL_addchar(&b, ' '); // use space instead of tab
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001719 luaV_addlstring(&b, s, l, 0);
1720 lua_pop(L, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001721 }
1722 luaL_pushresult(&b);
Bram Moolenaarb98678a2019-10-19 15:18:44 +02001723 if (!got_int)
1724 luaV_msg(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001725 return 0;
1726}
1727
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001728 static int
Bram Moolenaar38e2b062011-09-21 17:15:39 +02001729luaV_debug(lua_State *L)
1730{
1731 lua_settop(L, 0);
1732 lua_getglobal(L, "vim");
1733 lua_getfield(L, -1, "eval");
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001734 lua_remove(L, -2); // vim.eval at position 1
Bram Moolenaar38e2b062011-09-21 17:15:39 +02001735 for (;;)
1736 {
1737 const char *input;
1738 size_t l;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001739 lua_pushvalue(L, 1); // vim.eval
Bram Moolenaar38e2b062011-09-21 17:15:39 +02001740 lua_pushliteral(L, "input('lua_debug> ')");
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001741 lua_call(L, 1, 1); // return string
Bram Moolenaar38e2b062011-09-21 17:15:39 +02001742 input = lua_tolstring(L, -1, &l);
1743 if (l == 0 || strcmp(input, "cont") == 0)
1744 return 0;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001745 msg_putchar('\n'); // avoid outputting on input line
Bram Moolenaar38e2b062011-09-21 17:15:39 +02001746 if (luaL_loadbuffer(L, input, l, "=(debug command)")
1747 || lua_pcall(L, 0, 0, 0))
1748 luaV_emsg(L);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001749 lua_settop(L, 1); // remove eventual returns, but keep vim.eval
Bram Moolenaar38e2b062011-09-21 17:15:39 +02001750 }
1751}
1752
1753 static int
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001754luaV_command(lua_State *L)
1755{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001756 do_cmdline_cmd((char_u *) luaL_checkstring(L, 1));
1757 update_screen(VALID);
1758 return 0;
1759}
1760
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001761 static int
1762luaV_eval(lua_State *L)
1763{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001764 typval_T *tv = eval_expr((char_u *) luaL_checkstring(L, 1), NULL);
1765 if (tv == NULL) luaL_error(L, "invalid expression");
1766 luaV_pushtypval(L, tv);
Bram Moolenaarb3766472013-04-15 13:49:21 +02001767 free_tv(tv);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001768 return 1;
1769}
1770
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001771 static int
Bram Moolenaar0d2e4fc2010-07-18 12:35:47 +02001772luaV_beep(lua_State *L UNUSED)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001773{
Bram Moolenaar165bc692015-07-21 17:53:25 +02001774 vim_beep(BO_LANG);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001775 return 0;
1776}
1777
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001778 static int
1779luaV_line(lua_State *L)
1780{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001781 luaV_pushline(L, curbuf, curwin->w_cursor.lnum);
1782 return 1;
1783}
1784
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001785 static int
Bram Moolenaar1dced572012-04-05 16:54:08 +02001786luaV_list(lua_State *L)
1787{
Bram Moolenaarca06da92018-07-01 15:12:05 +02001788 list_T *l;
1789 int initarg = !lua_isnoneornil(L, 1);
1790
1791 if (initarg && lua_type(L, 1) != LUA_TTABLE)
1792 luaL_error(L, "table expected, got %s", luaL_typename(L, 1));
1793 l = list_alloc();
Bram Moolenaar1dced572012-04-05 16:54:08 +02001794 if (l == NULL)
1795 lua_pushnil(L);
1796 else
Bram Moolenaarca06da92018-07-01 15:12:05 +02001797 {
Bram Moolenaar1dced572012-04-05 16:54:08 +02001798 luaV_newlist(L, l);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001799 if (initarg) // traverse table to init list
Bram Moolenaar17413672018-07-14 20:49:42 +02001800 {
Bram Moolenaarca06da92018-07-01 15:12:05 +02001801 int notnil, i = 0;
1802 typval_T v;
Bram Moolenaar17413672018-07-14 20:49:42 +02001803 do
1804 {
Bram Moolenaarca06da92018-07-01 15:12:05 +02001805 lua_rawgeti(L, 1, ++i);
1806 notnil = !lua_isnil(L, -1);
Bram Moolenaar17413672018-07-14 20:49:42 +02001807 if (notnil)
1808 {
Bram Moolenaarca06da92018-07-01 15:12:05 +02001809 luaV_checktypval(L, -1, &v, "vim.list");
1810 list_append_tv(l, &v);
Bram Moolenaar713bf9e92019-03-16 16:38:41 +01001811 clear_tv(&v);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001812 }
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001813 lua_pop(L, 1); // value
Bram Moolenaarca06da92018-07-01 15:12:05 +02001814 } while (notnil);
1815 }
1816 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02001817 return 1;
1818}
1819
1820 static int
1821luaV_dict(lua_State *L)
1822{
Bram Moolenaarca06da92018-07-01 15:12:05 +02001823 dict_T *d;
1824 int initarg = !lua_isnoneornil(L, 1);
1825
1826 if (initarg && lua_type(L, 1) != LUA_TTABLE)
1827 luaL_error(L, "table expected, got %s", luaL_typename(L, 1));
1828 d = dict_alloc();
Bram Moolenaar1dced572012-04-05 16:54:08 +02001829 if (d == NULL)
1830 lua_pushnil(L);
1831 else
Bram Moolenaarca06da92018-07-01 15:12:05 +02001832 {
Bram Moolenaar1dced572012-04-05 16:54:08 +02001833 luaV_newdict(L, d);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001834 if (initarg) // traverse table to init dict
Bram Moolenaarca06da92018-07-01 15:12:05 +02001835 {
1836 lua_pushnil(L);
1837 while (lua_next(L, 1))
1838 {
1839 char_u *key;
1840 dictitem_T *di;
1841 typval_T v;
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001842
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001843 lua_pushvalue(L, -2); // dup key in case it's a number
Bram Moolenaarca06da92018-07-01 15:12:05 +02001844 key = (char_u *) lua_tostring(L, -1);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001845 if (key == NULL)
1846 {
1847 lua_pushnil(L);
1848 return 1;
1849 }
1850 if (*key == NUL)
Bram Moolenaarca06da92018-07-01 15:12:05 +02001851 luaL_error(L, "table has empty key");
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001852 luaV_checktypval(L, -2, &v, "vim.dict"); // value
Bram Moolenaarca06da92018-07-01 15:12:05 +02001853 di = dictitem_alloc(key);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001854 if (di == NULL || dict_add(d, di) == FAIL)
1855 {
Bram Moolenaarca06da92018-07-01 15:12:05 +02001856 vim_free(di);
1857 lua_pushnil(L);
1858 return 1;
1859 }
Bram Moolenaare49b8e82020-07-01 13:52:55 +02001860 di->di_tv = v;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001861 lua_pop(L, 2); // key copy and value
Bram Moolenaarca06da92018-07-01 15:12:05 +02001862 }
1863 }
1864 }
1865 return 1;
1866}
1867
1868 static int
Bram Moolenaarb7828692019-03-23 13:57:02 +01001869luaV_blob(lua_State *L)
1870{
1871 blob_T *b;
1872 int initarg = !lua_isnoneornil(L, 1);
1873
1874 if (initarg && !lua_isstring(L, 1))
1875 luaL_error(L, "string expected, got %s", luaL_typename(L, 1));
1876 b = blob_alloc();
1877 if (b == NULL)
1878 lua_pushnil(L);
1879 else
1880 {
1881 luaV_newblob(L, b);
1882 if (initarg)
1883 {
1884 size_t i, l = 0;
1885 const char *s = lua_tolstring(L, 1, &l);
1886
Bram Moolenaar5f1d3ae2020-02-11 22:37:35 +01001887 if (ga_grow(&b->bv_ga, (int)l) == OK)
Bram Moolenaar6fb5c972019-03-26 21:44:20 +01001888 for (i = 0; i < l; ++i)
1889 ga_append(&b->bv_ga, s[i]);
Bram Moolenaarb7828692019-03-23 13:57:02 +01001890 }
1891 }
1892 return 1;
1893}
1894
1895 static int
Bram Moolenaarca06da92018-07-01 15:12:05 +02001896luaV_funcref(lua_State *L)
1897{
1898 const char *name = luaL_checkstring(L, 1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001899 // note: not checking if function exists (needs function_exists)
Bram Moolenaarca06da92018-07-01 15:12:05 +02001900 if (name == NULL || *name == NUL || VIM_ISDIGIT(*name))
1901 luaL_error(L, "invalid function name: %s", name);
1902 luaV_newfuncref(L, (char_u *) name);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001903 return 1;
1904}
1905
1906 static int
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001907luaV_buffer(lua_State *L)
1908{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001909 buf_T *buf;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001910 if (lua_isstring(L, 1)) // get by number or name?
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001911 {
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001912 if (lua_isnumber(L, 1)) // by number?
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001913 {
1914 int n = lua_tointeger(L, 1);
Bram Moolenaar29323592016-07-24 22:04:11 +02001915 FOR_ALL_BUFFERS(buf)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001916 if (buf->b_fnum == n) break;
1917 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02001918 else // by name
1919 {
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001920 size_t l;
1921 const char *s = lua_tolstring(L, 1, &l);
Bram Moolenaar29323592016-07-24 22:04:11 +02001922 FOR_ALL_BUFFERS(buf)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001923 {
1924 if (buf->b_ffname == NULL || buf->b_sfname == NULL)
1925 {
1926 if (l == 0) break;
1927 }
Bram Moolenaar0d2e4fc2010-07-18 12:35:47 +02001928 else if (strncmp(s, (char *)buf->b_ffname, l) == 0
1929 || strncmp(s, (char *)buf->b_sfname, l) == 0)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001930 break;
1931 }
1932 }
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001933 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02001934 else
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001935 buf = (lua_toboolean(L, 1)) ? firstbuf : curbuf; // first buffer?
Bram Moolenaar1dced572012-04-05 16:54:08 +02001936 luaV_pushbuffer(L, buf);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001937 return 1;
1938}
1939
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001940 static int
1941luaV_window(lua_State *L)
1942{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001943 win_T *win;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001944 if (lua_isnumber(L, 1)) // get by number?
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001945 {
1946 int n = lua_tointeger(L, 1);
1947 for (win = firstwin; win != NULL; win = win->w_next, n--)
1948 if (n == 1) break;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001949 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02001950 else
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001951 win = (lua_toboolean(L, 1)) ? firstwin : curwin; // first window?
Bram Moolenaar1dced572012-04-05 16:54:08 +02001952 luaV_pushwindow(L, win);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001953 return 1;
1954}
1955
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001956 static int
1957luaV_open(lua_State *L)
1958{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001959 char_u *s = NULL;
1960#ifdef HAVE_SANDBOX
1961 luaV_checksandbox(L);
1962#endif
1963 if (lua_isstring(L, 1)) s = (char_u *) lua_tostring(L, 1);
Bram Moolenaarfa263a52011-12-08 16:00:16 +01001964 luaV_pushbuffer(L, buflist_new(s, NULL, 1L, BLN_LISTED));
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001965 return 1;
1966}
1967
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001968 static int
Bram Moolenaar1dced572012-04-05 16:54:08 +02001969luaV_type(lua_State *L)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001970{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001971 luaL_checkany(L, 1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001972 if (lua_type(L, 1) == LUA_TUSERDATA) // check vim udata?
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001973 {
Bram Moolenaar1dced572012-04-05 16:54:08 +02001974 lua_settop(L, 1);
1975 if (lua_getmetatable(L, 1))
1976 {
1977 luaV_getfield(L, LUAVIM_LIST);
1978 if (lua_rawequal(L, -1, 2))
1979 {
1980 lua_pushstring(L, "list");
1981 return 1;
1982 }
1983 luaV_getfield(L, LUAVIM_DICT);
1984 if (lua_rawequal(L, -1, 2))
1985 {
1986 lua_pushstring(L, "dict");
1987 return 1;
1988 }
Bram Moolenaarb7828692019-03-23 13:57:02 +01001989 luaV_getfield(L, LUAVIM_BLOB);
1990 if (lua_rawequal(L, -1, 2))
1991 {
1992 lua_pushstring(L, "blob");
1993 return 1;
1994 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02001995 luaV_getfield(L, LUAVIM_FUNCREF);
1996 if (lua_rawequal(L, -1, 2))
1997 {
1998 lua_pushstring(L, "funcref");
1999 return 1;
2000 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02002001 luaV_getfield(L, LUAVIM_BUFFER);
2002 if (lua_rawequal(L, -1, 2))
2003 {
2004 lua_pushstring(L, "buffer");
2005 return 1;
2006 }
2007 luaV_getfield(L, LUAVIM_WINDOW);
2008 if (lua_rawequal(L, -1, 2))
2009 {
2010 lua_pushstring(L, "window");
2011 return 1;
2012 }
2013 }
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002014 }
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002015 lua_pushstring(L, luaL_typename(L, 1)); // fallback
Bram Moolenaar1dced572012-04-05 16:54:08 +02002016 return 1;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002017}
2018
Bram Moolenaareb04f082020-05-17 14:32:35 +02002019 static int
2020luaV_call(lua_State *L)
2021{
2022 int argc = lua_gettop(L) - 1;
2023 size_t funcname_len;
2024 char_u *funcname;
2025 char *error = NULL;
2026 typval_T rettv;
2027 typval_T argv[MAX_FUNC_ARGS + 1];
2028 int i = 0;
2029
2030 if (argc > MAX_FUNC_ARGS)
2031 return luaL_error(L, "Function called with too many arguments");
2032
2033 funcname = (char_u *)luaL_checklstring(L, 1, &funcname_len);
2034
2035 for (; i < argc; i++)
2036 {
2037 if (luaV_totypval(L, i + 2, &argv[i]) == FAIL)
2038 {
2039 error = "lua: cannot convert value";
2040 goto free_vim_args;
2041 }
2042 }
2043
2044 argv[argc].v_type = VAR_UNKNOWN;
2045
2046 if (call_vim_function(funcname, argc, argv, &rettv) == FAIL)
2047 {
2048 error = "lua: call_vim_function failed";
2049 goto free_vim_args;
2050 }
2051
2052 luaV_pushtypval(L, &rettv);
2053 clear_tv(&rettv);
2054
2055free_vim_args:
2056 while (i > 0)
2057 clear_tv(&argv[--i]);
2058
2059 if (error == NULL)
2060 return 1;
2061 else
2062 return luaL_error(L, error);
2063}
2064
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002065static const luaL_Reg luaV_module[] = {
2066 {"command", luaV_command},
2067 {"eval", luaV_eval},
2068 {"beep", luaV_beep},
2069 {"line", luaV_line},
Bram Moolenaar1dced572012-04-05 16:54:08 +02002070 {"list", luaV_list},
2071 {"dict", luaV_dict},
Bram Moolenaarb7828692019-03-23 13:57:02 +01002072 {"blob", luaV_blob},
Bram Moolenaarca06da92018-07-01 15:12:05 +02002073 {"funcref", luaV_funcref},
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002074 {"buffer", luaV_buffer},
2075 {"window", luaV_window},
2076 {"open", luaV_open},
Bram Moolenaar1dced572012-04-05 16:54:08 +02002077 {"type", luaV_type},
Bram Moolenaareb04f082020-05-17 14:32:35 +02002078 {"call", luaV_call},
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002079 {NULL, NULL}
2080};
2081
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002082/*
2083 * for freeing list, dict, buffer and window objects; lightuserdata as arg
2084 */
Bram Moolenaar1dced572012-04-05 16:54:08 +02002085 static int
2086luaV_free(lua_State *L)
2087{
2088 lua_pushnil(L);
2089 luaV_setudata(L, lua_touserdata(L, 1));
2090 return 0;
2091}
2092
2093 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002094luaV_luaeval(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +02002095{
2096 luaL_Buffer b;
2097 size_t l;
2098 const char *str = lua_tolstring(L, 1, &l);
2099 typval_T *arg = (typval_T *) lua_touserdata(L, 2);
2100 typval_T *rettv = (typval_T *) lua_touserdata(L, 3);
2101 luaL_buffinit(L, &b);
2102 luaL_addlstring(&b, LUAVIM_EVALHEADER, sizeof(LUAVIM_EVALHEADER) - 1);
2103 luaL_addlstring(&b, str, l);
2104 luaL_pushresult(&b);
2105 str = lua_tolstring(L, -1, &l);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002106 if (luaL_loadbuffer(L, str, l, LUAVIM_EVALNAME)) // compile error?
Bram Moolenaar1dced572012-04-05 16:54:08 +02002107 {
2108 luaV_emsg(L);
2109 return 0;
2110 }
2111 luaV_pushtypval(L, arg);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002112 if (lua_pcall(L, 1, 1, 0)) // running error?
Bram Moolenaar1dced572012-04-05 16:54:08 +02002113 {
2114 luaV_emsg(L);
2115 return 0;
2116 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02002117 if (luaV_totypval(L, -1, rettv) == FAIL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002118 emsg("luaeval: cannot convert value");
Bram Moolenaarf554a322015-02-04 23:08:01 +01002119 return 0;
Bram Moolenaar1dced572012-04-05 16:54:08 +02002120}
2121
2122 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002123luaV_setref(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +02002124{
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002125 int copyID = lua_tointeger(L, 1);
2126 int abort = FALSE;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01002127
Bram Moolenaar1dced572012-04-05 16:54:08 +02002128 luaV_getfield(L, LUAVIM_LIST);
2129 luaV_getfield(L, LUAVIM_DICT);
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002130 luaV_getfield(L, LUAVIM_FUNCREF);
Bram Moolenaar1dced572012-04-05 16:54:08 +02002131 lua_pushnil(L);
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002132 // traverse cache table
Bram Moolenaarb84634d2015-02-04 22:02:37 +01002133 while (!abort && lua_next(L, lua_upvalueindex(1)) != 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +02002134 {
2135 lua_getmetatable(L, -1);
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002136 if (lua_rawequal(L, -1, 2)) // list?
Bram Moolenaar1dced572012-04-05 16:54:08 +02002137 {
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002138 list_T *l = (list_T *)lua_touserdata(L, 5); // key
2139
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02002140 abort = set_ref_in_list(l, copyID);
Bram Moolenaar1dced572012-04-05 16:54:08 +02002141 }
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002142 else if (lua_rawequal(L, -1, 3)) // dict?
Bram Moolenaar1dced572012-04-05 16:54:08 +02002143 {
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002144 dict_T *d = (dict_T *)lua_touserdata(L, 5); // key
2145
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02002146 abort = set_ref_in_dict(d, copyID);
Bram Moolenaar1dced572012-04-05 16:54:08 +02002147 }
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002148 else if (lua_rawequal(L, -1, 4)) // funcref?
2149 {
2150 luaV_Funcref *f = (luaV_Funcref *)lua_touserdata(L, 5); // key
2151
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02002152 abort = set_ref_in_dict(f->self, copyID);
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002153 }
2154 lua_pop(L, 2); // metatable and value
Bram Moolenaar1dced572012-04-05 16:54:08 +02002155 }
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01002156 lua_pushinteger(L, abort);
Bram Moolenaarf554a322015-02-04 23:08:01 +01002157 return 1;
Bram Moolenaar1dced572012-04-05 16:54:08 +02002158}
2159
Bram Moolenaareb04f082020-05-17 14:32:35 +02002160#define LUA_VIM_FN_CODE \
Bram Moolenaar788fbb42020-05-31 14:08:12 +02002161 "vim.fn = setmetatable({}, {\n"\
2162 " __index = function (t, key)\n"\
2163 " local function _fn(...)\n"\
2164 " return vim.call(key, ...)\n"\
2165 " end\n"\
2166 " t[key] = _fn\n"\
2167 " return _fn\n"\
2168 " end\n"\
2169 " })"
2170
2171#define LUA_VIM_UPDATE_PACKAGE_PATHS \
2172 "local last_vim_paths = {}\n"\
2173 "vim._update_package_paths = function ()\n"\
2174 " local cur_vim_paths = {}\n"\
2175 " local function split(s, delimiter)\n"\
2176 " result = {}\n"\
2177 " for match in (s..delimiter):gmatch(\"(.-)\"..delimiter) do\n"\
2178 " table.insert(result, match)\n"\
2179 " end\n"\
2180 " return result\n"\
2181 " end\n"\
2182 " local rtps = split(vim.eval('&runtimepath'), ',')\n"\
2183 " local sep = package.config:sub(1, 1)\n"\
2184 " for _, key in ipairs({'path', 'cpath'}) do\n"\
2185 " local orig_str = package[key] .. ';'\n"\
2186 " local pathtrails_ordered = {}\n"\
2187 " -- Note: ignores trailing item without trailing `;`. Not using something\n"\
2188 " -- simpler in order to preserve empty items (stand for default path).\n"\
2189 " local orig = {}\n"\
2190 " for s in orig_str:gmatch('[^;]*;') do\n"\
2191 " s = s:sub(1, -2) -- Strip trailing semicolon\n"\
2192 " orig[#orig + 1] = s\n"\
2193 " end\n"\
2194 " if key == 'path' then\n"\
2195 " -- /?.lua and /?/init.lua\n"\
2196 " pathtrails_ordered = {sep .. '?.lua', sep .. '?' .. sep .. 'init.lua'}\n"\
2197 " else\n"\
2198 " local pathtrails = {}\n"\
2199 " for _, s in ipairs(orig) do\n"\
2200 " -- Find out path patterns. pathtrail should contain something like\n"\
2201 " -- /?.so, \?.dll. This allows not to bother determining what correct\n"\
2202 " -- suffixes are.\n"\
2203 " local pathtrail = s:match('[/\\\\][^/\\\\]*%?.*$')\n"\
2204 " if pathtrail and not pathtrails[pathtrail] then\n"\
2205 " pathtrails[pathtrail] = true\n"\
2206 " pathtrails_ordered[#pathtrails_ordered + 1] = pathtrail\n"\
2207 " end\n"\
2208 " end\n"\
2209 " end\n"\
2210 " local new = {}\n"\
2211 " for _, rtp in ipairs(rtps) do\n"\
2212 " if not rtp:match(';') then\n"\
2213 " for _, pathtrail in pairs(pathtrails_ordered) do\n"\
2214 " local new_path = rtp .. sep .. 'lua' .. pathtrail\n"\
2215 " -- Always keep paths from &runtimepath at the start:\n"\
2216 " -- append them here disregarding orig possibly containing one of them.\n"\
2217 " new[#new + 1] = new_path\n"\
2218 " cur_vim_paths[new_path] = true\n"\
2219 " end\n"\
2220 " end\n"\
2221 " end\n"\
2222 " for _, orig_path in ipairs(orig) do\n"\
2223 " -- Handle removing obsolete paths originating from &runtimepath: such\n"\
2224 " -- paths either belong to cur_nvim_paths and were already added above or\n"\
2225 " -- to last_nvim_paths and should not be added at all if corresponding\n"\
2226 " -- entry was removed from &runtimepath list.\n"\
2227 " if not (cur_vim_paths[orig_path] or last_vim_paths[orig_path]) then\n"\
2228 " new[#new + 1] = orig_path\n"\
2229 " end\n"\
2230 " end\n"\
2231 " package[key] = table.concat(new, ';')\n"\
2232 " end\n"\
2233 " last_vim_paths = cur_vim_paths\n"\
2234 "end"
Bram Moolenaareb04f082020-05-17 14:32:35 +02002235
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002236 static int
2237luaopen_vim(lua_State *L)
2238{
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002239 // set cache table
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002240 lua_newtable(L);
2241 lua_newtable(L);
Bram Moolenaar1dced572012-04-05 16:54:08 +02002242 lua_pushstring(L, "v");
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002243 lua_setfield(L, -2, "__mode");
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002244 lua_setmetatable(L, -2); // cache is weak-valued
2245 // print
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002246 lua_pushcfunction(L, luaV_print);
2247 lua_setglobal(L, "print");
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002248 // debug.debug
Bram Moolenaar38e2b062011-09-21 17:15:39 +02002249 lua_getglobal(L, "debug");
2250 lua_pushcfunction(L, luaV_debug);
2251 lua_setfield(L, -2, "debug");
2252 lua_pop(L, 1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002253 // free
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002254 lua_pushlightuserdata(L, (void *) LUAVIM_FREE);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002255 lua_pushvalue(L, 1); // cache table
Bram Moolenaar1dced572012-04-05 16:54:08 +02002256 lua_pushcclosure(L, luaV_free, 1);
2257 lua_rawset(L, LUA_REGISTRYINDEX);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002258 // luaeval
Bram Moolenaar1dced572012-04-05 16:54:08 +02002259 lua_pushlightuserdata(L, (void *) LUAVIM_LUAEVAL);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002260 lua_pushvalue(L, 1); // cache table
Bram Moolenaar1dced572012-04-05 16:54:08 +02002261 lua_pushcclosure(L, luaV_luaeval, 1);
2262 lua_rawset(L, LUA_REGISTRYINDEX);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002263 // setref
Bram Moolenaar1dced572012-04-05 16:54:08 +02002264 lua_pushlightuserdata(L, (void *) LUAVIM_SETREF);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002265 lua_pushvalue(L, 1); // cache table
Bram Moolenaar1dced572012-04-05 16:54:08 +02002266 lua_pushcclosure(L, luaV_setref, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002267 lua_rawset(L, LUA_REGISTRYINDEX);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002268 // register
Bram Moolenaar1dced572012-04-05 16:54:08 +02002269 luaV_newmetatable(L, LUAVIM_LIST);
2270 lua_pushvalue(L, 1);
2271 luaV_openlib(L, luaV_List_mt, 1);
2272 luaV_newmetatable(L, LUAVIM_DICT);
2273 lua_pushvalue(L, 1);
2274 luaV_openlib(L, luaV_Dict_mt, 1);
Bram Moolenaarb7828692019-03-23 13:57:02 +01002275 luaV_newmetatable(L, LUAVIM_BLOB);
2276 lua_pushvalue(L, 1);
2277 luaV_openlib(L, luaV_Blob_mt, 1);
Bram Moolenaarca06da92018-07-01 15:12:05 +02002278 luaV_newmetatable(L, LUAVIM_FUNCREF);
2279 lua_pushvalue(L, 1);
2280 luaV_openlib(L, luaV_Funcref_mt, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002281 luaV_newmetatable(L, LUAVIM_BUFFER);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002282 lua_pushvalue(L, 1); // cache table
Bram Moolenaar1dced572012-04-05 16:54:08 +02002283 luaV_openlib(L, luaV_Buffer_mt, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002284 luaV_newmetatable(L, LUAVIM_WINDOW);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002285 lua_pushvalue(L, 1); // cache table
Bram Moolenaar1dced572012-04-05 16:54:08 +02002286 luaV_openlib(L, luaV_Window_mt, 1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002287 lua_newtable(L); // vim table
2288 lua_pushvalue(L, 1); // cache table
Bram Moolenaar1dced572012-04-05 16:54:08 +02002289 luaV_openlib(L, luaV_module, 1);
2290 lua_setglobal(L, LUAVIM_NAME);
Bram Moolenaareb04f082020-05-17 14:32:35 +02002291 // custom code
Bram Moolenaar9309eb22020-05-17 16:53:56 +02002292 (void)luaL_dostring(L, LUA_VIM_FN_CODE);
Bram Moolenaar788fbb42020-05-31 14:08:12 +02002293 (void)luaL_dostring(L, LUA_VIM_UPDATE_PACKAGE_PATHS);
2294
2295 lua_getglobal(L, "vim");
2296 lua_getfield(L, -1, "_update_package_paths");
2297
2298 if (lua_pcall(L, 0, 0, 0))
2299 luaV_emsg(L);
2300
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002301 return 0;
2302}
2303
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002304 static lua_State *
2305luaV_newstate(void)
2306{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002307 lua_State *L = luaL_newstate();
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002308 luaL_openlibs(L); // core libs
2309 lua_pushcfunction(L, luaopen_vim); // vim
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002310 lua_call(L, 0, 0);
2311 return L;
2312}
2313
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002314 static void
2315luaV_setrange(lua_State *L, int line1, int line2)
2316{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002317 lua_getglobal(L, LUAVIM_NAME);
2318 lua_pushinteger(L, line1);
2319 lua_setfield(L, -2, "firstline");
2320 lua_pushinteger(L, line2);
2321 lua_setfield(L, -2, "lastline");
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002322 lua_pop(L, 1); // vim table
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002323}
2324
2325
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002326// ======= Interface =======
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002327
2328static lua_State *L = NULL;
2329
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002330 static int
Bram Moolenaar1dced572012-04-05 16:54:08 +02002331lua_isopen(void)
Bram Moolenaar2bd6a1b2010-08-12 22:14:01 +02002332{
2333 return L != NULL;
2334}
2335
2336 static int
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002337lua_init(void)
2338{
Bram Moolenaar1dced572012-04-05 16:54:08 +02002339 if (!lua_isopen())
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002340 {
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002341#ifdef DYNAMIC_LUA
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002342 if (!lua_enabled(TRUE))
2343 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002344 emsg(_("Lua library cannot be loaded."));
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002345 return FAIL;
2346 }
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002347#endif
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002348 L = luaV_newstate();
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002349 }
2350 return OK;
2351}
2352
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002353 void
2354lua_end(void)
2355{
Bram Moolenaar1dced572012-04-05 16:54:08 +02002356 if (lua_isopen())
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002357 {
2358 lua_close(L);
2359 L = NULL;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002360 }
2361}
2362
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002363/*
2364 * ex commands
2365 */
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002366 void
2367ex_lua(exarg_T *eap)
2368{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002369 char *script;
2370 if (lua_init() == FAIL) return;
2371 script = (char *) script_get(eap, eap->arg);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002372 if (!eap->skip)
2373 {
2374 char *s = (script) ? script : (char *) eap->arg;
2375 luaV_setrange(L, eap->line1, eap->line2);
2376 if (luaL_loadbuffer(L, s, strlen(s), LUAVIM_CHUNKNAME)
2377 || lua_pcall(L, 0, 0, 0))
2378 luaV_emsg(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002379 }
2380 if (script != NULL) vim_free(script);
2381}
2382
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002383 void
2384ex_luado(exarg_T *eap)
2385{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002386 linenr_T l;
2387 const char *s = (const char *) eap->arg;
2388 luaL_Buffer b;
2389 size_t len;
Bram Moolenaard58f03b2017-01-29 22:48:45 +01002390 buf_T *was_curbuf = curbuf;
2391
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002392 if (lua_init() == FAIL) return;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002393 if (u_save(eap->line1 - 1, eap->line2 + 1) == FAIL)
2394 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002395 emsg(_("cannot save undo information"));
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002396 return;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002397 }
2398 luaV_setrange(L, eap->line1, eap->line2);
2399 luaL_buffinit(L, &b);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002400 luaL_addlstring(&b, "return function(line, linenr) ", 30); // header
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002401 luaL_addlstring(&b, s, strlen(s));
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002402 luaL_addlstring(&b, " end", 4); // footer
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002403 luaL_pushresult(&b);
2404 s = lua_tolstring(L, -1, &len);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002405 if (luaL_loadbuffer(L, s, len, LUAVIM_CHUNKNAME))
2406 {
2407 luaV_emsg(L);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002408 lua_pop(L, 1); // function body
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002409 return;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002410 }
2411 lua_call(L, 0, 1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002412 lua_replace(L, -2); // function -> body
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002413 for (l = eap->line1; l <= eap->line2; l++)
2414 {
Bram Moolenaare49b8e82020-07-01 13:52:55 +02002415 // Check the line number, the command may have deleted lines.
Bram Moolenaard58f03b2017-01-29 22:48:45 +01002416 if (l > curbuf->b_ml.ml_line_count)
2417 break;
2418
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002419 lua_pushvalue(L, -1); // function
2420 luaV_pushline(L, curbuf, l); // current line as arg
2421 lua_pushinteger(L, l); // current line number as arg
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +02002422 if (lua_pcall(L, 2, 1, 0))
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002423 {
2424 luaV_emsg(L);
2425 break;
2426 }
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002427 // Catch the command switching to another buffer.
Bram Moolenaard58f03b2017-01-29 22:48:45 +01002428 if (curbuf != was_curbuf)
2429 break;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002430 if (lua_isstring(L, -1)) // update line?
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002431 {
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002432#ifdef HAVE_SANDBOX
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002433 luaV_checksandbox(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002434#endif
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002435 ml_replace(l, luaV_toline(L, -1), TRUE);
2436 changed_bytes(l, 0);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002437 lua_pop(L, 1); // result from luaV_toline
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002438 }
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002439 lua_pop(L, 1); // line
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002440 }
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002441 lua_pop(L, 1); // function
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002442 check_cursor();
2443 update_screen(NOT_VALID);
2444}
2445
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002446 void
2447ex_luafile(exarg_T *eap)
2448{
2449 if (lua_init() == FAIL)
2450 return;
2451 if (!eap->skip)
2452 {
2453 luaV_setrange(L, eap->line1, eap->line2);
2454 if (luaL_loadfile(L, (char *) eap->arg) || lua_pcall(L, 0, 0, 0))
2455 luaV_emsg(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002456 }
2457}
2458
Bram Moolenaar1dced572012-04-05 16:54:08 +02002459#define luaV_freetype(typ,tname) \
2460 void \
2461 lua_##tname##_free(typ *o) \
2462 { \
2463 if (!lua_isopen()) return; \
2464 luaV_getfield(L, LUAVIM_FREE); \
2465 lua_pushlightuserdata(L, (void *) o); \
2466 lua_call(L, 1, 0); \
2467 }
2468
2469luaV_freetype(buf_T, buffer)
2470luaV_freetype(win_T, window)
2471
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002472 void
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002473do_luaeval(char_u *str, typval_T *arg, typval_T *rettv)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002474{
Bram Moolenaar1dced572012-04-05 16:54:08 +02002475 lua_init();
2476 luaV_getfield(L, LUAVIM_LUAEVAL);
2477 lua_pushstring(L, (char *) str);
2478 lua_pushlightuserdata(L, (void *) arg);
2479 lua_pushlightuserdata(L, (void *) rettv);
2480 lua_call(L, 3, 0);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002481}
2482
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01002483 int
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002484set_ref_in_lua(int copyID)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002485{
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01002486 int aborted = 0;
2487
2488 if (lua_isopen())
2489 {
2490 luaV_getfield(L, LUAVIM_SETREF);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002491 // call the function with 1 arg, getting 1 result back
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01002492 lua_pushinteger(L, copyID);
2493 lua_call(L, 1, 1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002494 // get the result
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01002495 aborted = lua_tointeger(L, -1);
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01002496 // pop result off the stack
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01002497 lua_pop(L, 1);
2498 }
2499 return aborted;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002500}
2501
Bram Moolenaar788fbb42020-05-31 14:08:12 +02002502 void
2503update_package_paths_in_lua()
2504{
2505 if (lua_isopen())
2506 {
2507 lua_getglobal(L, "vim");
2508 lua_getfield(L, -1, "_update_package_paths");
2509
2510 if (lua_pcall(L, 0, 0, 0))
2511 luaV_emsg(L);
2512 }
2513}
2514
Bram Moolenaar801ab062020-06-25 19:27:56 +02002515/*
2516 * Native C function callback
2517 */
2518 static int
2519luaV_call_lua_func(
2520 int argcount,
2521 typval_T *argvars,
2522 typval_T *rettv,
2523 void *state)
2524{
2525 int i;
2526 int luaargcount = argcount;
2527 luaV_CFuncState *funcstate = (luaV_CFuncState*)state;
2528 lua_rawgeti(funcstate->L, LUA_REGISTRYINDEX, funcstate->lua_funcref);
2529
2530 if (funcstate->lua_tableref != LUA_NOREF)
2531 {
2532 // First arg for metatable __call method is a table
2533 luaargcount += 1;
2534 lua_rawgeti(funcstate->L, LUA_REGISTRYINDEX, funcstate->lua_tableref);
2535 }
2536
2537 for (i = 0; i < argcount; ++i)
2538 luaV_pushtypval(funcstate->L, &argvars[i]);
2539
2540 if (lua_pcall(funcstate->L, luaargcount, 1, 0))
2541 {
2542 luaV_emsg(funcstate->L);
2543 return FCERR_OTHER;
2544 }
2545
2546 luaV_checktypval(funcstate->L, -1, rettv, "get return value");
2547 return FCERR_NONE;
2548}
2549
2550/*
2551 * Free up any lua references held by the func state.
2552 */
2553 static void
2554luaV_call_lua_func_free(void *state)
2555{
2556 luaV_CFuncState *funcstate = (luaV_CFuncState*)state;
2557 luaL_unref(L, LUA_REGISTRYINDEX, funcstate->lua_funcref);
2558 funcstate->L = NULL;
2559 if (funcstate->lua_tableref != LUA_NOREF)
2560 luaL_unref(L, LUA_REGISTRYINDEX, funcstate->lua_tableref);
2561 VIM_CLEAR(funcstate);
2562}
2563
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002564#endif