blob: 0dcb63f1b99339a524072a0740e94741787adade [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
18/* Only do the following when the feature is enabled. Needed for "make
19 * depend". */
20#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 Moolenaarca06da92018-07-01 15:12:05 +020031typedef struct {
Bram Moolenaar4eefe472019-03-19 21:59:19 +010032 char_u *name; // funcref
Bram Moolenaarca06da92018-07-01 15:12:05 +020033 dict_T *self; // selfdict
34} luaV_Funcref;
Bram Moolenaar0ba04292010-07-14 23:23:17 +020035typedef void (*msgfunc_T)(char_u *);
36
Bram Moolenaar1dced572012-04-05 16:54:08 +020037static const char LUAVIM_DICT[] = "dict";
38static const char LUAVIM_LIST[] = "list";
Bram Moolenaarca06da92018-07-01 15:12:05 +020039static const char LUAVIM_FUNCREF[] = "funcref";
Bram Moolenaar0ba04292010-07-14 23:23:17 +020040static const char LUAVIM_BUFFER[] = "buffer";
41static const char LUAVIM_WINDOW[] = "window";
42static const char LUAVIM_FREE[] = "luaV_free";
Bram Moolenaar1dced572012-04-05 16:54:08 +020043static const char LUAVIM_LUAEVAL[] = "luaV_luaeval";
44static const char LUAVIM_SETREF[] = "luaV_setref";
Bram Moolenaar0ba04292010-07-14 23:23:17 +020045
Bram Moolenaar1dced572012-04-05 16:54:08 +020046/* most functions are closures with a cache table as first upvalue;
47 * get/setudata manage references to vim userdata in cache table through
48 * object pointers (light userdata) */
49#define luaV_getudata(L, v) \
50 lua_pushlightuserdata((L), (void *) (v)); \
51 lua_rawget((L), lua_upvalueindex(1))
52#define luaV_setudata(L, v) \
53 lua_pushlightuserdata((L), (void *) (v)); \
54 lua_pushvalue((L), -2); \
55 lua_rawset((L), lua_upvalueindex(1))
Bram Moolenaar0ba04292010-07-14 23:23:17 +020056#define luaV_getfield(L, s) \
57 lua_pushlightuserdata((L), (void *)(s)); \
58 lua_rawget((L), LUA_REGISTRYINDEX)
59#define luaV_checksandbox(L) \
60 if (sandbox) luaL_error((L), "not allowed in sandbox")
61#define luaV_msg(L) luaV_msgfunc((L), (msgfunc_T) msg)
62#define luaV_emsg(L) luaV_msgfunc((L), (msgfunc_T) emsg)
Bram Moolenaarca06da92018-07-01 15:12:05 +020063#define luaV_checktypval(L, a, v, msg) \
64 do { \
65 if (luaV_totypval(L, a, v) == FAIL) \
66 luaL_error(L, msg ": cannot convert value"); \
67 } while (0)
Bram Moolenaar0ba04292010-07-14 23:23:17 +020068
Bram Moolenaarca06da92018-07-01 15:12:05 +020069static luaV_List *luaV_pushlist(lua_State *L, list_T *lis);
70static luaV_Dict *luaV_pushdict(lua_State *L, dict_T *dic);
Bram Moolenaar4eefe472019-03-19 21:59:19 +010071static luaV_Funcref *luaV_pushfuncref(lua_State *L, char_u *name);
Bram Moolenaar1dced572012-04-05 16:54:08 +020072
73#if LUA_VERSION_NUM <= 501
74#define luaV_openlib(L, l, n) luaL_openlib(L, NULL, l, n)
75#define luaL_typeerror luaL_typerror
76#else
77#define luaV_openlib luaL_setfuncs
78#endif
Bram Moolenaar0ba04292010-07-14 23:23:17 +020079
80#ifdef DYNAMIC_LUA
Bram Moolenaar2334b6d2010-07-22 21:32:16 +020081
Bram Moolenaar4f974752019-02-17 17:44:42 +010082#ifndef MSWIN
Bram Moolenaar2334b6d2010-07-22 21:32:16 +020083# include <dlfcn.h>
84# define HANDLE void*
85# define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL)
86# define symbol_from_dll dlsym
87# define close_dll dlclose
88#else
Bram Moolenaarebbcb822010-10-23 14:02:54 +020089# define load_dll vimLoadLib
Bram Moolenaar2334b6d2010-07-22 21:32:16 +020090# define symbol_from_dll GetProcAddress
91# define close_dll FreeLibrary
92#endif
93
Bram Moolenaar0ba04292010-07-14 23:23:17 +020094/* lauxlib */
Bram Moolenaar1dced572012-04-05 16:54:08 +020095#if LUA_VERSION_NUM <= 501
Bram Moolenaar0ba04292010-07-14 23:23:17 +020096#define luaL_register dll_luaL_register
Bram Moolenaar1dced572012-04-05 16:54:08 +020097#define luaL_prepbuffer dll_luaL_prepbuffer
98#define luaL_openlib dll_luaL_openlib
Bram Moolenaar0ba04292010-07-14 23:23:17 +020099#define luaL_typerror dll_luaL_typerror
Bram Moolenaar1dced572012-04-05 16:54:08 +0200100#define luaL_loadfile dll_luaL_loadfile
101#define luaL_loadbuffer dll_luaL_loadbuffer
102#else
103#define luaL_prepbuffsize dll_luaL_prepbuffsize
104#define luaL_setfuncs dll_luaL_setfuncs
105#define luaL_loadfilex dll_luaL_loadfilex
106#define luaL_loadbufferx dll_luaL_loadbufferx
107#define luaL_argerror dll_luaL_argerror
108#endif
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +0200109#define luaL_checkany dll_luaL_checkany
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200110#define luaL_checklstring dll_luaL_checklstring
111#define luaL_checkinteger dll_luaL_checkinteger
112#define luaL_optinteger dll_luaL_optinteger
113#define luaL_checktype dll_luaL_checktype
114#define luaL_error dll_luaL_error
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200115#define luaL_newstate dll_luaL_newstate
116#define luaL_buffinit dll_luaL_buffinit
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200117#define luaL_addlstring dll_luaL_addlstring
118#define luaL_pushresult dll_luaL_pushresult
119/* lua */
Bram Moolenaar1dced572012-04-05 16:54:08 +0200120#if LUA_VERSION_NUM <= 501
121#define lua_tonumber dll_lua_tonumber
122#define lua_tointeger dll_lua_tointeger
123#define lua_call dll_lua_call
124#define lua_pcall dll_lua_pcall
125#else
126#define lua_tonumberx dll_lua_tonumberx
127#define lua_tointegerx dll_lua_tointegerx
128#define lua_callk dll_lua_callk
129#define lua_pcallk dll_lua_pcallk
130#define lua_getglobal dll_lua_getglobal
131#define lua_setglobal dll_lua_setglobal
Bram Moolenaar1dced572012-04-05 16:54:08 +0200132#endif
Bram Moolenaar1f860d82015-06-27 18:36:16 +0200133#if LUA_VERSION_NUM <= 502
134#define lua_replace dll_lua_replace
135#define lua_remove dll_lua_remove
136#endif
137#if LUA_VERSION_NUM >= 503
138#define lua_rotate dll_lua_rotate
139#define lua_copy dll_lua_copy
140#endif
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +0200141#define lua_typename dll_lua_typename
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200142#define lua_close dll_lua_close
143#define lua_gettop dll_lua_gettop
144#define lua_settop dll_lua_settop
145#define lua_pushvalue dll_lua_pushvalue
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200146#define lua_isnumber dll_lua_isnumber
147#define lua_isstring dll_lua_isstring
148#define lua_type dll_lua_type
149#define lua_rawequal dll_lua_rawequal
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200150#define lua_toboolean dll_lua_toboolean
151#define lua_tolstring dll_lua_tolstring
152#define lua_touserdata dll_lua_touserdata
153#define lua_pushnil dll_lua_pushnil
154#define lua_pushnumber dll_lua_pushnumber
155#define lua_pushinteger dll_lua_pushinteger
156#define lua_pushlstring dll_lua_pushlstring
157#define lua_pushstring dll_lua_pushstring
158#define lua_pushfstring dll_lua_pushfstring
159#define lua_pushcclosure dll_lua_pushcclosure
160#define lua_pushboolean dll_lua_pushboolean
161#define lua_pushlightuserdata dll_lua_pushlightuserdata
162#define lua_getfield dll_lua_getfield
163#define lua_rawget dll_lua_rawget
Bram Moolenaar1dced572012-04-05 16:54:08 +0200164#define lua_rawgeti dll_lua_rawgeti
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200165#define lua_createtable dll_lua_createtable
Bram Moolenaar830e3582018-08-21 14:23:35 +0200166#if LUA_VERSION_NUM >= 504
167 #define lua_newuserdatauv dll_lua_newuserdatauv
168#else
169 #define lua_newuserdata dll_lua_newuserdata
170#endif
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200171#define lua_getmetatable dll_lua_getmetatable
172#define lua_setfield dll_lua_setfield
173#define lua_rawset dll_lua_rawset
174#define lua_rawseti dll_lua_rawseti
175#define lua_setmetatable dll_lua_setmetatable
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +0200176#define lua_next dll_lua_next
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200177/* libs */
178#define luaopen_base dll_luaopen_base
179#define luaopen_table dll_luaopen_table
180#define luaopen_string dll_luaopen_string
181#define luaopen_math dll_luaopen_math
Bram Moolenaar16c98f92010-07-28 22:46:08 +0200182#define luaopen_io dll_luaopen_io
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200183#define luaopen_os dll_luaopen_os
184#define luaopen_package dll_luaopen_package
185#define luaopen_debug dll_luaopen_debug
Bram Moolenaar16c98f92010-07-28 22:46:08 +0200186#define luaL_openlibs dll_luaL_openlibs
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200187
188/* lauxlib */
Bram Moolenaar1dced572012-04-05 16:54:08 +0200189#if LUA_VERSION_NUM <= 501
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200190void (*dll_luaL_register) (lua_State *L, const char *libname, const luaL_Reg *l);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200191char *(*dll_luaL_prepbuffer) (luaL_Buffer *B);
192void (*dll_luaL_openlib) (lua_State *L, const char *libname, const luaL_Reg *l, int nup);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200193int (*dll_luaL_typerror) (lua_State *L, int narg, const char *tname);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200194int (*dll_luaL_loadfile) (lua_State *L, const char *filename);
195int (*dll_luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, const char *name);
196#else
197char *(*dll_luaL_prepbuffsize) (luaL_Buffer *B, size_t sz);
198void (*dll_luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
199int (*dll_luaL_loadfilex) (lua_State *L, const char *filename, const char *mode);
200int (*dll_luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode);
201int (*dll_luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
202#endif
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +0200203void (*dll_luaL_checkany) (lua_State *L, int narg);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200204const char *(*dll_luaL_checklstring) (lua_State *L, int numArg, size_t *l);
205lua_Integer (*dll_luaL_checkinteger) (lua_State *L, int numArg);
206lua_Integer (*dll_luaL_optinteger) (lua_State *L, int nArg, lua_Integer def);
207void (*dll_luaL_checktype) (lua_State *L, int narg, int t);
208int (*dll_luaL_error) (lua_State *L, const char *fmt, ...);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200209lua_State *(*dll_luaL_newstate) (void);
210void (*dll_luaL_buffinit) (lua_State *L, luaL_Buffer *B);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200211void (*dll_luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
212void (*dll_luaL_pushresult) (luaL_Buffer *B);
213/* lua */
Bram Moolenaar1dced572012-04-05 16:54:08 +0200214#if LUA_VERSION_NUM <= 501
215lua_Number (*dll_lua_tonumber) (lua_State *L, int idx);
216lua_Integer (*dll_lua_tointeger) (lua_State *L, int idx);
217void (*dll_lua_call) (lua_State *L, int nargs, int nresults);
218int (*dll_lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
219#else
220lua_Number (*dll_lua_tonumberx) (lua_State *L, int idx, int *isnum);
221lua_Integer (*dll_lua_tointegerx) (lua_State *L, int idx, int *isnum);
222void (*dll_lua_callk) (lua_State *L, int nargs, int nresults, int ctx,
Bram Moolenaardb913952012-06-29 12:54:53 +0200223 lua_CFunction k);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200224int (*dll_lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc,
Bram Moolenaardb913952012-06-29 12:54:53 +0200225 int ctx, lua_CFunction k);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200226void (*dll_lua_getglobal) (lua_State *L, const char *var);
227void (*dll_lua_setglobal) (lua_State *L, const char *var);
Bram Moolenaar1f860d82015-06-27 18:36:16 +0200228#endif
229#if LUA_VERSION_NUM <= 502
230void (*dll_lua_replace) (lua_State *L, int idx);
231void (*dll_lua_remove) (lua_State *L, int idx);
232#endif
233#if LUA_VERSION_NUM >= 503
234void (*dll_lua_rotate) (lua_State *L, int idx, int n);
Bram Moolenaar9514b1f2015-06-25 18:27:32 +0200235void (*dll_lua_copy) (lua_State *L, int fromidx, int toidx);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200236#endif
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +0200237const char *(*dll_lua_typename) (lua_State *L, int tp);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200238void (*dll_lua_close) (lua_State *L);
239int (*dll_lua_gettop) (lua_State *L);
240void (*dll_lua_settop) (lua_State *L, int idx);
241void (*dll_lua_pushvalue) (lua_State *L, int idx);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200242int (*dll_lua_isnumber) (lua_State *L, int idx);
243int (*dll_lua_isstring) (lua_State *L, int idx);
244int (*dll_lua_type) (lua_State *L, int idx);
245int (*dll_lua_rawequal) (lua_State *L, int idx1, int idx2);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200246int (*dll_lua_toboolean) (lua_State *L, int idx);
247const char *(*dll_lua_tolstring) (lua_State *L, int idx, size_t *len);
248void *(*dll_lua_touserdata) (lua_State *L, int idx);
249void (*dll_lua_pushnil) (lua_State *L);
250void (*dll_lua_pushnumber) (lua_State *L, lua_Number n);
251void (*dll_lua_pushinteger) (lua_State *L, lua_Integer n);
252void (*dll_lua_pushlstring) (lua_State *L, const char *s, size_t l);
253void (*dll_lua_pushstring) (lua_State *L, const char *s);
254const char *(*dll_lua_pushfstring) (lua_State *L, const char *fmt, ...);
255void (*dll_lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
256void (*dll_lua_pushboolean) (lua_State *L, int b);
257void (*dll_lua_pushlightuserdata) (lua_State *L, void *p);
258void (*dll_lua_getfield) (lua_State *L, int idx, const char *k);
Bram Moolenaar17413672018-07-14 20:49:42 +0200259#if LUA_VERSION_NUM <= 502
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200260void (*dll_lua_rawget) (lua_State *L, int idx);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200261void (*dll_lua_rawgeti) (lua_State *L, int idx, int n);
Bram Moolenaar17413672018-07-14 20:49:42 +0200262#else
263int (*dll_lua_rawget) (lua_State *L, int idx);
264int (*dll_lua_rawgeti) (lua_State *L, int idx, lua_Integer n);
265#endif
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200266void (*dll_lua_createtable) (lua_State *L, int narr, int nrec);
Bram Moolenaar830e3582018-08-21 14:23:35 +0200267#if LUA_VERSION_NUM >= 504
268void *(*dll_lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue);
269#else
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200270void *(*dll_lua_newuserdata) (lua_State *L, size_t sz);
Bram Moolenaar830e3582018-08-21 14:23:35 +0200271#endif
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200272int (*dll_lua_getmetatable) (lua_State *L, int objindex);
273void (*dll_lua_setfield) (lua_State *L, int idx, const char *k);
274void (*dll_lua_rawset) (lua_State *L, int idx);
Bram Moolenaar17413672018-07-14 20:49:42 +0200275#if LUA_VERSION_NUM <= 502
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200276void (*dll_lua_rawseti) (lua_State *L, int idx, int n);
Bram Moolenaar17413672018-07-14 20:49:42 +0200277#else
278void (*dll_lua_rawseti) (lua_State *L, int idx, lua_Integer n);
279#endif
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200280int (*dll_lua_setmetatable) (lua_State *L, int objindex);
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +0200281int (*dll_lua_next) (lua_State *L, int idx);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200282/* libs */
283int (*dll_luaopen_base) (lua_State *L);
284int (*dll_luaopen_table) (lua_State *L);
285int (*dll_luaopen_string) (lua_State *L);
286int (*dll_luaopen_math) (lua_State *L);
Bram Moolenaar16c98f92010-07-28 22:46:08 +0200287int (*dll_luaopen_io) (lua_State *L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200288int (*dll_luaopen_os) (lua_State *L);
289int (*dll_luaopen_package) (lua_State *L);
290int (*dll_luaopen_debug) (lua_State *L);
Bram Moolenaar16c98f92010-07-28 22:46:08 +0200291void (*dll_luaL_openlibs) (lua_State *L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200292
293typedef void **luaV_function;
294typedef struct {
295 const char *name;
296 luaV_function func;
297} luaV_Reg;
298
299static const luaV_Reg luaV_dll[] = {
300 /* lauxlib */
Bram Moolenaar1dced572012-04-05 16:54:08 +0200301#if LUA_VERSION_NUM <= 501
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200302 {"luaL_register", (luaV_function) &dll_luaL_register},
Bram Moolenaar1dced572012-04-05 16:54:08 +0200303 {"luaL_prepbuffer", (luaV_function) &dll_luaL_prepbuffer},
304 {"luaL_openlib", (luaV_function) &dll_luaL_openlib},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200305 {"luaL_typerror", (luaV_function) &dll_luaL_typerror},
Bram Moolenaar1dced572012-04-05 16:54:08 +0200306 {"luaL_loadfile", (luaV_function) &dll_luaL_loadfile},
307 {"luaL_loadbuffer", (luaV_function) &dll_luaL_loadbuffer},
308#else
309 {"luaL_prepbuffsize", (luaV_function) &dll_luaL_prepbuffsize},
310 {"luaL_setfuncs", (luaV_function) &dll_luaL_setfuncs},
311 {"luaL_loadfilex", (luaV_function) &dll_luaL_loadfilex},
312 {"luaL_loadbufferx", (luaV_function) &dll_luaL_loadbufferx},
313 {"luaL_argerror", (luaV_function) &dll_luaL_argerror},
314#endif
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +0200315 {"luaL_checkany", (luaV_function) &dll_luaL_checkany},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200316 {"luaL_checklstring", (luaV_function) &dll_luaL_checklstring},
317 {"luaL_checkinteger", (luaV_function) &dll_luaL_checkinteger},
318 {"luaL_optinteger", (luaV_function) &dll_luaL_optinteger},
319 {"luaL_checktype", (luaV_function) &dll_luaL_checktype},
320 {"luaL_error", (luaV_function) &dll_luaL_error},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200321 {"luaL_newstate", (luaV_function) &dll_luaL_newstate},
322 {"luaL_buffinit", (luaV_function) &dll_luaL_buffinit},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200323 {"luaL_addlstring", (luaV_function) &dll_luaL_addlstring},
324 {"luaL_pushresult", (luaV_function) &dll_luaL_pushresult},
325 /* lua */
Bram Moolenaar1dced572012-04-05 16:54:08 +0200326#if LUA_VERSION_NUM <= 501
327 {"lua_tonumber", (luaV_function) &dll_lua_tonumber},
328 {"lua_tointeger", (luaV_function) &dll_lua_tointeger},
329 {"lua_call", (luaV_function) &dll_lua_call},
330 {"lua_pcall", (luaV_function) &dll_lua_pcall},
331#else
332 {"lua_tonumberx", (luaV_function) &dll_lua_tonumberx},
333 {"lua_tointegerx", (luaV_function) &dll_lua_tointegerx},
334 {"lua_callk", (luaV_function) &dll_lua_callk},
335 {"lua_pcallk", (luaV_function) &dll_lua_pcallk},
336 {"lua_getglobal", (luaV_function) &dll_lua_getglobal},
337 {"lua_setglobal", (luaV_function) &dll_lua_setglobal},
Bram Moolenaar1dced572012-04-05 16:54:08 +0200338#endif
Bram Moolenaar1f860d82015-06-27 18:36:16 +0200339#if LUA_VERSION_NUM <= 502
340 {"lua_replace", (luaV_function) &dll_lua_replace},
341 {"lua_remove", (luaV_function) &dll_lua_remove},
342#endif
343#if LUA_VERSION_NUM >= 503
344 {"lua_rotate", (luaV_function) &dll_lua_rotate},
345 {"lua_copy", (luaV_function) &dll_lua_copy},
346#endif
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +0200347 {"lua_typename", (luaV_function) &dll_lua_typename},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200348 {"lua_close", (luaV_function) &dll_lua_close},
349 {"lua_gettop", (luaV_function) &dll_lua_gettop},
350 {"lua_settop", (luaV_function) &dll_lua_settop},
351 {"lua_pushvalue", (luaV_function) &dll_lua_pushvalue},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200352 {"lua_isnumber", (luaV_function) &dll_lua_isnumber},
353 {"lua_isstring", (luaV_function) &dll_lua_isstring},
354 {"lua_type", (luaV_function) &dll_lua_type},
355 {"lua_rawequal", (luaV_function) &dll_lua_rawequal},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200356 {"lua_toboolean", (luaV_function) &dll_lua_toboolean},
357 {"lua_tolstring", (luaV_function) &dll_lua_tolstring},
358 {"lua_touserdata", (luaV_function) &dll_lua_touserdata},
359 {"lua_pushnil", (luaV_function) &dll_lua_pushnil},
360 {"lua_pushnumber", (luaV_function) &dll_lua_pushnumber},
361 {"lua_pushinteger", (luaV_function) &dll_lua_pushinteger},
362 {"lua_pushlstring", (luaV_function) &dll_lua_pushlstring},
363 {"lua_pushstring", (luaV_function) &dll_lua_pushstring},
364 {"lua_pushfstring", (luaV_function) &dll_lua_pushfstring},
365 {"lua_pushcclosure", (luaV_function) &dll_lua_pushcclosure},
366 {"lua_pushboolean", (luaV_function) &dll_lua_pushboolean},
367 {"lua_pushlightuserdata", (luaV_function) &dll_lua_pushlightuserdata},
368 {"lua_getfield", (luaV_function) &dll_lua_getfield},
369 {"lua_rawget", (luaV_function) &dll_lua_rawget},
Bram Moolenaar1dced572012-04-05 16:54:08 +0200370 {"lua_rawgeti", (luaV_function) &dll_lua_rawgeti},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200371 {"lua_createtable", (luaV_function) &dll_lua_createtable},
Bram Moolenaar830e3582018-08-21 14:23:35 +0200372#if LUA_VERSION_NUM >= 504
373 {"lua_newuserdatauv", (luaV_function) &dll_lua_newuserdatauv},
374#else
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200375 {"lua_newuserdata", (luaV_function) &dll_lua_newuserdata},
Bram Moolenaar830e3582018-08-21 14:23:35 +0200376#endif
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200377 {"lua_getmetatable", (luaV_function) &dll_lua_getmetatable},
378 {"lua_setfield", (luaV_function) &dll_lua_setfield},
379 {"lua_rawset", (luaV_function) &dll_lua_rawset},
380 {"lua_rawseti", (luaV_function) &dll_lua_rawseti},
381 {"lua_setmetatable", (luaV_function) &dll_lua_setmetatable},
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +0200382 {"lua_next", (luaV_function) &dll_lua_next},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200383 /* libs */
384 {"luaopen_base", (luaV_function) &dll_luaopen_base},
385 {"luaopen_table", (luaV_function) &dll_luaopen_table},
386 {"luaopen_string", (luaV_function) &dll_luaopen_string},
387 {"luaopen_math", (luaV_function) &dll_luaopen_math},
Bram Moolenaar16c98f92010-07-28 22:46:08 +0200388 {"luaopen_io", (luaV_function) &dll_luaopen_io},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200389 {"luaopen_os", (luaV_function) &dll_luaopen_os},
390 {"luaopen_package", (luaV_function) &dll_luaopen_package},
391 {"luaopen_debug", (luaV_function) &dll_luaopen_debug},
Bram Moolenaar16c98f92010-07-28 22:46:08 +0200392 {"luaL_openlibs", (luaV_function) &dll_luaL_openlibs},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200393 {NULL, NULL}
394};
395
Bram Moolenaar2334b6d2010-07-22 21:32:16 +0200396static HANDLE hinstLua = NULL;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200397
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200398 static void
399end_dynamic_lua(void)
400{
401 if (hinstLua)
402 {
Bram Moolenaar2334b6d2010-07-22 21:32:16 +0200403 close_dll(hinstLua);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200404 hinstLua = 0;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200405 }
406}
407
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200408 static int
409lua_link_init(char *libname, int verbose)
410{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200411 const luaV_Reg *reg;
412 if (hinstLua) return OK;
Bram Moolenaar2334b6d2010-07-22 21:32:16 +0200413 hinstLua = load_dll(libname);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200414 if (!hinstLua)
415 {
416 if (verbose)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100417 semsg(_(e_loadlib), libname);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200418 return FAIL;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200419 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200420 for (reg = luaV_dll; reg->func; reg++)
421 {
Bram Moolenaar2334b6d2010-07-22 21:32:16 +0200422 if ((*reg->func = symbol_from_dll(hinstLua, reg->name)) == NULL)
423 {
424 close_dll(hinstLua);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200425 hinstLua = 0;
426 if (verbose)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100427 semsg(_(e_loadfunc), reg->name);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200428 return FAIL;
429 }
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200430 }
431 return OK;
432}
Bram Moolenaard90b6c02016-08-28 18:10:45 +0200433#endif /* DYNAMIC_LUA */
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200434
Bram Moolenaard90b6c02016-08-28 18:10:45 +0200435#if defined(DYNAMIC_LUA) || defined(PROTO)
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200436 int
437lua_enabled(int verbose)
438{
Bram Moolenaar25e4fcd2016-01-09 14:57:47 +0100439 return lua_link_init((char *)p_luadll, verbose) == OK;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200440}
Bram Moolenaard90b6c02016-08-28 18:10:45 +0200441#endif
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200442
Bram Moolenaar1dced572012-04-05 16:54:08 +0200443#if LUA_VERSION_NUM > 501
444 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100445luaL_typeerror(lua_State *L, int narg, const char *tname)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200446{
447 const char *msg = lua_pushfstring(L, "%s expected, got %s",
Bram Moolenaardb913952012-06-29 12:54:53 +0200448 tname, luaL_typename(L, narg));
Bram Moolenaar1dced572012-04-05 16:54:08 +0200449 return luaL_argerror(L, narg, msg);
450}
451#endif
452
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200453
454/* ======= Internal ======= */
455
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200456 static void
457luaV_newmetatable(lua_State *L, const char *tname)
458{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200459 lua_newtable(L);
460 lua_pushlightuserdata(L, (void *) tname);
461 lua_pushvalue(L, -2);
462 lua_rawset(L, LUA_REGISTRYINDEX);
463}
464
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200465 static void *
466luaV_toudata(lua_State *L, int ud, const char *tname)
467{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200468 void *p = lua_touserdata(L, ud);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200469
470 if (p != NULL) /* value is userdata? */
471 {
472 if (lua_getmetatable(L, ud)) /* does it have a metatable? */
473 {
474 luaV_getfield(L, tname); /* get metatable */
475 if (lua_rawequal(L, -1, -2)) /* MTs match? */
476 {
477 lua_pop(L, 2); /* MTs */
478 return p;
479 }
480 }
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200481 }
482 return NULL;
483}
484
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200485 static void *
Bram Moolenaar1dced572012-04-05 16:54:08 +0200486luaV_checkcache(lua_State *L, void *p)
487{
488 luaV_getudata(L, p);
489 if (lua_isnil(L, -1)) luaL_error(L, "invalid object");
490 lua_pop(L, 1);
491 return p;
492}
493
494#define luaV_unbox(L,luatyp,ud) (*((luatyp *) lua_touserdata((L),(ud))))
495
496#define luaV_checkvalid(L,luatyp,ud) \
497 luaV_checkcache((L), (void *) luaV_unbox((L),luatyp,(ud)))
498
499 static void *
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200500luaV_checkudata(lua_State *L, int ud, const char *tname)
501{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200502 void *p = luaV_toudata(L, ud, tname);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200503 if (p == NULL) luaL_typeerror(L, ud, tname);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200504 return p;
505}
506
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200507 static void
508luaV_pushtypval(lua_State *L, typval_T *tv)
509{
Bram Moolenaar1dced572012-04-05 16:54:08 +0200510 if (tv == NULL)
511 {
512 lua_pushnil(L);
513 return;
514 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200515 switch (tv->v_type)
516 {
517 case VAR_STRING:
Bram Moolenaard04da7c2012-10-14 03:41:59 +0200518 lua_pushstring(L, tv->vval.v_string == NULL
519 ? "" : (char *)tv->vval.v_string);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200520 break;
521 case VAR_NUMBER:
522 lua_pushinteger(L, (int) tv->vval.v_number);
523 break;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200524#ifdef FEAT_FLOAT
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200525 case VAR_FLOAT:
526 lua_pushnumber(L, (lua_Number) tv->vval.v_float);
527 break;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200528#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +0200529 case VAR_LIST:
530 luaV_pushlist(L, tv->vval.v_list);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200531 break;
Bram Moolenaar1dced572012-04-05 16:54:08 +0200532 case VAR_DICT:
533 luaV_pushdict(L, tv->vval.v_dict);
534 break;
Bram Moolenaar520e1e42016-01-23 19:46:28 +0100535 case VAR_SPECIAL:
536 if (tv->vval.v_number <= VVAL_TRUE)
537 lua_pushinteger(L, (int) tv->vval.v_number);
538 else
539 lua_pushnil(L);
540 break;
Bram Moolenaarca06da92018-07-01 15:12:05 +0200541 case VAR_FUNC:
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100542 luaV_pushfuncref(L, tv->vval.v_string);
Bram Moolenaarca06da92018-07-01 15:12:05 +0200543 break;
Bram Moolenaar1dced572012-04-05 16:54:08 +0200544 default:
545 lua_pushnil(L);
546 }
547}
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200548
Bram Moolenaarca06da92018-07-01 15:12:05 +0200549/*
550 * Converts lua value at 'pos' to typval 'tv'.
551 * Returns OK or FAIL.
552 */
553 static int
554luaV_totypval(lua_State *L, int pos, typval_T *tv)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200555{
Bram Moolenaarca06da92018-07-01 15:12:05 +0200556 int status = OK;
557
558 switch (lua_type(L, pos))
559 {
Bram Moolenaar1dced572012-04-05 16:54:08 +0200560 case LUA_TBOOLEAN:
Bram Moolenaar520e1e42016-01-23 19:46:28 +0100561 tv->v_type = VAR_SPECIAL;
Bram Moolenaar1dced572012-04-05 16:54:08 +0200562 tv->vval.v_number = (varnumber_T) lua_toboolean(L, pos);
563 break;
Bram Moolenaar9067cd62019-01-01 00:41:54 +0100564 case LUA_TNIL:
565 tv->v_type = VAR_SPECIAL;
566 tv->vval.v_number = VVAL_NULL;
567 break;
Bram Moolenaar1dced572012-04-05 16:54:08 +0200568 case LUA_TSTRING:
569 tv->v_type = VAR_STRING;
570 tv->vval.v_string = vim_strsave((char_u *) lua_tostring(L, pos));
571 break;
572 case LUA_TNUMBER:
573#ifdef FEAT_FLOAT
574 tv->v_type = VAR_FLOAT;
575 tv->vval.v_float = (float_T) lua_tonumber(L, pos);
576#else
577 tv->v_type = VAR_NUMBER;
578 tv->vval.v_number = (varnumber_T) lua_tointeger(L, pos);
579#endif
580 break;
Bram Moolenaarca06da92018-07-01 15:12:05 +0200581 case LUA_TUSERDATA:
582 {
Bram Moolenaar1dced572012-04-05 16:54:08 +0200583 void *p = lua_touserdata(L, pos);
Bram Moolenaarca06da92018-07-01 15:12:05 +0200584
Bram Moolenaar1dced572012-04-05 16:54:08 +0200585 if (lua_getmetatable(L, pos)) /* has metatable? */
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200586 {
Bram Moolenaar1dced572012-04-05 16:54:08 +0200587 /* check list */
588 luaV_getfield(L, LUAVIM_LIST);
589 if (lua_rawequal(L, -1, -2))
Bram Moolenaar2334b6d2010-07-22 21:32:16 +0200590 {
Bram Moolenaar1dced572012-04-05 16:54:08 +0200591 tv->v_type = VAR_LIST;
592 tv->vval.v_list = *((luaV_List *) p);
593 ++tv->vval.v_list->lv_refcount;
594 lua_pop(L, 2); /* MTs */
Bram Moolenaarca06da92018-07-01 15:12:05 +0200595 break;
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200596 }
Bram Moolenaar1dced572012-04-05 16:54:08 +0200597 /* check dict */
598 luaV_getfield(L, LUAVIM_DICT);
599 if (lua_rawequal(L, -1, -3))
600 {
601 tv->v_type = VAR_DICT;
602 tv->vval.v_dict = *((luaV_Dict *) p);
603 ++tv->vval.v_dict->dv_refcount;
604 lua_pop(L, 3); /* MTs */
Bram Moolenaarca06da92018-07-01 15:12:05 +0200605 break;
Bram Moolenaar1dced572012-04-05 16:54:08 +0200606 }
Bram Moolenaarca06da92018-07-01 15:12:05 +0200607 /* check funcref */
608 luaV_getfield(L, LUAVIM_FUNCREF);
609 if (lua_rawequal(L, -1, -4))
610 {
611 luaV_Funcref *f = (luaV_Funcref *) p;
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100612 func_ref(f->name);
613 tv->v_type = VAR_FUNC;
614 tv->vval.v_string = vim_strsave(f->name);
Bram Moolenaarca06da92018-07-01 15:12:05 +0200615 lua_pop(L, 4); /* MTs */
616 break;
617 }
618 lua_pop(L, 4); /* MTs */
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200619 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200620 }
Bram Moolenaarca06da92018-07-01 15:12:05 +0200621 /* FALLTHROUGH */
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200622 default:
Bram Moolenaar1dced572012-04-05 16:54:08 +0200623 tv->v_type = VAR_NUMBER;
624 tv->vval.v_number = 0;
Bram Moolenaarca06da92018-07-01 15:12:05 +0200625 status = FAIL;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200626 }
Bram Moolenaarca06da92018-07-01 15:12:05 +0200627 return status;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200628}
629
630/* similar to luaL_addlstring, but replaces \0 with \n if toline and
631 * \n with \0 otherwise */
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200632 static void
633luaV_addlstring(luaL_Buffer *b, const char *s, size_t l, int toline)
634{
635 while (l--)
636 {
637 if (*s == '\0' && toline)
638 luaL_addchar(b, '\n');
639 else if (*s == '\n' && !toline)
640 luaL_addchar(b, '\0');
641 else
642 luaL_addchar(b, *s);
643 s++;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200644 }
645}
646
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200647 static void
648luaV_pushline(lua_State *L, buf_T *buf, linenr_T n)
649{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200650 const char *s = (const char *) ml_get_buf(buf, n, FALSE);
651 luaL_Buffer b;
652 luaL_buffinit(L, &b);
653 luaV_addlstring(&b, s, strlen(s), 0);
654 luaL_pushresult(&b);
655}
656
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200657 static char_u *
658luaV_toline(lua_State *L, int pos)
659{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200660 size_t l;
661 const char *s = lua_tolstring(L, pos, &l);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200662
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200663 luaL_Buffer b;
664 luaL_buffinit(L, &b);
665 luaV_addlstring(&b, s, l, 1);
666 luaL_pushresult(&b);
667 return (char_u *) lua_tostring(L, -1);
668}
669
670/* pops a string s from the top of the stack and calls mf(t) for pieces t of
671 * s separated by newlines */
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200672 static void
673luaV_msgfunc(lua_State *L, msgfunc_T mf)
674{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200675 luaL_Buffer b;
676 size_t l;
677 const char *p, *s = lua_tolstring(L, -1, &l);
678 luaL_buffinit(L, &b);
679 luaV_addlstring(&b, s, l, 0);
680 luaL_pushresult(&b);
681 /* break string */
682 p = s = lua_tolstring(L, -1, &l);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200683 while (l--)
684 {
685 if (*p++ == '\0') /* break? */
686 {
687 mf((char_u *) s);
688 s = p;
689 }
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200690 }
691 mf((char_u *) s);
692 lua_pop(L, 2); /* original and modified strings */
693}
694
Bram Moolenaar1dced572012-04-05 16:54:08 +0200695#define luaV_newtype(typ,tname,luatyp,luatname) \
696 static luatyp * \
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100697 luaV_new##tname(lua_State *L, typ *obj) \
Bram Moolenaar1dced572012-04-05 16:54:08 +0200698 { \
699 luatyp *o = (luatyp *) lua_newuserdata(L, sizeof(luatyp)); \
700 *o = obj; \
701 luaV_setudata(L, obj); /* cache[obj] = udata */ \
702 luaV_getfield(L, luatname); \
703 lua_setmetatable(L, -2); \
704 return o; \
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200705 }
Bram Moolenaar1dced572012-04-05 16:54:08 +0200706
707#define luaV_pushtype(typ,tname,luatyp) \
708 static luatyp * \
Bram Moolenaarca06da92018-07-01 15:12:05 +0200709 luaV_push##tname(lua_State *L, typ *obj) \
Bram Moolenaar1dced572012-04-05 16:54:08 +0200710 { \
711 luatyp *o = NULL; \
712 if (obj == NULL) \
713 lua_pushnil(L); \
714 else { \
715 luaV_getudata(L, obj); \
716 if (lua_isnil(L, -1)) /* not interned? */ \
717 { \
718 lua_pop(L, 1); \
719 o = luaV_new##tname(L, obj); \
720 } \
721 else \
722 o = (luatyp *) lua_touserdata(L, -1); \
723 } \
724 return o; \
725 }
726
727#define luaV_type_tostring(tname,luatname) \
728 static int \
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100729 luaV_##tname##_tostring(lua_State *L) \
Bram Moolenaar1dced572012-04-05 16:54:08 +0200730 { \
731 lua_pushfstring(L, "%s: %p", luatname, lua_touserdata(L, 1)); \
732 return 1; \
733 }
734
Bram Moolenaar1dced572012-04-05 16:54:08 +0200735/* ======= List type ======= */
736
737 static luaV_List *
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100738luaV_newlist(lua_State *L, list_T *lis)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200739{
740 luaV_List *l = (luaV_List *) lua_newuserdata(L, sizeof(luaV_List));
741 *l = lis;
742 lis->lv_refcount++; /* reference in Lua */
743 luaV_setudata(L, lis); /* cache[lis] = udata */
744 luaV_getfield(L, LUAVIM_LIST);
745 lua_setmetatable(L, -2);
746 return l;
747}
748
749luaV_pushtype(list_T, list, luaV_List)
750luaV_type_tostring(list, LUAVIM_LIST)
751
752 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100753luaV_list_len(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200754{
755 list_T *l = luaV_unbox(L, luaV_List, 1);
756 lua_pushinteger(L, (l == NULL) ? 0 : (int) l->lv_len);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200757 return 1;
758}
759
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200760 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100761luaV_list_iter(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200762{
763 listitem_T *li = (listitem_T *) lua_touserdata(L, lua_upvalueindex(2));
764 if (li == NULL) return 0;
765 luaV_pushtypval(L, &li->li_tv);
766 lua_pushlightuserdata(L, (void *) li->li_next);
767 lua_replace(L, lua_upvalueindex(2));
768 return 1;
769}
770
771 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100772luaV_list_call(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200773{
774 list_T *l = luaV_unbox(L, luaV_List, 1);
775 lua_pushvalue(L, lua_upvalueindex(1)); /* pass cache table along */
776 lua_pushlightuserdata(L, (void *) l->lv_first);
777 lua_pushcclosure(L, luaV_list_iter, 2);
778 return 1;
779}
780
781 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100782luaV_list_index(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200783{
784 list_T *l = luaV_unbox(L, luaV_List, 1);
785 if (lua_isnumber(L, 2)) /* list item? */
786 {
787 listitem_T *li = list_find(l, (long) luaL_checkinteger(L, 2));
788 if (li == NULL)
789 lua_pushnil(L);
790 else
791 luaV_pushtypval(L, &li->li_tv);
792 }
793 else if (lua_isstring(L, 2)) /* method? */
794 {
795 const char *s = lua_tostring(L, 2);
796 if (strncmp(s, "add", 3) == 0
Bram Moolenaarb3766472013-04-15 13:49:21 +0200797 || strncmp(s, "insert", 6) == 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200798 {
799 lua_getmetatable(L, 1);
800 lua_getfield(L, -1, s);
801 }
802 else
803 lua_pushnil(L);
804 }
805 else
806 lua_pushnil(L);
807 return 1;
808}
809
810 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100811luaV_list_newindex(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200812{
813 list_T *l = luaV_unbox(L, luaV_List, 1);
814 long n = (long) luaL_checkinteger(L, 2);
815 listitem_T *li;
816 if (l->lv_lock)
817 luaL_error(L, "list is locked");
818 li = list_find(l, n);
819 if (li == NULL) return 0;
820 if (lua_isnil(L, 3)) /* remove? */
821 {
Bram Moolenaar3ec7f4e2014-05-07 17:31:37 +0200822 vimlist_remove(l, li, li);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200823 clear_tv(&li->li_tv);
824 vim_free(li);
825 }
826 else
827 {
828 typval_T v;
Bram Moolenaarca06da92018-07-01 15:12:05 +0200829 luaV_checktypval(L, 3, &v, "setting list item");
Bram Moolenaar1dced572012-04-05 16:54:08 +0200830 clear_tv(&li->li_tv);
831 copy_tv(&v, &li->li_tv);
Bram Moolenaarb3766472013-04-15 13:49:21 +0200832 clear_tv(&v);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200833 }
834 return 0;
835}
836
837 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100838luaV_list_add(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200839{
840 luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST);
841 list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis);
Bram Moolenaarb3766472013-04-15 13:49:21 +0200842 typval_T v;
Bram Moolenaar1dced572012-04-05 16:54:08 +0200843 if (l->lv_lock)
844 luaL_error(L, "list is locked");
Bram Moolenaarb3766472013-04-15 13:49:21 +0200845 lua_settop(L, 2);
Bram Moolenaarca06da92018-07-01 15:12:05 +0200846 luaV_checktypval(L, 2, &v, "adding list item");
Bram Moolenaarb3766472013-04-15 13:49:21 +0200847 if (list_append_tv(l, &v) == FAIL)
Bram Moolenaarca06da92018-07-01 15:12:05 +0200848 luaL_error(L, "failed to add item to list");
Bram Moolenaarb3766472013-04-15 13:49:21 +0200849 clear_tv(&v);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200850 lua_settop(L, 1);
851 return 1;
852}
853
854 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100855luaV_list_insert(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200856{
857 luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST);
858 list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis);
Bram Moolenaar46538ee2015-02-17 16:28:55 +0100859 long pos = (long) luaL_optinteger(L, 3, 0);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200860 listitem_T *li = NULL;
861 typval_T v;
862 if (l->lv_lock)
863 luaL_error(L, "list is locked");
864 if (pos < l->lv_len)
865 {
866 li = list_find(l, pos);
867 if (li == NULL)
868 luaL_error(L, "invalid position");
869 }
870 lua_settop(L, 2);
Bram Moolenaarca06da92018-07-01 15:12:05 +0200871 luaV_checktypval(L, 2, &v, "inserting list item");
Bram Moolenaarb3766472013-04-15 13:49:21 +0200872 if (list_insert_tv(l, &v, li) == FAIL)
Bram Moolenaarca06da92018-07-01 15:12:05 +0200873 luaL_error(L, "failed to add item to list");
Bram Moolenaarb3766472013-04-15 13:49:21 +0200874 clear_tv(&v);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200875 lua_settop(L, 1);
876 return 1;
877}
878
879static const luaL_Reg luaV_List_mt[] = {
880 {"__tostring", luaV_list_tostring},
Bram Moolenaar1dced572012-04-05 16:54:08 +0200881 {"__len", luaV_list_len},
882 {"__call", luaV_list_call},
883 {"__index", luaV_list_index},
884 {"__newindex", luaV_list_newindex},
885 {"add", luaV_list_add},
886 {"insert", luaV_list_insert},
887 {NULL, NULL}
888};
889
890
891/* ======= Dict type ======= */
892
893 static luaV_Dict *
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100894luaV_newdict(lua_State *L, dict_T *dic)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200895{
896 luaV_Dict *d = (luaV_Dict *) lua_newuserdata(L, sizeof(luaV_Dict));
897 *d = dic;
898 dic->dv_refcount++; /* reference in Lua */
899 luaV_setudata(L, dic); /* cache[dic] = udata */
900 luaV_getfield(L, LUAVIM_DICT);
901 lua_setmetatable(L, -2);
902 return d;
903}
904
905luaV_pushtype(dict_T, dict, luaV_Dict)
906luaV_type_tostring(dict, LUAVIM_DICT)
907
908 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100909luaV_dict_len(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200910{
911 dict_T *d = luaV_unbox(L, luaV_Dict, 1);
912 lua_pushinteger(L, (d == NULL) ? 0 : (int) d->dv_hashtab.ht_used);
913 return 1;
914}
915
916 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100917luaV_dict_iter(lua_State *L UNUSED)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200918{
Bram Moolenaarfeeaa682013-02-14 22:19:51 +0100919#ifdef FEAT_EVAL
Bram Moolenaar1dced572012-04-05 16:54:08 +0200920 hashitem_T *hi = (hashitem_T *) lua_touserdata(L, lua_upvalueindex(2));
921 int n = lua_tointeger(L, lua_upvalueindex(3));
922 dictitem_T *di;
923 if (n <= 0) return 0;
924 while (HASHITEM_EMPTY(hi)) hi++;
925 di = dict_lookup(hi);
926 lua_pushstring(L, (char *) hi->hi_key);
927 luaV_pushtypval(L, &di->di_tv);
928 lua_pushlightuserdata(L, (void *) (hi + 1));
929 lua_replace(L, lua_upvalueindex(2));
930 lua_pushinteger(L, n - 1);
931 lua_replace(L, lua_upvalueindex(3));
932 return 2;
Bram Moolenaarfeeaa682013-02-14 22:19:51 +0100933#else
934 return 0;
935#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +0200936}
937
938 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +0100939luaV_dict_call(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200940{
941 dict_T *d = luaV_unbox(L, luaV_Dict, 1);
942 hashtab_T *ht = &d->dv_hashtab;
943 lua_pushvalue(L, lua_upvalueindex(1)); /* pass cache table along */
944 lua_pushlightuserdata(L, (void *) ht->ht_array);
945 lua_pushinteger(L, ht->ht_used); /* # remaining items */
946 lua_pushcclosure(L, luaV_dict_iter, 3);
947 return 1;
948}
949
950 static int
Bram Moolenaarca06da92018-07-01 15:12:05 +0200951luaV_dict_index(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200952{
953 dict_T *d = luaV_unbox(L, luaV_Dict, 1);
954 char_u *key = (char_u *) luaL_checkstring(L, 2);
955 dictitem_T *di = dict_find(d, key, -1);
Bram Moolenaarca06da92018-07-01 15:12:05 +0200956
Bram Moolenaar1dced572012-04-05 16:54:08 +0200957 if (di == NULL)
958 lua_pushnil(L);
959 else
Bram Moolenaarca06da92018-07-01 15:12:05 +0200960 {
Bram Moolenaar1dced572012-04-05 16:54:08 +0200961 luaV_pushtypval(L, &di->di_tv);
Bram Moolenaarca06da92018-07-01 15:12:05 +0200962 if (di->di_tv.v_type == VAR_FUNC) /* funcref? */
963 {
964 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, -1);
965 f->self = d; /* keep "self" reference */
966 d->dv_refcount++;
967 }
968 }
Bram Moolenaar1dced572012-04-05 16:54:08 +0200969 return 1;
970}
971
972 static int
Bram Moolenaarca06da92018-07-01 15:12:05 +0200973luaV_dict_newindex(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +0200974{
975 dict_T *d = luaV_unbox(L, luaV_Dict, 1);
976 char_u *key = (char_u *) luaL_checkstring(L, 2);
977 dictitem_T *di;
Bram Moolenaarca06da92018-07-01 15:12:05 +0200978 typval_T v;
Bram Moolenaar713bf9e92019-03-16 16:38:41 +0100979
Bram Moolenaar1dced572012-04-05 16:54:08 +0200980 if (d->dv_lock)
981 luaL_error(L, "dict is locked");
Bram Moolenaard6ef5f92018-07-13 22:08:23 +0200982 if (key == NULL)
983 return 0;
984 if (*key == NUL)
Bram Moolenaarca06da92018-07-01 15:12:05 +0200985 luaL_error(L, "empty key");
Bram Moolenaar17413672018-07-14 20:49:42 +0200986 if (!lua_isnil(L, 3)) /* read value? */
987 {
Bram Moolenaarca06da92018-07-01 15:12:05 +0200988 luaV_checktypval(L, 3, &v, "setting dict item");
989 if (d->dv_scope == VAR_DEF_SCOPE && v.v_type == VAR_FUNC)
990 luaL_error(L, "cannot assign funcref to builtin scope");
991 }
Bram Moolenaar1dced572012-04-05 16:54:08 +0200992 di = dict_find(d, key, -1);
993 if (di == NULL) /* non-existing key? */
994 {
Bram Moolenaard6ef5f92018-07-13 22:08:23 +0200995 if (lua_isnil(L, 3))
996 return 0;
Bram Moolenaar1dced572012-04-05 16:54:08 +0200997 di = dictitem_alloc(key);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +0200998 if (di == NULL)
999 return 0;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001000 if (dict_add(d, di) == FAIL)
1001 {
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001002 vim_free(di);
1003 return 0;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001004 }
1005 }
1006 else
1007 clear_tv(&di->di_tv);
1008 if (lua_isnil(L, 3)) /* remove? */
1009 {
1010 hashitem_T *hi = hash_find(&d->dv_hashtab, di->di_key);
1011 hash_remove(&d->dv_hashtab, hi);
1012 dictitem_free(di);
1013 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02001014 else
1015 {
Bram Moolenaar1dced572012-04-05 16:54:08 +02001016 copy_tv(&v, &di->di_tv);
Bram Moolenaarb3766472013-04-15 13:49:21 +02001017 clear_tv(&v);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001018 }
1019 return 0;
1020}
1021
1022static const luaL_Reg luaV_Dict_mt[] = {
1023 {"__tostring", luaV_dict_tostring},
Bram Moolenaar1dced572012-04-05 16:54:08 +02001024 {"__len", luaV_dict_len},
1025 {"__call", luaV_dict_call},
1026 {"__index", luaV_dict_index},
1027 {"__newindex", luaV_dict_newindex},
1028 {NULL, NULL}
1029};
1030
1031
Bram Moolenaarca06da92018-07-01 15:12:05 +02001032/* ======= Funcref type ======= */
1033
1034 static luaV_Funcref *
1035luaV_newfuncref(lua_State *L, char_u *name)
1036{
1037 luaV_Funcref *f = (luaV_Funcref *)lua_newuserdata(L, sizeof(luaV_Funcref));
1038
1039 if (name != NULL)
1040 {
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001041 func_ref(name);
1042 f->name = vim_strsave(name);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001043 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02001044 f->self = NULL;
1045 luaV_getfield(L, LUAVIM_FUNCREF);
1046 lua_setmetatable(L, -2);
1047 return f;
1048}
1049
1050 static luaV_Funcref *
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001051luaV_pushfuncref(lua_State *L, char_u *name)
Bram Moolenaarca06da92018-07-01 15:12:05 +02001052{
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001053 return luaV_newfuncref(L, name);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001054}
1055
1056
1057luaV_type_tostring(funcref, LUAVIM_FUNCREF)
1058
1059 static int
1060luaV_funcref_gc(lua_State *L)
1061{
1062 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
1063
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001064 func_unref(f->name);
1065 vim_free(f->name);
1066 // NOTE: Don't call "dict_unref(f->self)", because the dict of "f->self"
1067 // will be (or has been already) freed by Vim's garbage collection.
Bram Moolenaarca06da92018-07-01 15:12:05 +02001068 return 0;
1069}
1070
1071/* equivalent to string(funcref) */
1072 static int
1073luaV_funcref_len(lua_State *L)
1074{
1075 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
1076
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001077 lua_pushstring(L, (const char *) f->name);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001078 return 1;
1079}
1080
1081 static int
1082luaV_funcref_call(lua_State *L)
1083{
1084 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001085 int i, n = lua_gettop(L) - 1; // #args
1086 int status = FAIL;
1087 typval_T args;
1088 typval_T rettv;
Bram Moolenaarca06da92018-07-01 15:12:05 +02001089
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001090 args.v_type = VAR_LIST;
1091 args.vval.v_list = list_alloc();
1092 rettv.v_type = VAR_UNKNOWN; // as in clear_tv
1093 if (args.vval.v_list != NULL)
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001094 {
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001095 typval_T v;
1096
Bram Moolenaar17413672018-07-14 20:49:42 +02001097 for (i = 0; i < n; i++)
1098 {
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001099 luaV_checktypval(L, i + 2, &v, "calling funcref");
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001100 list_append_tv(args.vval.v_list, &v);
Bram Moolenaar713bf9e92019-03-16 16:38:41 +01001101 clear_tv(&v);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001102 }
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001103 status = func_call(f->name, &args, NULL, f->self, &rettv);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001104 if (status == OK)
1105 luaV_pushtypval(L, &rettv);
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001106 clear_tv(&args);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001107 clear_tv(&rettv);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001108 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02001109 if (status != OK)
1110 luaL_error(L, "cannot call funcref");
1111 return 1;
1112}
1113
1114static const luaL_Reg luaV_Funcref_mt[] = {
1115 {"__tostring", luaV_funcref_tostring},
1116 {"__gc", luaV_funcref_gc},
1117 {"__len", luaV_funcref_len},
1118 {"__call", luaV_funcref_call},
1119 {NULL, NULL}
1120};
1121
1122
Bram Moolenaar1dced572012-04-05 16:54:08 +02001123/* ======= Buffer type ======= */
1124
1125luaV_newtype(buf_T, buffer, luaV_Buffer, LUAVIM_BUFFER)
1126luaV_pushtype(buf_T, buffer, luaV_Buffer)
1127luaV_type_tostring(buffer, LUAVIM_BUFFER)
1128
1129 static int
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001130luaV_buffer_len(lua_State *L)
1131{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001132 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
1133 lua_pushinteger(L, b->b_ml.ml_line_count);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001134 return 1;
1135}
1136
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001137 static int
1138luaV_buffer_call(lua_State *L)
1139{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001140 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001141 lua_settop(L, 1);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001142 set_curbuf(b, DOBUF_SPLIT);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001143 return 1;
1144}
1145
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001146 static int
1147luaV_buffer_index(lua_State *L)
1148{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001149 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001150 linenr_T n = (linenr_T) lua_tointeger(L, 2);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001151 if (n > 0 && n <= b->b_ml.ml_line_count)
1152 luaV_pushline(L, b, n);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001153 else if (lua_isstring(L, 2))
1154 {
1155 const char *s = lua_tostring(L, 2);
1156 if (strncmp(s, "name", 4) == 0)
Bram Moolenaarfe08df42018-07-07 23:07:41 +02001157 lua_pushstring(L, (b->b_sfname == NULL)
1158 ? "" : (char *) b->b_sfname);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001159 else if (strncmp(s, "fname", 5) == 0)
Bram Moolenaarfe08df42018-07-07 23:07:41 +02001160 lua_pushstring(L, (b->b_ffname == NULL)
1161 ? "" : (char *) b->b_ffname);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001162 else if (strncmp(s, "number", 6) == 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001163 lua_pushinteger(L, b->b_fnum);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001164 /* methods */
1165 else if (strncmp(s, "insert", 6) == 0
1166 || strncmp(s, "next", 4) == 0
1167 || strncmp(s, "previous", 8) == 0
1168 || strncmp(s, "isvalid", 7) == 0)
1169 {
1170 lua_getmetatable(L, 1);
1171 lua_getfield(L, -1, s);
1172 }
1173 else
1174 lua_pushnil(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001175 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001176 else
1177 lua_pushnil(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001178 return 1;
1179}
1180
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001181 static int
1182luaV_buffer_newindex(lua_State *L)
1183{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001184 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001185 linenr_T n = (linenr_T) luaL_checkinteger(L, 2);
1186#ifdef HAVE_SANDBOX
1187 luaV_checksandbox(L);
1188#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +02001189 if (n < 1 || n > b->b_ml.ml_line_count)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001190 luaL_error(L, "invalid line number");
1191 if (lua_isnil(L, 3)) /* delete line */
1192 {
1193 buf_T *buf = curbuf;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001194 curbuf = b;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001195 if (u_savedel(n, 1L) == FAIL)
1196 {
1197 curbuf = buf;
1198 luaL_error(L, "cannot save undo information");
1199 }
1200 else if (ml_delete(n, FALSE) == FAIL)
1201 {
1202 curbuf = buf;
1203 luaL_error(L, "cannot delete line");
1204 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02001205 else
1206 {
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001207 deleted_lines_mark(n, 1L);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001208 if (b == curwin->w_buffer) /* fix cursor in current window? */
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001209 {
1210 if (curwin->w_cursor.lnum >= n)
1211 {
1212 if (curwin->w_cursor.lnum > n)
1213 {
1214 curwin->w_cursor.lnum -= 1;
1215 check_cursor_col();
1216 }
1217 else check_cursor();
1218 changed_cline_bef_curs();
1219 }
1220 invalidate_botline();
1221 }
1222 }
1223 curbuf = buf;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001224 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001225 else if (lua_isstring(L, 3)) /* update line */
1226 {
1227 buf_T *buf = curbuf;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001228 curbuf = b;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001229 if (u_savesub(n) == FAIL)
1230 {
1231 curbuf = buf;
1232 luaL_error(L, "cannot save undo information");
1233 }
1234 else if (ml_replace(n, luaV_toline(L, 3), TRUE) == FAIL)
1235 {
1236 curbuf = buf;
1237 luaL_error(L, "cannot replace line");
1238 }
1239 else changed_bytes(n, 0);
1240 curbuf = buf;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001241 if (b == curwin->w_buffer)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001242 check_cursor_col();
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001243 }
1244 else
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001245 luaL_error(L, "wrong argument to change line");
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001246 return 0;
1247}
1248
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001249 static int
1250luaV_buffer_insert(lua_State *L)
1251{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001252 luaV_Buffer *lb = luaV_checkudata(L, 1, LUAVIM_BUFFER);
1253 buf_T *b = (buf_T *) luaV_checkcache(L, (void *) *lb);
1254 linenr_T last = b->b_ml.ml_line_count;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001255 linenr_T n = (linenr_T) luaL_optinteger(L, 3, last);
1256 buf_T *buf;
1257 luaL_checktype(L, 2, LUA_TSTRING);
1258#ifdef HAVE_SANDBOX
1259 luaV_checksandbox(L);
1260#endif
1261 /* fix insertion line */
1262 if (n < 0) n = 0;
1263 if (n > last) n = last;
1264 /* insert */
1265 buf = curbuf;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001266 curbuf = b;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001267 if (u_save(n, n + 1) == FAIL)
1268 {
1269 curbuf = buf;
1270 luaL_error(L, "cannot save undo information");
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001271 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001272 else if (ml_append(n, luaV_toline(L, 2), 0, FALSE) == FAIL)
1273 {
1274 curbuf = buf;
1275 luaL_error(L, "cannot insert line");
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001276 }
1277 else
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001278 appended_lines_mark(n, 1L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001279 curbuf = buf;
1280 update_screen(VALID);
1281 return 0;
1282}
1283
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001284 static int
1285luaV_buffer_next(lua_State *L)
1286{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001287 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001288 buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b);
1289 luaV_pushbuffer(L, buf->b_next);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001290 return 1;
1291}
1292
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001293 static int
1294luaV_buffer_previous(lua_State *L)
1295{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001296 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001297 buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b);
1298 luaV_pushbuffer(L, buf->b_prev);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001299 return 1;
1300}
1301
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001302 static int
1303luaV_buffer_isvalid(lua_State *L)
1304{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001305 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001306 luaV_getudata(L, *b);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001307 lua_pushboolean(L, !lua_isnil(L, -1));
1308 return 1;
1309}
1310
1311static const luaL_Reg luaV_Buffer_mt[] = {
1312 {"__tostring", luaV_buffer_tostring},
1313 {"__len", luaV_buffer_len},
1314 {"__call", luaV_buffer_call},
1315 {"__index", luaV_buffer_index},
1316 {"__newindex", luaV_buffer_newindex},
1317 {"insert", luaV_buffer_insert},
1318 {"next", luaV_buffer_next},
1319 {"previous", luaV_buffer_previous},
1320 {"isvalid", luaV_buffer_isvalid},
1321 {NULL, NULL}
1322};
1323
1324
1325/* ======= Window type ======= */
1326
Bram Moolenaar1dced572012-04-05 16:54:08 +02001327luaV_newtype(win_T, window, luaV_Window, LUAVIM_WINDOW)
1328luaV_pushtype(win_T, window, luaV_Window)
1329luaV_type_tostring(window, LUAVIM_WINDOW)
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001330
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001331 static int
1332luaV_window_call(lua_State *L)
1333{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001334 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001335 lua_settop(L, 1);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001336 win_goto(w);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001337 return 1;
1338}
1339
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001340 static int
1341luaV_window_index(lua_State *L)
1342{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001343 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001344 const char *s = luaL_checkstring(L, 2);
1345 if (strncmp(s, "buffer", 6) == 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001346 luaV_pushbuffer(L, w->w_buffer);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001347 else if (strncmp(s, "line", 4) == 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001348 lua_pushinteger(L, w->w_cursor.lnum);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001349 else if (strncmp(s, "col", 3) == 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001350 lua_pushinteger(L, w->w_cursor.col + 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001351 else if (strncmp(s, "width", 5) == 0)
Bram Moolenaar02631462017-09-22 15:20:32 +02001352 lua_pushinteger(L, w->w_width);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001353 else if (strncmp(s, "height", 6) == 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001354 lua_pushinteger(L, w->w_height);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001355 /* methods */
1356 else if (strncmp(s, "next", 4) == 0
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001357 || strncmp(s, "previous", 8) == 0
1358 || strncmp(s, "isvalid", 7) == 0)
1359 {
1360 lua_getmetatable(L, 1);
1361 lua_getfield(L, -1, s);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001362 }
1363 else
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001364 lua_pushnil(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001365 return 1;
1366}
1367
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001368 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001369luaV_window_newindex(lua_State *L)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001370{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001371 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001372 const char *s = luaL_checkstring(L, 2);
1373 int v = luaL_checkinteger(L, 3);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001374 if (strncmp(s, "line", 4) == 0)
1375 {
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001376#ifdef HAVE_SANDBOX
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001377 luaV_checksandbox(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001378#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +02001379 if (v < 1 || v > w->w_buffer->b_ml.ml_line_count)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001380 luaL_error(L, "line out of range");
Bram Moolenaar1dced572012-04-05 16:54:08 +02001381 w->w_cursor.lnum = v;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001382 update_screen(VALID);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001383 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001384 else if (strncmp(s, "col", 3) == 0)
1385 {
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001386#ifdef HAVE_SANDBOX
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001387 luaV_checksandbox(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001388#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +02001389 w->w_cursor.col = v - 1;
Bram Moolenaar53901442018-07-25 22:02:36 +02001390 w->w_set_curswant = TRUE;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001391 update_screen(VALID);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001392 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001393 else if (strncmp(s, "width", 5) == 0)
1394 {
1395 win_T *win = curwin;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001396#ifdef FEAT_GUI
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001397 need_mouse_correct = TRUE;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001398#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +02001399 curwin = w;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001400 win_setwidth(v);
1401 curwin = win;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001402 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001403 else if (strncmp(s, "height", 6) == 0)
1404 {
1405 win_T *win = curwin;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001406#ifdef FEAT_GUI
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001407 need_mouse_correct = TRUE;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001408#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +02001409 curwin = w;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001410 win_setheight(v);
1411 curwin = win;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001412 }
1413 else
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001414 luaL_error(L, "invalid window property: `%s'", s);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001415 return 0;
1416}
1417
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001418 static int
1419luaV_window_next(lua_State *L)
1420{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001421 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001422 win_T *win = (win_T *) luaV_checkcache(L, (void *) *w);
1423 luaV_pushwindow(L, win->w_next);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001424 return 1;
1425}
1426
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001427 static int
1428luaV_window_previous(lua_State *L)
1429{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001430 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001431 win_T *win = (win_T *) luaV_checkcache(L, (void *) *w);
1432 luaV_pushwindow(L, win->w_prev);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001433 return 1;
1434}
1435
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001436 static int
1437luaV_window_isvalid(lua_State *L)
1438{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001439 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001440 luaV_getudata(L, *w);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001441 lua_pushboolean(L, !lua_isnil(L, -1));
1442 return 1;
1443}
1444
1445static const luaL_Reg luaV_Window_mt[] = {
1446 {"__tostring", luaV_window_tostring},
1447 {"__call", luaV_window_call},
1448 {"__index", luaV_window_index},
1449 {"__newindex", luaV_window_newindex},
1450 {"next", luaV_window_next},
1451 {"previous", luaV_window_previous},
1452 {"isvalid", luaV_window_isvalid},
1453 {NULL, NULL}
1454};
1455
1456
1457/* ======= Vim module ======= */
1458
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001459 static int
1460luaV_print(lua_State *L)
1461{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001462 int i, n = lua_gettop(L); /* nargs */
1463 const char *s;
1464 size_t l;
1465 luaL_Buffer b;
1466 luaL_buffinit(L, &b);
1467 lua_getglobal(L, "tostring");
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001468 for (i = 1; i <= n; i++)
1469 {
1470 lua_pushvalue(L, -1); /* tostring */
1471 lua_pushvalue(L, i); /* arg */
1472 lua_call(L, 1, 1);
1473 s = lua_tolstring(L, -1, &l);
1474 if (s == NULL)
1475 return luaL_error(L, "cannot convert to string");
1476 if (i > 1) luaL_addchar(&b, ' '); /* use space instead of tab */
1477 luaV_addlstring(&b, s, l, 0);
1478 lua_pop(L, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001479 }
1480 luaL_pushresult(&b);
1481 luaV_msg(L);
1482 return 0;
1483}
1484
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001485 static int
Bram Moolenaar38e2b062011-09-21 17:15:39 +02001486luaV_debug(lua_State *L)
1487{
1488 lua_settop(L, 0);
1489 lua_getglobal(L, "vim");
1490 lua_getfield(L, -1, "eval");
1491 lua_remove(L, -2); /* vim.eval at position 1 */
1492 for (;;)
1493 {
1494 const char *input;
1495 size_t l;
1496 lua_pushvalue(L, 1); /* vim.eval */
1497 lua_pushliteral(L, "input('lua_debug> ')");
1498 lua_call(L, 1, 1); /* return string */
1499 input = lua_tolstring(L, -1, &l);
1500 if (l == 0 || strcmp(input, "cont") == 0)
1501 return 0;
1502 msg_putchar('\n'); /* avoid outputting on input line */
1503 if (luaL_loadbuffer(L, input, l, "=(debug command)")
1504 || lua_pcall(L, 0, 0, 0))
1505 luaV_emsg(L);
1506 lua_settop(L, 1); /* remove eventual returns, but keep vim.eval */
1507 }
1508}
1509
1510 static int
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001511luaV_command(lua_State *L)
1512{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001513 do_cmdline_cmd((char_u *) luaL_checkstring(L, 1));
1514 update_screen(VALID);
1515 return 0;
1516}
1517
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001518 static int
1519luaV_eval(lua_State *L)
1520{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001521 typval_T *tv = eval_expr((char_u *) luaL_checkstring(L, 1), NULL);
1522 if (tv == NULL) luaL_error(L, "invalid expression");
1523 luaV_pushtypval(L, tv);
Bram Moolenaarb3766472013-04-15 13:49:21 +02001524 free_tv(tv);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001525 return 1;
1526}
1527
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001528 static int
Bram Moolenaar0d2e4fc2010-07-18 12:35:47 +02001529luaV_beep(lua_State *L UNUSED)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001530{
Bram Moolenaar165bc692015-07-21 17:53:25 +02001531 vim_beep(BO_LANG);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001532 return 0;
1533}
1534
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001535 static int
1536luaV_line(lua_State *L)
1537{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001538 luaV_pushline(L, curbuf, curwin->w_cursor.lnum);
1539 return 1;
1540}
1541
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001542 static int
Bram Moolenaar1dced572012-04-05 16:54:08 +02001543luaV_list(lua_State *L)
1544{
Bram Moolenaarca06da92018-07-01 15:12:05 +02001545 list_T *l;
1546 int initarg = !lua_isnoneornil(L, 1);
1547
1548 if (initarg && lua_type(L, 1) != LUA_TTABLE)
1549 luaL_error(L, "table expected, got %s", luaL_typename(L, 1));
1550 l = list_alloc();
Bram Moolenaar1dced572012-04-05 16:54:08 +02001551 if (l == NULL)
1552 lua_pushnil(L);
1553 else
Bram Moolenaarca06da92018-07-01 15:12:05 +02001554 {
Bram Moolenaar1dced572012-04-05 16:54:08 +02001555 luaV_newlist(L, l);
Bram Moolenaar17413672018-07-14 20:49:42 +02001556 if (initarg) /* traverse table to init list */
1557 {
Bram Moolenaarca06da92018-07-01 15:12:05 +02001558 int notnil, i = 0;
1559 typval_T v;
Bram Moolenaar17413672018-07-14 20:49:42 +02001560 do
1561 {
Bram Moolenaarca06da92018-07-01 15:12:05 +02001562 lua_rawgeti(L, 1, ++i);
1563 notnil = !lua_isnil(L, -1);
Bram Moolenaar17413672018-07-14 20:49:42 +02001564 if (notnil)
1565 {
Bram Moolenaarca06da92018-07-01 15:12:05 +02001566 luaV_checktypval(L, -1, &v, "vim.list");
1567 list_append_tv(l, &v);
Bram Moolenaar713bf9e92019-03-16 16:38:41 +01001568 clear_tv(&v);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001569 }
1570 lua_pop(L, 1); /* value */
1571 } while (notnil);
1572 }
1573 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02001574 return 1;
1575}
1576
1577 static int
1578luaV_dict(lua_State *L)
1579{
Bram Moolenaarca06da92018-07-01 15:12:05 +02001580 dict_T *d;
1581 int initarg = !lua_isnoneornil(L, 1);
1582
1583 if (initarg && lua_type(L, 1) != LUA_TTABLE)
1584 luaL_error(L, "table expected, got %s", luaL_typename(L, 1));
1585 d = dict_alloc();
Bram Moolenaar1dced572012-04-05 16:54:08 +02001586 if (d == NULL)
1587 lua_pushnil(L);
1588 else
Bram Moolenaarca06da92018-07-01 15:12:05 +02001589 {
Bram Moolenaar1dced572012-04-05 16:54:08 +02001590 luaV_newdict(L, d);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001591 if (initarg) /* traverse table to init dict */
1592 {
1593 lua_pushnil(L);
1594 while (lua_next(L, 1))
1595 {
1596 char_u *key;
1597 dictitem_T *di;
1598 typval_T v;
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001599
Bram Moolenaarca06da92018-07-01 15:12:05 +02001600 lua_pushvalue(L, -2); /* dup key in case it's a number */
1601 key = (char_u *) lua_tostring(L, -1);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001602 if (key == NULL)
1603 {
1604 lua_pushnil(L);
1605 return 1;
1606 }
1607 if (*key == NUL)
Bram Moolenaarca06da92018-07-01 15:12:05 +02001608 luaL_error(L, "table has empty key");
1609 luaV_checktypval(L, -2, &v, "vim.dict"); /* value */
1610 di = dictitem_alloc(key);
Bram Moolenaard6ef5f92018-07-13 22:08:23 +02001611 if (di == NULL || dict_add(d, di) == FAIL)
1612 {
Bram Moolenaarca06da92018-07-01 15:12:05 +02001613 vim_free(di);
1614 lua_pushnil(L);
1615 return 1;
1616 }
1617 copy_tv(&v, &di->di_tv);
1618 clear_tv(&v);
1619 lua_pop(L, 2); /* key copy and value */
1620 }
1621 }
1622 }
1623 return 1;
1624}
1625
1626 static int
1627luaV_funcref(lua_State *L)
1628{
1629 const char *name = luaL_checkstring(L, 1);
1630 /* note: not checking if function exists (needs function_exists) */
1631 if (name == NULL || *name == NUL || VIM_ISDIGIT(*name))
1632 luaL_error(L, "invalid function name: %s", name);
1633 luaV_newfuncref(L, (char_u *) name);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001634 return 1;
1635}
1636
1637 static int
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001638luaV_buffer(lua_State *L)
1639{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001640 buf_T *buf;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001641 if (lua_isstring(L, 1)) /* get by number or name? */
1642 {
1643 if (lua_isnumber(L, 1)) /* by number? */
1644 {
1645 int n = lua_tointeger(L, 1);
Bram Moolenaar29323592016-07-24 22:04:11 +02001646 FOR_ALL_BUFFERS(buf)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001647 if (buf->b_fnum == n) break;
1648 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02001649 else // by name
1650 {
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001651 size_t l;
1652 const char *s = lua_tolstring(L, 1, &l);
Bram Moolenaar29323592016-07-24 22:04:11 +02001653 FOR_ALL_BUFFERS(buf)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001654 {
1655 if (buf->b_ffname == NULL || buf->b_sfname == NULL)
1656 {
1657 if (l == 0) break;
1658 }
Bram Moolenaar0d2e4fc2010-07-18 12:35:47 +02001659 else if (strncmp(s, (char *)buf->b_ffname, l) == 0
1660 || strncmp(s, (char *)buf->b_sfname, l) == 0)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001661 break;
1662 }
1663 }
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001664 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02001665 else
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001666 buf = (lua_toboolean(L, 1)) ? firstbuf : curbuf; /* first buffer? */
Bram Moolenaar1dced572012-04-05 16:54:08 +02001667 luaV_pushbuffer(L, buf);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001668 return 1;
1669}
1670
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001671 static int
1672luaV_window(lua_State *L)
1673{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001674 win_T *win;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001675 if (lua_isnumber(L, 1)) /* get by number? */
1676 {
1677 int n = lua_tointeger(L, 1);
1678 for (win = firstwin; win != NULL; win = win->w_next, n--)
1679 if (n == 1) break;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001680 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02001681 else
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001682 win = (lua_toboolean(L, 1)) ? firstwin : curwin; /* first window? */
Bram Moolenaar1dced572012-04-05 16:54:08 +02001683 luaV_pushwindow(L, win);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001684 return 1;
1685}
1686
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001687 static int
1688luaV_open(lua_State *L)
1689{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001690 char_u *s = NULL;
1691#ifdef HAVE_SANDBOX
1692 luaV_checksandbox(L);
1693#endif
1694 if (lua_isstring(L, 1)) s = (char_u *) lua_tostring(L, 1);
Bram Moolenaarfa263a52011-12-08 16:00:16 +01001695 luaV_pushbuffer(L, buflist_new(s, NULL, 1L, BLN_LISTED));
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001696 return 1;
1697}
1698
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001699 static int
Bram Moolenaar1dced572012-04-05 16:54:08 +02001700luaV_type(lua_State *L)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001701{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001702 luaL_checkany(L, 1);
1703 if (lua_type(L, 1) == LUA_TUSERDATA) /* check vim udata? */
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001704 {
Bram Moolenaar1dced572012-04-05 16:54:08 +02001705 lua_settop(L, 1);
1706 if (lua_getmetatable(L, 1))
1707 {
1708 luaV_getfield(L, LUAVIM_LIST);
1709 if (lua_rawequal(L, -1, 2))
1710 {
1711 lua_pushstring(L, "list");
1712 return 1;
1713 }
1714 luaV_getfield(L, LUAVIM_DICT);
1715 if (lua_rawequal(L, -1, 2))
1716 {
1717 lua_pushstring(L, "dict");
1718 return 1;
1719 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02001720 luaV_getfield(L, LUAVIM_FUNCREF);
1721 if (lua_rawequal(L, -1, 2))
1722 {
1723 lua_pushstring(L, "funcref");
1724 return 1;
1725 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02001726 luaV_getfield(L, LUAVIM_BUFFER);
1727 if (lua_rawequal(L, -1, 2))
1728 {
1729 lua_pushstring(L, "buffer");
1730 return 1;
1731 }
1732 luaV_getfield(L, LUAVIM_WINDOW);
1733 if (lua_rawequal(L, -1, 2))
1734 {
1735 lua_pushstring(L, "window");
1736 return 1;
1737 }
1738 }
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001739 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02001740 lua_pushstring(L, luaL_typename(L, 1)); /* fallback */
1741 return 1;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001742}
1743
1744static const luaL_Reg luaV_module[] = {
1745 {"command", luaV_command},
1746 {"eval", luaV_eval},
1747 {"beep", luaV_beep},
1748 {"line", luaV_line},
Bram Moolenaar1dced572012-04-05 16:54:08 +02001749 {"list", luaV_list},
1750 {"dict", luaV_dict},
Bram Moolenaarca06da92018-07-01 15:12:05 +02001751 {"funcref", luaV_funcref},
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001752 {"buffer", luaV_buffer},
1753 {"window", luaV_window},
1754 {"open", luaV_open},
Bram Moolenaar1dced572012-04-05 16:54:08 +02001755 {"type", luaV_type},
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001756 {NULL, NULL}
1757};
1758
Bram Moolenaar1dced572012-04-05 16:54:08 +02001759/* for freeing list, dict, buffer and window objects; lightuserdata as arg */
1760 static int
1761luaV_free(lua_State *L)
1762{
1763 lua_pushnil(L);
1764 luaV_setudata(L, lua_touserdata(L, 1));
1765 return 0;
1766}
1767
1768 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001769luaV_luaeval(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001770{
1771 luaL_Buffer b;
1772 size_t l;
1773 const char *str = lua_tolstring(L, 1, &l);
1774 typval_T *arg = (typval_T *) lua_touserdata(L, 2);
1775 typval_T *rettv = (typval_T *) lua_touserdata(L, 3);
1776 luaL_buffinit(L, &b);
1777 luaL_addlstring(&b, LUAVIM_EVALHEADER, sizeof(LUAVIM_EVALHEADER) - 1);
1778 luaL_addlstring(&b, str, l);
1779 luaL_pushresult(&b);
1780 str = lua_tolstring(L, -1, &l);
1781 if (luaL_loadbuffer(L, str, l, LUAVIM_EVALNAME)) /* compile error? */
1782 {
1783 luaV_emsg(L);
1784 return 0;
1785 }
1786 luaV_pushtypval(L, arg);
1787 if (lua_pcall(L, 1, 1, 0)) /* running error? */
1788 {
1789 luaV_emsg(L);
1790 return 0;
1791 }
Bram Moolenaarca06da92018-07-01 15:12:05 +02001792 if (luaV_totypval(L, -1, rettv) == FAIL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001793 emsg("luaeval: cannot convert value");
Bram Moolenaarf554a322015-02-04 23:08:01 +01001794 return 0;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001795}
1796
1797 static int
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001798luaV_setref(lua_State *L)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001799{
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001800 int copyID = lua_tointeger(L, 1);
1801 int abort = FALSE;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01001802
Bram Moolenaar1dced572012-04-05 16:54:08 +02001803 luaV_getfield(L, LUAVIM_LIST);
1804 luaV_getfield(L, LUAVIM_DICT);
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001805 luaV_getfield(L, LUAVIM_FUNCREF);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001806 lua_pushnil(L);
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001807 // traverse cache table
Bram Moolenaarb84634d2015-02-04 22:02:37 +01001808 while (!abort && lua_next(L, lua_upvalueindex(1)) != 0)
Bram Moolenaar1dced572012-04-05 16:54:08 +02001809 {
1810 lua_getmetatable(L, -1);
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001811 if (lua_rawequal(L, -1, 2)) // list?
Bram Moolenaar1dced572012-04-05 16:54:08 +02001812 {
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001813 list_T *l = (list_T *)lua_touserdata(L, 5); // key
1814
1815 if (l->lv_copyID != copyID)
1816 {
1817 l->lv_copyID = copyID;
1818 abort = set_ref_in_list(l, copyID, NULL);
1819 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02001820 }
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001821 else if (lua_rawequal(L, -1, 3)) // dict?
Bram Moolenaar1dced572012-04-05 16:54:08 +02001822 {
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001823 dict_T *d = (dict_T *)lua_touserdata(L, 5); // key
1824
1825 if (d->dv_copyID != copyID)
1826 {
1827 d->dv_copyID = copyID;
1828 abort = set_ref_in_ht(&d->dv_hashtab, copyID, NULL);
1829 }
Bram Moolenaar1dced572012-04-05 16:54:08 +02001830 }
Bram Moolenaar4eefe472019-03-19 21:59:19 +01001831 else if (lua_rawequal(L, -1, 4)) // funcref?
1832 {
1833 luaV_Funcref *f = (luaV_Funcref *)lua_touserdata(L, 5); // key
1834
1835 if (f->self != NULL && f->self->dv_copyID != copyID)
1836 {
1837 f->self->dv_copyID = copyID;
1838 abort = set_ref_in_ht(&f->self->dv_hashtab, copyID, NULL);
1839 }
1840 }
1841 lua_pop(L, 2); // metatable and value
Bram Moolenaar1dced572012-04-05 16:54:08 +02001842 }
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01001843 lua_pushinteger(L, abort);
Bram Moolenaarf554a322015-02-04 23:08:01 +01001844 return 1;
Bram Moolenaar1dced572012-04-05 16:54:08 +02001845}
1846
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001847 static int
1848luaopen_vim(lua_State *L)
1849{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001850 /* set cache table */
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001851 lua_newtable(L);
1852 lua_newtable(L);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001853 lua_pushstring(L, "v");
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001854 lua_setfield(L, -2, "__mode");
Bram Moolenaar1dced572012-04-05 16:54:08 +02001855 lua_setmetatable(L, -2); /* cache is weak-valued */
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001856 /* print */
1857 lua_pushcfunction(L, luaV_print);
1858 lua_setglobal(L, "print");
Bram Moolenaar38e2b062011-09-21 17:15:39 +02001859 /* debug.debug */
1860 lua_getglobal(L, "debug");
1861 lua_pushcfunction(L, luaV_debug);
1862 lua_setfield(L, -2, "debug");
1863 lua_pop(L, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001864 /* free */
1865 lua_pushlightuserdata(L, (void *) LUAVIM_FREE);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001866 lua_pushvalue(L, 1); /* cache table */
1867 lua_pushcclosure(L, luaV_free, 1);
1868 lua_rawset(L, LUA_REGISTRYINDEX);
1869 /* luaeval */
1870 lua_pushlightuserdata(L, (void *) LUAVIM_LUAEVAL);
1871 lua_pushvalue(L, 1); /* cache table */
1872 lua_pushcclosure(L, luaV_luaeval, 1);
1873 lua_rawset(L, LUA_REGISTRYINDEX);
1874 /* setref */
1875 lua_pushlightuserdata(L, (void *) LUAVIM_SETREF);
1876 lua_pushvalue(L, 1); /* cache table */
1877 lua_pushcclosure(L, luaV_setref, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001878 lua_rawset(L, LUA_REGISTRYINDEX);
1879 /* register */
Bram Moolenaar1dced572012-04-05 16:54:08 +02001880 luaV_newmetatable(L, LUAVIM_LIST);
1881 lua_pushvalue(L, 1);
1882 luaV_openlib(L, luaV_List_mt, 1);
1883 luaV_newmetatable(L, LUAVIM_DICT);
1884 lua_pushvalue(L, 1);
1885 luaV_openlib(L, luaV_Dict_mt, 1);
Bram Moolenaarca06da92018-07-01 15:12:05 +02001886 luaV_newmetatable(L, LUAVIM_FUNCREF);
1887 lua_pushvalue(L, 1);
1888 luaV_openlib(L, luaV_Funcref_mt, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001889 luaV_newmetatable(L, LUAVIM_BUFFER);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001890 lua_pushvalue(L, 1); /* cache table */
1891 luaV_openlib(L, luaV_Buffer_mt, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001892 luaV_newmetatable(L, LUAVIM_WINDOW);
Bram Moolenaar1dced572012-04-05 16:54:08 +02001893 lua_pushvalue(L, 1); /* cache table */
1894 luaV_openlib(L, luaV_Window_mt, 1);
1895 lua_newtable(L); /* vim table */
1896 lua_pushvalue(L, 1); /* cache table */
1897 luaV_openlib(L, luaV_module, 1);
1898 lua_setglobal(L, LUAVIM_NAME);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001899 return 0;
1900}
1901
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001902 static lua_State *
1903luaV_newstate(void)
1904{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001905 lua_State *L = luaL_newstate();
Bram Moolenaar16c98f92010-07-28 22:46:08 +02001906 luaL_openlibs(L); /* core libs */
1907 lua_pushcfunction(L, luaopen_vim); /* vim */
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001908 lua_call(L, 0, 0);
1909 return L;
1910}
1911
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001912 static void
1913luaV_setrange(lua_State *L, int line1, int line2)
1914{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001915 lua_getglobal(L, LUAVIM_NAME);
1916 lua_pushinteger(L, line1);
1917 lua_setfield(L, -2, "firstline");
1918 lua_pushinteger(L, line2);
1919 lua_setfield(L, -2, "lastline");
1920 lua_pop(L, 1); /* vim table */
1921}
1922
1923
1924/* ======= Interface ======= */
1925
1926static lua_State *L = NULL;
1927
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001928 static int
Bram Moolenaar1dced572012-04-05 16:54:08 +02001929lua_isopen(void)
Bram Moolenaar2bd6a1b2010-08-12 22:14:01 +02001930{
1931 return L != NULL;
1932}
1933
1934 static int
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001935lua_init(void)
1936{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001937 if (!lua_isopen())
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001938 {
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001939#ifdef DYNAMIC_LUA
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001940 if (!lua_enabled(TRUE))
1941 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001942 emsg(_("Lua library cannot be loaded."));
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001943 return FAIL;
1944 }
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001945#endif
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001946 L = luaV_newstate();
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001947 }
1948 return OK;
1949}
1950
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001951 void
1952lua_end(void)
1953{
Bram Moolenaar1dced572012-04-05 16:54:08 +02001954 if (lua_isopen())
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001955 {
1956 lua_close(L);
1957 L = NULL;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001958#ifdef DYNAMIC_LUA
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001959 end_dynamic_lua();
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001960#endif
1961 }
1962}
1963
1964/* ex commands */
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001965 void
1966ex_lua(exarg_T *eap)
1967{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001968 char *script;
1969 if (lua_init() == FAIL) return;
1970 script = (char *) script_get(eap, eap->arg);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001971 if (!eap->skip)
1972 {
1973 char *s = (script) ? script : (char *) eap->arg;
1974 luaV_setrange(L, eap->line1, eap->line2);
1975 if (luaL_loadbuffer(L, s, strlen(s), LUAVIM_CHUNKNAME)
1976 || lua_pcall(L, 0, 0, 0))
1977 luaV_emsg(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001978 }
1979 if (script != NULL) vim_free(script);
1980}
1981
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001982 void
1983ex_luado(exarg_T *eap)
1984{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001985 linenr_T l;
1986 const char *s = (const char *) eap->arg;
1987 luaL_Buffer b;
1988 size_t len;
Bram Moolenaard58f03b2017-01-29 22:48:45 +01001989 buf_T *was_curbuf = curbuf;
1990
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001991 if (lua_init() == FAIL) return;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001992 if (u_save(eap->line1 - 1, eap->line2 + 1) == FAIL)
1993 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001994 emsg(_("cannot save undo information"));
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001995 return;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001996 }
1997 luaV_setrange(L, eap->line1, eap->line2);
1998 luaL_buffinit(L, &b);
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +02001999 luaL_addlstring(&b, "return function(line, linenr) ", 30); /* header */
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002000 luaL_addlstring(&b, s, strlen(s));
2001 luaL_addlstring(&b, " end", 4); /* footer */
2002 luaL_pushresult(&b);
2003 s = lua_tolstring(L, -1, &len);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002004 if (luaL_loadbuffer(L, s, len, LUAVIM_CHUNKNAME))
2005 {
2006 luaV_emsg(L);
2007 lua_pop(L, 1); /* function body */
2008 return;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002009 }
2010 lua_call(L, 0, 1);
2011 lua_replace(L, -2); /* function -> body */
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002012 for (l = eap->line1; l <= eap->line2; l++)
2013 {
Bram Moolenaard58f03b2017-01-29 22:48:45 +01002014 /* Check the line number, the command my have deleted lines. */
2015 if (l > curbuf->b_ml.ml_line_count)
2016 break;
2017
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002018 lua_pushvalue(L, -1); /* function */
2019 luaV_pushline(L, curbuf, l); /* current line as arg */
Bram Moolenaarbd2f3c32012-04-06 14:31:00 +02002020 lua_pushinteger(L, l); /* current line number as arg */
2021 if (lua_pcall(L, 2, 1, 0))
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002022 {
2023 luaV_emsg(L);
2024 break;
2025 }
Bram Moolenaard58f03b2017-01-29 22:48:45 +01002026 /* Catch the command switching to another buffer. */
2027 if (curbuf != was_curbuf)
2028 break;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002029 if (lua_isstring(L, -1)) /* update line? */
2030 {
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002031#ifdef HAVE_SANDBOX
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002032 luaV_checksandbox(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002033#endif
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002034 ml_replace(l, luaV_toline(L, -1), TRUE);
2035 changed_bytes(l, 0);
2036 lua_pop(L, 1); /* result from luaV_toline */
2037 }
2038 lua_pop(L, 1); /* line */
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002039 }
2040 lua_pop(L, 1); /* function */
2041 check_cursor();
2042 update_screen(NOT_VALID);
2043}
2044
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002045 void
2046ex_luafile(exarg_T *eap)
2047{
2048 if (lua_init() == FAIL)
2049 return;
2050 if (!eap->skip)
2051 {
2052 luaV_setrange(L, eap->line1, eap->line2);
2053 if (luaL_loadfile(L, (char *) eap->arg) || lua_pcall(L, 0, 0, 0))
2054 luaV_emsg(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002055 }
2056}
2057
Bram Moolenaar1dced572012-04-05 16:54:08 +02002058#define luaV_freetype(typ,tname) \
2059 void \
2060 lua_##tname##_free(typ *o) \
2061 { \
2062 if (!lua_isopen()) return; \
2063 luaV_getfield(L, LUAVIM_FREE); \
2064 lua_pushlightuserdata(L, (void *) o); \
2065 lua_call(L, 1, 0); \
2066 }
2067
2068luaV_freetype(buf_T, buffer)
2069luaV_freetype(win_T, window)
2070
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002071 void
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002072do_luaeval(char_u *str, typval_T *arg, typval_T *rettv)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002073{
Bram Moolenaar1dced572012-04-05 16:54:08 +02002074 lua_init();
2075 luaV_getfield(L, LUAVIM_LUAEVAL);
2076 lua_pushstring(L, (char *) str);
2077 lua_pushlightuserdata(L, (void *) arg);
2078 lua_pushlightuserdata(L, (void *) rettv);
2079 lua_call(L, 3, 0);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002080}
2081
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01002082 int
Bram Moolenaar4eefe472019-03-19 21:59:19 +01002083set_ref_in_lua(int copyID)
Bram Moolenaar55d5c032010-07-17 23:52:29 +02002084{
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01002085 int aborted = 0;
2086
2087 if (lua_isopen())
2088 {
2089 luaV_getfield(L, LUAVIM_SETREF);
2090 /* call the function with 1 arg, getting 1 result back */
2091 lua_pushinteger(L, copyID);
2092 lua_call(L, 1, 1);
2093 /* get the result */
2094 aborted = lua_tointeger(L, -1);
2095 /* pop result off the stack */
2096 lua_pop(L, 1);
2097 }
2098 return aborted;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02002099}
2100
2101#endif