blob: d3c6a4220112423b7cb904f79c78d25ef45b5211 [file] [log] [blame]
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001/* vi:set ts=8 sts=4 sw=4:
2 *
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"
24
25typedef buf_T *luaV_Buffer;
26typedef win_T *luaV_Window;
27typedef void (*msgfunc_T)(char_u *);
28
29static const char LUAVIM_BUFFER[] = "buffer";
30static const char LUAVIM_WINDOW[] = "window";
31static const char LUAVIM_FREE[] = "luaV_free";
32
33#define luaV_getfield(L, s) \
34 lua_pushlightuserdata((L), (void *)(s)); \
35 lua_rawget((L), LUA_REGISTRYINDEX)
36#define luaV_checksandbox(L) \
37 if (sandbox) luaL_error((L), "not allowed in sandbox")
38#define luaV_msg(L) luaV_msgfunc((L), (msgfunc_T) msg)
39#define luaV_emsg(L) luaV_msgfunc((L), (msgfunc_T) emsg)
40
41
42#ifdef DYNAMIC_LUA
Bram Moolenaar2334b6d2010-07-22 21:32:16 +020043
44#ifndef WIN3264
45# include <dlfcn.h>
46# define HANDLE void*
47# define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL)
48# define symbol_from_dll dlsym
49# define close_dll dlclose
50#else
Bram Moolenaarebbcb822010-10-23 14:02:54 +020051# define load_dll vimLoadLib
Bram Moolenaar2334b6d2010-07-22 21:32:16 +020052# define symbol_from_dll GetProcAddress
53# define close_dll FreeLibrary
54#endif
55
Bram Moolenaar0ba04292010-07-14 23:23:17 +020056/* lauxlib */
57#define luaL_register dll_luaL_register
58#define luaL_typerror dll_luaL_typerror
59#define luaL_checklstring dll_luaL_checklstring
60#define luaL_checkinteger dll_luaL_checkinteger
61#define luaL_optinteger dll_luaL_optinteger
62#define luaL_checktype dll_luaL_checktype
63#define luaL_error dll_luaL_error
64#define luaL_loadfile dll_luaL_loadfile
65#define luaL_loadbuffer dll_luaL_loadbuffer
66#define luaL_newstate dll_luaL_newstate
67#define luaL_buffinit dll_luaL_buffinit
68#define luaL_prepbuffer dll_luaL_prepbuffer
69#define luaL_addlstring dll_luaL_addlstring
70#define luaL_pushresult dll_luaL_pushresult
71/* lua */
72#define lua_close dll_lua_close
73#define lua_gettop dll_lua_gettop
74#define lua_settop dll_lua_settop
75#define lua_pushvalue dll_lua_pushvalue
76#define lua_replace dll_lua_replace
77#define lua_isnumber dll_lua_isnumber
78#define lua_isstring dll_lua_isstring
79#define lua_type dll_lua_type
80#define lua_rawequal dll_lua_rawequal
81#define lua_tonumber dll_lua_tonumber
82#define lua_tointeger dll_lua_tointeger
83#define lua_toboolean dll_lua_toboolean
84#define lua_tolstring dll_lua_tolstring
85#define lua_touserdata dll_lua_touserdata
86#define lua_pushnil dll_lua_pushnil
87#define lua_pushnumber dll_lua_pushnumber
88#define lua_pushinteger dll_lua_pushinteger
89#define lua_pushlstring dll_lua_pushlstring
90#define lua_pushstring dll_lua_pushstring
91#define lua_pushfstring dll_lua_pushfstring
92#define lua_pushcclosure dll_lua_pushcclosure
93#define lua_pushboolean dll_lua_pushboolean
94#define lua_pushlightuserdata dll_lua_pushlightuserdata
95#define lua_getfield dll_lua_getfield
96#define lua_rawget dll_lua_rawget
97#define lua_createtable dll_lua_createtable
98#define lua_newuserdata dll_lua_newuserdata
99#define lua_getmetatable dll_lua_getmetatable
100#define lua_setfield dll_lua_setfield
101#define lua_rawset dll_lua_rawset
102#define lua_rawseti dll_lua_rawseti
103#define lua_setmetatable dll_lua_setmetatable
104#define lua_call dll_lua_call
105#define lua_pcall dll_lua_pcall
106/* libs */
107#define luaopen_base dll_luaopen_base
108#define luaopen_table dll_luaopen_table
109#define luaopen_string dll_luaopen_string
110#define luaopen_math dll_luaopen_math
Bram Moolenaar16c98f92010-07-28 22:46:08 +0200111#define luaopen_io dll_luaopen_io
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200112#define luaopen_os dll_luaopen_os
113#define luaopen_package dll_luaopen_package
114#define luaopen_debug dll_luaopen_debug
Bram Moolenaar16c98f92010-07-28 22:46:08 +0200115#define luaL_openlibs dll_luaL_openlibs
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200116
117/* lauxlib */
118void (*dll_luaL_register) (lua_State *L, const char *libname, const luaL_Reg *l);
119int (*dll_luaL_typerror) (lua_State *L, int narg, const char *tname);
120const char *(*dll_luaL_checklstring) (lua_State *L, int numArg, size_t *l);
121lua_Integer (*dll_luaL_checkinteger) (lua_State *L, int numArg);
122lua_Integer (*dll_luaL_optinteger) (lua_State *L, int nArg, lua_Integer def);
123void (*dll_luaL_checktype) (lua_State *L, int narg, int t);
124int (*dll_luaL_error) (lua_State *L, const char *fmt, ...);
125int (*dll_luaL_loadfile) (lua_State *L, const char *filename);
126int (*dll_luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, const char *name);
127lua_State *(*dll_luaL_newstate) (void);
128void (*dll_luaL_buffinit) (lua_State *L, luaL_Buffer *B);
129char *(*dll_luaL_prepbuffer) (luaL_Buffer *B);
130void (*dll_luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
131void (*dll_luaL_pushresult) (luaL_Buffer *B);
132/* lua */
133void (*dll_lua_close) (lua_State *L);
134int (*dll_lua_gettop) (lua_State *L);
135void (*dll_lua_settop) (lua_State *L, int idx);
136void (*dll_lua_pushvalue) (lua_State *L, int idx);
137void (*dll_lua_replace) (lua_State *L, int idx);
138int (*dll_lua_isnumber) (lua_State *L, int idx);
139int (*dll_lua_isstring) (lua_State *L, int idx);
140int (*dll_lua_type) (lua_State *L, int idx);
141int (*dll_lua_rawequal) (lua_State *L, int idx1, int idx2);
142lua_Number (*dll_lua_tonumber) (lua_State *L, int idx);
143lua_Integer (*dll_lua_tointeger) (lua_State *L, int idx);
144int (*dll_lua_toboolean) (lua_State *L, int idx);
145const char *(*dll_lua_tolstring) (lua_State *L, int idx, size_t *len);
146void *(*dll_lua_touserdata) (lua_State *L, int idx);
147void (*dll_lua_pushnil) (lua_State *L);
148void (*dll_lua_pushnumber) (lua_State *L, lua_Number n);
149void (*dll_lua_pushinteger) (lua_State *L, lua_Integer n);
150void (*dll_lua_pushlstring) (lua_State *L, const char *s, size_t l);
151void (*dll_lua_pushstring) (lua_State *L, const char *s);
152const char *(*dll_lua_pushfstring) (lua_State *L, const char *fmt, ...);
153void (*dll_lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
154void (*dll_lua_pushboolean) (lua_State *L, int b);
155void (*dll_lua_pushlightuserdata) (lua_State *L, void *p);
156void (*dll_lua_getfield) (lua_State *L, int idx, const char *k);
157void (*dll_lua_rawget) (lua_State *L, int idx);
158void (*dll_lua_createtable) (lua_State *L, int narr, int nrec);
159void *(*dll_lua_newuserdata) (lua_State *L, size_t sz);
160int (*dll_lua_getmetatable) (lua_State *L, int objindex);
161void (*dll_lua_setfield) (lua_State *L, int idx, const char *k);
162void (*dll_lua_rawset) (lua_State *L, int idx);
163void (*dll_lua_rawseti) (lua_State *L, int idx, int n);
164int (*dll_lua_setmetatable) (lua_State *L, int objindex);
165void (*dll_lua_call) (lua_State *L, int nargs, int nresults);
166int (*dll_lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
167/* libs */
168int (*dll_luaopen_base) (lua_State *L);
169int (*dll_luaopen_table) (lua_State *L);
170int (*dll_luaopen_string) (lua_State *L);
171int (*dll_luaopen_math) (lua_State *L);
Bram Moolenaar16c98f92010-07-28 22:46:08 +0200172int (*dll_luaopen_io) (lua_State *L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200173int (*dll_luaopen_os) (lua_State *L);
174int (*dll_luaopen_package) (lua_State *L);
175int (*dll_luaopen_debug) (lua_State *L);
Bram Moolenaar16c98f92010-07-28 22:46:08 +0200176void (*dll_luaL_openlibs) (lua_State *L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200177
178typedef void **luaV_function;
179typedef struct {
180 const char *name;
181 luaV_function func;
182} luaV_Reg;
183
184static const luaV_Reg luaV_dll[] = {
185 /* lauxlib */
186 {"luaL_register", (luaV_function) &dll_luaL_register},
187 {"luaL_typerror", (luaV_function) &dll_luaL_typerror},
188 {"luaL_checklstring", (luaV_function) &dll_luaL_checklstring},
189 {"luaL_checkinteger", (luaV_function) &dll_luaL_checkinteger},
190 {"luaL_optinteger", (luaV_function) &dll_luaL_optinteger},
191 {"luaL_checktype", (luaV_function) &dll_luaL_checktype},
192 {"luaL_error", (luaV_function) &dll_luaL_error},
193 {"luaL_loadfile", (luaV_function) &dll_luaL_loadfile},
194 {"luaL_loadbuffer", (luaV_function) &dll_luaL_loadbuffer},
195 {"luaL_newstate", (luaV_function) &dll_luaL_newstate},
196 {"luaL_buffinit", (luaV_function) &dll_luaL_buffinit},
197 {"luaL_prepbuffer", (luaV_function) &dll_luaL_prepbuffer},
198 {"luaL_addlstring", (luaV_function) &dll_luaL_addlstring},
199 {"luaL_pushresult", (luaV_function) &dll_luaL_pushresult},
200 /* lua */
201 {"lua_close", (luaV_function) &dll_lua_close},
202 {"lua_gettop", (luaV_function) &dll_lua_gettop},
203 {"lua_settop", (luaV_function) &dll_lua_settop},
204 {"lua_pushvalue", (luaV_function) &dll_lua_pushvalue},
205 {"lua_replace", (luaV_function) &dll_lua_replace},
206 {"lua_isnumber", (luaV_function) &dll_lua_isnumber},
207 {"lua_isstring", (luaV_function) &dll_lua_isstring},
208 {"lua_type", (luaV_function) &dll_lua_type},
209 {"lua_rawequal", (luaV_function) &dll_lua_rawequal},
210 {"lua_tonumber", (luaV_function) &dll_lua_tonumber},
211 {"lua_tointeger", (luaV_function) &dll_lua_tointeger},
212 {"lua_toboolean", (luaV_function) &dll_lua_toboolean},
213 {"lua_tolstring", (luaV_function) &dll_lua_tolstring},
214 {"lua_touserdata", (luaV_function) &dll_lua_touserdata},
215 {"lua_pushnil", (luaV_function) &dll_lua_pushnil},
216 {"lua_pushnumber", (luaV_function) &dll_lua_pushnumber},
217 {"lua_pushinteger", (luaV_function) &dll_lua_pushinteger},
218 {"lua_pushlstring", (luaV_function) &dll_lua_pushlstring},
219 {"lua_pushstring", (luaV_function) &dll_lua_pushstring},
220 {"lua_pushfstring", (luaV_function) &dll_lua_pushfstring},
221 {"lua_pushcclosure", (luaV_function) &dll_lua_pushcclosure},
222 {"lua_pushboolean", (luaV_function) &dll_lua_pushboolean},
223 {"lua_pushlightuserdata", (luaV_function) &dll_lua_pushlightuserdata},
224 {"lua_getfield", (luaV_function) &dll_lua_getfield},
225 {"lua_rawget", (luaV_function) &dll_lua_rawget},
226 {"lua_createtable", (luaV_function) &dll_lua_createtable},
227 {"lua_newuserdata", (luaV_function) &dll_lua_newuserdata},
228 {"lua_getmetatable", (luaV_function) &dll_lua_getmetatable},
229 {"lua_setfield", (luaV_function) &dll_lua_setfield},
230 {"lua_rawset", (luaV_function) &dll_lua_rawset},
231 {"lua_rawseti", (luaV_function) &dll_lua_rawseti},
232 {"lua_setmetatable", (luaV_function) &dll_lua_setmetatable},
233 {"lua_call", (luaV_function) &dll_lua_call},
234 {"lua_pcall", (luaV_function) &dll_lua_pcall},
235 /* libs */
236 {"luaopen_base", (luaV_function) &dll_luaopen_base},
237 {"luaopen_table", (luaV_function) &dll_luaopen_table},
238 {"luaopen_string", (luaV_function) &dll_luaopen_string},
239 {"luaopen_math", (luaV_function) &dll_luaopen_math},
Bram Moolenaar16c98f92010-07-28 22:46:08 +0200240 {"luaopen_io", (luaV_function) &dll_luaopen_io},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200241 {"luaopen_os", (luaV_function) &dll_luaopen_os},
242 {"luaopen_package", (luaV_function) &dll_luaopen_package},
243 {"luaopen_debug", (luaV_function) &dll_luaopen_debug},
Bram Moolenaar16c98f92010-07-28 22:46:08 +0200244 {"luaL_openlibs", (luaV_function) &dll_luaL_openlibs},
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200245 {NULL, NULL}
246};
247
Bram Moolenaar2334b6d2010-07-22 21:32:16 +0200248static HANDLE hinstLua = NULL;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200249
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200250 static void
251end_dynamic_lua(void)
252{
253 if (hinstLua)
254 {
Bram Moolenaar2334b6d2010-07-22 21:32:16 +0200255 close_dll(hinstLua);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200256 hinstLua = 0;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200257 }
258}
259
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200260 static int
261lua_link_init(char *libname, int verbose)
262{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200263 const luaV_Reg *reg;
264 if (hinstLua) return OK;
Bram Moolenaar2334b6d2010-07-22 21:32:16 +0200265 hinstLua = load_dll(libname);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200266 if (!hinstLua)
267 {
268 if (verbose)
269 EMSG2(_(e_loadlib), libname);
270 return FAIL;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200271 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200272 for (reg = luaV_dll; reg->func; reg++)
273 {
Bram Moolenaar2334b6d2010-07-22 21:32:16 +0200274 if ((*reg->func = symbol_from_dll(hinstLua, reg->name)) == NULL)
275 {
276 close_dll(hinstLua);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200277 hinstLua = 0;
278 if (verbose)
279 EMSG2(_(e_loadfunc), reg->name);
280 return FAIL;
281 }
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200282 }
283 return OK;
284}
285
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200286 int
287lua_enabled(int verbose)
288{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200289 return lua_link_init(DYNAMIC_LUA_DLL, verbose) == OK;
290}
291
292#endif /* DYNAMIC_LUA */
293
294
295/* ======= Internal ======= */
296
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200297 static void
298luaV_newmetatable(lua_State *L, const char *tname)
299{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200300 lua_newtable(L);
301 lua_pushlightuserdata(L, (void *) tname);
302 lua_pushvalue(L, -2);
303 lua_rawset(L, LUA_REGISTRYINDEX);
304}
305
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200306 static void *
307luaV_toudata(lua_State *L, int ud, const char *tname)
308{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200309 void *p = lua_touserdata(L, ud);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200310
311 if (p != NULL) /* value is userdata? */
312 {
313 if (lua_getmetatable(L, ud)) /* does it have a metatable? */
314 {
315 luaV_getfield(L, tname); /* get metatable */
316 if (lua_rawequal(L, -1, -2)) /* MTs match? */
317 {
318 lua_pop(L, 2); /* MTs */
319 return p;
320 }
321 }
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200322 }
323 return NULL;
324}
325
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200326 static void *
327luaV_checkudata(lua_State *L, int ud, const char *tname)
328{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200329 void *p = luaV_toudata(L, ud, tname);
330 if (p == NULL) luaL_typerror(L, ud, tname);
331 return p;
332}
333
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200334 static void
335luaV_pushtypval(lua_State *L, typval_T *tv)
336{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200337 if (tv == NULL) luaL_error(L, "null type");
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200338 switch (tv->v_type)
339 {
340 case VAR_STRING:
341 lua_pushstring(L, (char *) tv->vval.v_string);
342 break;
343 case VAR_NUMBER:
344 lua_pushinteger(L, (int) tv->vval.v_number);
345 break;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200346#ifdef FEAT_FLOAT
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200347 case VAR_FLOAT:
348 lua_pushnumber(L, (lua_Number) tv->vval.v_float);
349 break;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200350#endif
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200351 case VAR_LIST: {
352 list_T *l = tv->vval.v_list;
353
354 if (l != NULL)
355 {
356 /* check cache */
357 lua_pushlightuserdata(L, (void *) l);
358 lua_rawget(L, LUA_ENVIRONINDEX);
359 if (lua_isnil(L, -1)) /* not interned? */
360 {
361 listitem_T *li;
362 int n = 0;
363 lua_pop(L, 1); /* nil */
364 lua_newtable(L);
365 lua_pushlightuserdata(L, (void *) l);
366 lua_pushvalue(L, -2);
367 lua_rawset(L, LUA_ENVIRONINDEX);
368 for (li = l->lv_first; li != NULL; li = li->li_next)
369 {
370 luaV_pushtypval(L, &li->li_tv);
371 lua_rawseti(L, -2, ++n);
372 }
373 }
374 }
375 else lua_pushnil(L);
376 break;
377 }
378 case VAR_DICT: {
379 dict_T *d = tv->vval.v_dict;
380
381 if (d != NULL)
382 {
383 /* check cache */
384 lua_pushlightuserdata(L, (void *) d);
385 lua_rawget(L, LUA_ENVIRONINDEX);
Bram Moolenaar2334b6d2010-07-22 21:32:16 +0200386 if (lua_isnil(L, -1)) /* not interned? */
387 {
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200388 hashtab_T *ht = &d->dv_hashtab;
389 hashitem_T *hi;
390 int n = ht->ht_used; /* remaining items */
391 lua_pop(L, 1); /* nil */
392 lua_newtable(L);
393 lua_pushlightuserdata(L, (void *) d);
394 lua_pushvalue(L, -2);
395 lua_rawset(L, LUA_ENVIRONINDEX);
396 for (hi = ht->ht_array; n > 0; hi++)
397 {
398 if (!HASHITEM_EMPTY(hi))
399 {
400 dictitem_T *di = dict_lookup(hi);
401 luaV_pushtypval(L, &di->di_tv);
402 lua_setfield(L, -2, (char *) hi->hi_key);
403 n--;
404 }
405 }
406 }
407 }
408 else lua_pushnil(L);
409 break;
410 }
411 default:
412 luaL_error(L, "invalid type");
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200413 }
414}
415
416/* similar to luaL_addlstring, but replaces \0 with \n if toline and
417 * \n with \0 otherwise */
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200418 static void
419luaV_addlstring(luaL_Buffer *b, const char *s, size_t l, int toline)
420{
421 while (l--)
422 {
423 if (*s == '\0' && toline)
424 luaL_addchar(b, '\n');
425 else if (*s == '\n' && !toline)
426 luaL_addchar(b, '\0');
427 else
428 luaL_addchar(b, *s);
429 s++;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200430 }
431}
432
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200433 static void
434luaV_pushline(lua_State *L, buf_T *buf, linenr_T n)
435{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200436 const char *s = (const char *) ml_get_buf(buf, n, FALSE);
437 luaL_Buffer b;
438 luaL_buffinit(L, &b);
439 luaV_addlstring(&b, s, strlen(s), 0);
440 luaL_pushresult(&b);
441}
442
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200443 static char_u *
444luaV_toline(lua_State *L, int pos)
445{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200446 size_t l;
447 const char *s = lua_tolstring(L, pos, &l);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200448
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200449 luaL_Buffer b;
450 luaL_buffinit(L, &b);
451 luaV_addlstring(&b, s, l, 1);
452 luaL_pushresult(&b);
453 return (char_u *) lua_tostring(L, -1);
454}
455
456/* pops a string s from the top of the stack and calls mf(t) for pieces t of
457 * s separated by newlines */
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200458 static void
459luaV_msgfunc(lua_State *L, msgfunc_T mf)
460{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200461 luaL_Buffer b;
462 size_t l;
463 const char *p, *s = lua_tolstring(L, -1, &l);
464 luaL_buffinit(L, &b);
465 luaV_addlstring(&b, s, l, 0);
466 luaL_pushresult(&b);
467 /* break string */
468 p = s = lua_tolstring(L, -1, &l);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200469 while (l--)
470 {
471 if (*p++ == '\0') /* break? */
472 {
473 mf((char_u *) s);
474 s = p;
475 }
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200476 }
477 mf((char_u *) s);
478 lua_pop(L, 2); /* original and modified strings */
479}
480
481
482/* ======= Buffer type ======= */
483
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200484 static luaV_Buffer *
485luaV_newbuffer(lua_State *L, buf_T *buf)
486{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200487 luaV_Buffer *b = (luaV_Buffer *) lua_newuserdata(L, sizeof(luaV_Buffer));
488 *b = buf;
489 lua_pushlightuserdata(L, (void *) buf);
490 lua_pushvalue(L, -2);
491 lua_rawset(L, LUA_ENVIRONINDEX); /* env[buf] = udata */
492 /* to avoid GC, store as key in env */
493 lua_pushvalue(L, -1);
494 lua_pushboolean(L, 1);
495 lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = true */
496 /* set metatable */
497 luaV_getfield(L, LUAVIM_BUFFER);
498 lua_setmetatable(L, -2);
499 return b;
500}
501
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200502 static luaV_Buffer *
503luaV_pushbuffer (lua_State *L, buf_T *buf)
504{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200505 luaV_Buffer *b = NULL;
506 if (buf == NULL)
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200507 lua_pushnil(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200508 else {
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200509 lua_pushlightuserdata(L, (void *) buf);
510 lua_rawget(L, LUA_ENVIRONINDEX);
511 if (lua_isnil(L, -1)) /* not interned? */
512 {
513 lua_pop(L, 1);
514 b = luaV_newbuffer(L, buf);
515 }
516 else
517 b = (luaV_Buffer *) lua_touserdata(L, -1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200518 }
519 return b;
520}
521
522/* Buffer metamethods */
523
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200524 static int
525luaV_buffer_tostring(lua_State *L)
526{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200527 lua_pushfstring(L, "%s: %p", LUAVIM_BUFFER, lua_touserdata(L, 1));
528 return 1;
529}
530
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200531 static int
532luaV_buffer_len(lua_State *L)
533{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200534 luaV_Buffer *b = lua_touserdata(L, 1);
535 lua_pushinteger(L, (*b)->b_ml.ml_line_count);
536 return 1;
537}
538
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200539 static int
540luaV_buffer_call(lua_State *L)
541{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200542 luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1);
543 lua_settop(L, 1);
544 set_curbuf(*b, DOBUF_SPLIT);
545 return 1;
546}
547
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200548 static int
549luaV_buffer_index(lua_State *L)
550{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200551 luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1);
552 linenr_T n = (linenr_T) lua_tointeger(L, 2);
553 if (n > 0 && n <= (*b)->b_ml.ml_line_count)
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200554 luaV_pushline(L, *b, n);
555 else if (lua_isstring(L, 2))
556 {
557 const char *s = lua_tostring(L, 2);
558 if (strncmp(s, "name", 4) == 0)
559 lua_pushstring(L, (char *) (*b)->b_sfname);
560 else if (strncmp(s, "fname", 5) == 0)
561 lua_pushstring(L, (char *) (*b)->b_ffname);
562 else if (strncmp(s, "number", 6) == 0)
563 lua_pushinteger(L, (*b)->b_fnum);
564 /* methods */
565 else if (strncmp(s, "insert", 6) == 0
566 || strncmp(s, "next", 4) == 0
567 || strncmp(s, "previous", 8) == 0
568 || strncmp(s, "isvalid", 7) == 0)
569 {
570 lua_getmetatable(L, 1);
571 lua_getfield(L, -1, s);
572 }
573 else
574 lua_pushnil(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200575 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200576 else
577 lua_pushnil(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200578 return 1;
579}
580
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200581 static int
582luaV_buffer_newindex(lua_State *L)
583{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200584 luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1);
585 linenr_T n = (linenr_T) luaL_checkinteger(L, 2);
586#ifdef HAVE_SANDBOX
587 luaV_checksandbox(L);
588#endif
589 if (n < 1 || n > (*b)->b_ml.ml_line_count)
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200590 luaL_error(L, "invalid line number");
591 if (lua_isnil(L, 3)) /* delete line */
592 {
593 buf_T *buf = curbuf;
594 curbuf = *b;
595 if (u_savedel(n, 1L) == FAIL)
596 {
597 curbuf = buf;
598 luaL_error(L, "cannot save undo information");
599 }
600 else if (ml_delete(n, FALSE) == FAIL)
601 {
602 curbuf = buf;
603 luaL_error(L, "cannot delete line");
604 }
605 else {
606 deleted_lines_mark(n, 1L);
607 if (*b == curwin->w_buffer) /* fix cursor in current window? */
608 {
609 if (curwin->w_cursor.lnum >= n)
610 {
611 if (curwin->w_cursor.lnum > n)
612 {
613 curwin->w_cursor.lnum -= 1;
614 check_cursor_col();
615 }
616 else check_cursor();
617 changed_cline_bef_curs();
618 }
619 invalidate_botline();
620 }
621 }
622 curbuf = buf;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200623 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200624 else if (lua_isstring(L, 3)) /* update line */
625 {
626 buf_T *buf = curbuf;
627 curbuf = *b;
628 if (u_savesub(n) == FAIL)
629 {
630 curbuf = buf;
631 luaL_error(L, "cannot save undo information");
632 }
633 else if (ml_replace(n, luaV_toline(L, 3), TRUE) == FAIL)
634 {
635 curbuf = buf;
636 luaL_error(L, "cannot replace line");
637 }
638 else changed_bytes(n, 0);
639 curbuf = buf;
640 if (*b == curwin->w_buffer)
641 check_cursor_col();
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200642 }
643 else
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200644 luaL_error(L, "wrong argument to change line");
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200645 return 0;
646}
647
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200648 static int
649luaV_buffer_insert(lua_State *L)
650{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200651 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
652 linenr_T last = (*b)->b_ml.ml_line_count;
653 linenr_T n = (linenr_T) luaL_optinteger(L, 3, last);
654 buf_T *buf;
655 luaL_checktype(L, 2, LUA_TSTRING);
656#ifdef HAVE_SANDBOX
657 luaV_checksandbox(L);
658#endif
659 /* fix insertion line */
660 if (n < 0) n = 0;
661 if (n > last) n = last;
662 /* insert */
663 buf = curbuf;
664 curbuf = *b;
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200665 if (u_save(n, n + 1) == FAIL)
666 {
667 curbuf = buf;
668 luaL_error(L, "cannot save undo information");
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200669 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200670 else if (ml_append(n, luaV_toline(L, 2), 0, FALSE) == FAIL)
671 {
672 curbuf = buf;
673 luaL_error(L, "cannot insert line");
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200674 }
675 else
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200676 appended_lines_mark(n, 1L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200677 curbuf = buf;
678 update_screen(VALID);
679 return 0;
680}
681
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200682 static int
683luaV_buffer_next(lua_State *L)
684{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200685 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
686 luaV_pushbuffer(L, (*b)->b_next);
687 return 1;
688}
689
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200690 static int
691luaV_buffer_previous(lua_State *L)
692{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200693 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
694 luaV_pushbuffer(L, (*b)->b_prev);
695 return 1;
696}
697
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200698 static int
699luaV_buffer_isvalid(lua_State *L)
700{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200701 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
702 lua_pushlightuserdata(L, (void *) (*b));
703 lua_rawget(L, LUA_ENVIRONINDEX);
704 lua_pushboolean(L, !lua_isnil(L, -1));
705 return 1;
706}
707
708static const luaL_Reg luaV_Buffer_mt[] = {
709 {"__tostring", luaV_buffer_tostring},
710 {"__len", luaV_buffer_len},
711 {"__call", luaV_buffer_call},
712 {"__index", luaV_buffer_index},
713 {"__newindex", luaV_buffer_newindex},
714 {"insert", luaV_buffer_insert},
715 {"next", luaV_buffer_next},
716 {"previous", luaV_buffer_previous},
717 {"isvalid", luaV_buffer_isvalid},
718 {NULL, NULL}
719};
720
721
722/* ======= Window type ======= */
723
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200724 static luaV_Window *
725luaV_newwindow(lua_State *L, win_T *win)
726{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200727 luaV_Window *w = (luaV_Window *) lua_newuserdata(L, sizeof(luaV_Window));
728 *w = win;
729 lua_pushlightuserdata(L, (void *) win);
730 lua_pushvalue(L, -2);
731 lua_rawset(L, LUA_ENVIRONINDEX); /* env[win] = udata */
732 /* to avoid GC, store as key in env */
733 lua_pushvalue(L, -1);
734 lua_pushboolean(L, 1);
735 lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = true */
736 /* set metatable */
737 luaV_getfield(L, LUAVIM_WINDOW);
738 lua_setmetatable(L, -2);
739 return w;
740}
741
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200742 static luaV_Window *
743luaV_pushwindow(lua_State *L, win_T *win)
744{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200745 luaV_Window *w = NULL;
746 if (win == NULL)
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200747 lua_pushnil(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200748 else {
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200749 lua_pushlightuserdata(L, (void *) win);
750 lua_rawget(L, LUA_ENVIRONINDEX);
751 if (lua_isnil(L, -1)) /* not interned? */
752 {
753 lua_pop(L, 1);
754 w = luaV_newwindow(L, win);
755 }
756 else w = (luaV_Window *) lua_touserdata(L, -1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200757 }
758 return w;
759}
760
761/* Window metamethods */
762
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200763 static int
764luaV_window_tostring(lua_State *L)
765{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200766 lua_pushfstring(L, "%s: %p", LUAVIM_WINDOW, lua_touserdata(L, 1));
767 return 1;
768}
769
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200770 static int
771luaV_window_call(lua_State *L)
772{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200773 luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1);
774 lua_settop(L, 1);
775 win_goto(*w);
776 return 1;
777}
778
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200779 static int
780luaV_window_index(lua_State *L)
781{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200782 luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1);
783 const char *s = luaL_checkstring(L, 2);
784 if (strncmp(s, "buffer", 6) == 0)
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200785 luaV_pushbuffer(L, (*w)->w_buffer);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200786 else if (strncmp(s, "line", 4) == 0)
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200787 lua_pushinteger(L, (*w)->w_cursor.lnum);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200788 else if (strncmp(s, "col", 3) == 0)
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200789 lua_pushinteger(L, (*w)->w_cursor.col + 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200790#ifdef FEAT_VERTSPLIT
791 else if (strncmp(s, "width", 5) == 0)
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200792 lua_pushinteger(L, W_WIDTH((*w)));
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200793#endif
794 else if (strncmp(s, "height", 6) == 0)
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200795 lua_pushinteger(L, (*w)->w_height);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200796 /* methods */
797 else if (strncmp(s, "next", 4) == 0
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200798 || strncmp(s, "previous", 8) == 0
799 || strncmp(s, "isvalid", 7) == 0)
800 {
801 lua_getmetatable(L, 1);
802 lua_getfield(L, -1, s);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200803 }
804 else
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200805 lua_pushnil(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200806 return 1;
807}
808
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200809 static int
810luaV_window_newindex (lua_State *L)
811{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200812 luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1);
813 const char *s = luaL_checkstring(L, 2);
814 int v = luaL_checkinteger(L, 3);
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200815 if (strncmp(s, "line", 4) == 0)
816 {
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200817#ifdef HAVE_SANDBOX
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200818 luaV_checksandbox(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200819#endif
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200820 if (v < 1 || v > (*w)->w_buffer->b_ml.ml_line_count)
821 luaL_error(L, "line out of range");
822 (*w)->w_cursor.lnum = v;
823 update_screen(VALID);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200824 }
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200825 else if (strncmp(s, "col", 3) == 0)
826 {
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200827#ifdef HAVE_SANDBOX
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200828 luaV_checksandbox(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200829#endif
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200830 (*w)->w_cursor.col = v - 1;
831 update_screen(VALID);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200832 }
833#ifdef FEAT_VERTSPLIT
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200834 else if (strncmp(s, "width", 5) == 0)
835 {
836 win_T *win = curwin;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200837#ifdef FEAT_GUI
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200838 need_mouse_correct = TRUE;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200839#endif
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200840 curwin = *w;
841 win_setwidth(v);
842 curwin = win;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200843 }
844#endif
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200845 else if (strncmp(s, "height", 6) == 0)
846 {
847 win_T *win = curwin;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200848#ifdef FEAT_GUI
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200849 need_mouse_correct = TRUE;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200850#endif
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200851 curwin = *w;
852 win_setheight(v);
853 curwin = win;
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200854 }
855 else
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200856 luaL_error(L, "invalid window property: `%s'", s);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200857 return 0;
858}
859
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200860 static int
861luaV_window_next(lua_State *L)
862{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200863 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
864 luaV_pushwindow(L, (*w)->w_next);
865 return 1;
866}
867
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200868 static int
869luaV_window_previous(lua_State *L)
870{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200871 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
872 luaV_pushwindow(L, (*w)->w_prev);
873 return 1;
874}
875
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200876 static int
877luaV_window_isvalid(lua_State *L)
878{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200879 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
880 lua_pushlightuserdata(L, (void *) (*w));
881 lua_rawget(L, LUA_ENVIRONINDEX);
882 lua_pushboolean(L, !lua_isnil(L, -1));
883 return 1;
884}
885
886static const luaL_Reg luaV_Window_mt[] = {
887 {"__tostring", luaV_window_tostring},
888 {"__call", luaV_window_call},
889 {"__index", luaV_window_index},
890 {"__newindex", luaV_window_newindex},
891 {"next", luaV_window_next},
892 {"previous", luaV_window_previous},
893 {"isvalid", luaV_window_isvalid},
894 {NULL, NULL}
895};
896
897
898/* ======= Vim module ======= */
899
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200900 static int
901luaV_print(lua_State *L)
902{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200903 int i, n = lua_gettop(L); /* nargs */
904 const char *s;
905 size_t l;
906 luaL_Buffer b;
907 luaL_buffinit(L, &b);
908 lua_getglobal(L, "tostring");
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200909 for (i = 1; i <= n; i++)
910 {
911 lua_pushvalue(L, -1); /* tostring */
912 lua_pushvalue(L, i); /* arg */
913 lua_call(L, 1, 1);
914 s = lua_tolstring(L, -1, &l);
915 if (s == NULL)
916 return luaL_error(L, "cannot convert to string");
917 if (i > 1) luaL_addchar(&b, ' '); /* use space instead of tab */
918 luaV_addlstring(&b, s, l, 0);
919 lua_pop(L, 1);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200920 }
921 luaL_pushresult(&b);
922 luaV_msg(L);
923 return 0;
924}
925
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200926 static int
927luaV_command(lua_State *L)
928{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200929 do_cmdline_cmd((char_u *) luaL_checkstring(L, 1));
930 update_screen(VALID);
931 return 0;
932}
933
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200934 static int
935luaV_eval(lua_State *L)
936{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200937 typval_T *tv = eval_expr((char_u *) luaL_checkstring(L, 1), NULL);
938 if (tv == NULL) luaL_error(L, "invalid expression");
939 luaV_pushtypval(L, tv);
940 return 1;
941}
942
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200943 static int
Bram Moolenaar0d2e4fc2010-07-18 12:35:47 +0200944luaV_beep(lua_State *L UNUSED)
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200945{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200946 vim_beep();
947 return 0;
948}
949
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200950 static int
951luaV_line(lua_State *L)
952{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200953 luaV_pushline(L, curbuf, curwin->w_cursor.lnum);
954 return 1;
955}
956
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200957 static int
958luaV_buffer(lua_State *L)
959{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200960 buf_T *buf;
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200961 if (lua_isstring(L, 1)) /* get by number or name? */
962 {
963 if (lua_isnumber(L, 1)) /* by number? */
964 {
965 int n = lua_tointeger(L, 1);
966 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
967 if (buf->b_fnum == n) break;
968 }
969 else { /* by name */
970 size_t l;
971 const char *s = lua_tolstring(L, 1, &l);
972 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
973 {
974 if (buf->b_ffname == NULL || buf->b_sfname == NULL)
975 {
976 if (l == 0) break;
977 }
Bram Moolenaar0d2e4fc2010-07-18 12:35:47 +0200978 else if (strncmp(s, (char *)buf->b_ffname, l) == 0
979 || strncmp(s, (char *)buf->b_sfname, l) == 0)
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200980 break;
981 }
982 }
983 if (buf == NULL) /* not found? */
984 lua_pushnil(L);
985 else
986 luaV_pushbuffer(L, buf);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200987 }
988 else {
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200989 buf = (lua_toboolean(L, 1)) ? firstbuf : curbuf; /* first buffer? */
990 luaV_pushbuffer(L, buf);
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200991 }
992 return 1;
993}
994
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200995 static int
996luaV_window(lua_State *L)
997{
Bram Moolenaar0ba04292010-07-14 23:23:17 +0200998 win_T *win;
Bram Moolenaar55d5c032010-07-17 23:52:29 +0200999 if (lua_isnumber(L, 1)) /* get by number? */
1000 {
1001 int n = lua_tointeger(L, 1);
1002 for (win = firstwin; win != NULL; win = win->w_next, n--)
1003 if (n == 1) break;
1004 if (win == NULL) /* not found? */
1005 lua_pushnil(L);
1006 else
1007 luaV_pushwindow(L, win);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001008 }
1009 else {
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001010 win = (lua_toboolean(L, 1)) ? firstwin : curwin; /* first window? */
1011 luaV_pushwindow(L, win);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001012 }
1013 return 1;
1014}
1015
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001016 static int
1017luaV_open(lua_State *L)
1018{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001019 luaV_Buffer *b;
1020 char_u *s = NULL;
1021#ifdef HAVE_SANDBOX
1022 luaV_checksandbox(L);
1023#endif
1024 if (lua_isstring(L, 1)) s = (char_u *) lua_tostring(L, 1);
1025 b = luaV_pushbuffer(L, buflist_new(s, NULL, 1L, BLN_LISTED));
1026 return 1;
1027}
1028
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001029 static int
1030luaV_isbuffer(lua_State *L)
1031{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001032 lua_pushboolean(L, luaV_toudata(L, 1, LUAVIM_BUFFER) != NULL);
1033 return 1;
1034}
1035
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001036 static int
1037luaV_iswindow(lua_State *L)
1038{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001039 lua_pushboolean(L, luaV_toudata(L, 1, LUAVIM_WINDOW) != NULL);
1040 return 1;
1041}
1042
1043/* for freeing buffer and window objects; lightuserdata as arg */
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001044 static int
1045luaV_free(lua_State *L)
1046{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001047 lua_pushvalue(L, 1); /* lightudata */
1048 lua_rawget(L, LUA_ENVIRONINDEX);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001049 if (!lua_isnil(L, -1))
1050 {
1051 lua_pushnil(L);
1052 lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = nil */
1053 lua_pushnil(L);
1054 lua_rawset(L, LUA_ENVIRONINDEX); /* env[lightudata] = nil */
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001055 }
1056 return 0;
1057}
1058
1059static const luaL_Reg luaV_module[] = {
1060 {"command", luaV_command},
1061 {"eval", luaV_eval},
1062 {"beep", luaV_beep},
1063 {"line", luaV_line},
1064 {"buffer", luaV_buffer},
1065 {"window", luaV_window},
1066 {"open", luaV_open},
1067 {"isbuffer", luaV_isbuffer},
1068 {"iswindow", luaV_iswindow},
1069 {NULL, NULL}
1070};
1071
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001072 static int
1073luaopen_vim(lua_State *L)
1074{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001075 /* set environment */
1076 lua_newtable(L);
1077 lua_newtable(L);
1078 lua_pushliteral(L, "v");
1079 lua_setfield(L, -2, "__mode");
1080 lua_setmetatable(L, -2);
1081 lua_replace(L, LUA_ENVIRONINDEX);
1082 /* print */
1083 lua_pushcfunction(L, luaV_print);
1084 lua_setglobal(L, "print");
1085 /* free */
1086 lua_pushlightuserdata(L, (void *) LUAVIM_FREE);
1087 lua_pushcfunction(L, luaV_free);
1088 lua_rawset(L, LUA_REGISTRYINDEX);
1089 /* register */
1090 luaV_newmetatable(L, LUAVIM_BUFFER);
1091 luaL_register(L, NULL, luaV_Buffer_mt);
1092 luaV_newmetatable(L, LUAVIM_WINDOW);
1093 luaL_register(L, NULL, luaV_Window_mt);
1094 luaL_register(L, LUAVIM_NAME, luaV_module);
1095 return 0;
1096}
1097
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001098 static lua_State *
1099luaV_newstate(void)
1100{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001101 lua_State *L = luaL_newstate();
Bram Moolenaar16c98f92010-07-28 22:46:08 +02001102 luaL_openlibs(L); /* core libs */
1103 lua_pushcfunction(L, luaopen_vim); /* vim */
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001104 lua_call(L, 0, 0);
1105 return L;
1106}
1107
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001108 static void
1109luaV_setrange(lua_State *L, int line1, int line2)
1110{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001111 lua_getglobal(L, LUAVIM_NAME);
1112 lua_pushinteger(L, line1);
1113 lua_setfield(L, -2, "firstline");
1114 lua_pushinteger(L, line2);
1115 lua_setfield(L, -2, "lastline");
1116 lua_pop(L, 1); /* vim table */
1117}
1118
1119
1120/* ======= Interface ======= */
1121
1122static lua_State *L = NULL;
1123
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001124 static int
Bram Moolenaar2bd6a1b2010-08-12 22:14:01 +02001125lua_is_open(void)
1126{
1127 return L != NULL;
1128}
1129
1130 static int
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001131lua_init(void)
1132{
1133 if (L == NULL)
1134 {
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001135#ifdef DYNAMIC_LUA
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001136 if (!lua_enabled(TRUE))
1137 {
1138 EMSG(_("Lua library cannot be loaded."));
1139 return FAIL;
1140 }
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001141#endif
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001142 L = luaV_newstate();
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001143 }
1144 return OK;
1145}
1146
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001147 void
1148lua_end(void)
1149{
1150 if (L != NULL)
1151 {
1152 lua_close(L);
1153 L = NULL;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001154#ifdef DYNAMIC_LUA
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001155 end_dynamic_lua();
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001156#endif
1157 }
1158}
1159
1160/* ex commands */
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001161 void
1162ex_lua(exarg_T *eap)
1163{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001164 char *script;
1165 if (lua_init() == FAIL) return;
1166 script = (char *) script_get(eap, eap->arg);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001167 if (!eap->skip)
1168 {
1169 char *s = (script) ? script : (char *) eap->arg;
1170 luaV_setrange(L, eap->line1, eap->line2);
1171 if (luaL_loadbuffer(L, s, strlen(s), LUAVIM_CHUNKNAME)
1172 || lua_pcall(L, 0, 0, 0))
1173 luaV_emsg(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001174 }
1175 if (script != NULL) vim_free(script);
1176}
1177
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001178 void
1179ex_luado(exarg_T *eap)
1180{
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001181 linenr_T l;
1182 const char *s = (const char *) eap->arg;
1183 luaL_Buffer b;
1184 size_t len;
1185 if (lua_init() == FAIL) return;
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001186 if (u_save(eap->line1 - 1, eap->line2 + 1) == FAIL)
1187 {
1188 EMSG(_("cannot save undo information"));
1189 return;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001190 }
1191 luaV_setrange(L, eap->line1, eap->line2);
1192 luaL_buffinit(L, &b);
1193 luaL_addlstring(&b, "return function(line) ", 22); /* header */
1194 luaL_addlstring(&b, s, strlen(s));
1195 luaL_addlstring(&b, " end", 4); /* footer */
1196 luaL_pushresult(&b);
1197 s = lua_tolstring(L, -1, &len);
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001198 if (luaL_loadbuffer(L, s, len, LUAVIM_CHUNKNAME))
1199 {
1200 luaV_emsg(L);
1201 lua_pop(L, 1); /* function body */
1202 return;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001203 }
1204 lua_call(L, 0, 1);
1205 lua_replace(L, -2); /* function -> body */
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001206 for (l = eap->line1; l <= eap->line2; l++)
1207 {
1208 lua_pushvalue(L, -1); /* function */
1209 luaV_pushline(L, curbuf, l); /* current line as arg */
1210 if (lua_pcall(L, 1, 1, 0))
1211 {
1212 luaV_emsg(L);
1213 break;
1214 }
1215 if (lua_isstring(L, -1)) /* update line? */
1216 {
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001217#ifdef HAVE_SANDBOX
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001218 luaV_checksandbox(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001219#endif
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001220 ml_replace(l, luaV_toline(L, -1), TRUE);
1221 changed_bytes(l, 0);
1222 lua_pop(L, 1); /* result from luaV_toline */
1223 }
1224 lua_pop(L, 1); /* line */
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001225 }
1226 lua_pop(L, 1); /* function */
1227 check_cursor();
1228 update_screen(NOT_VALID);
1229}
1230
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001231 void
1232ex_luafile(exarg_T *eap)
1233{
1234 if (lua_init() == FAIL)
1235 return;
1236 if (!eap->skip)
1237 {
1238 luaV_setrange(L, eap->line1, eap->line2);
1239 if (luaL_loadfile(L, (char *) eap->arg) || lua_pcall(L, 0, 0, 0))
1240 luaV_emsg(L);
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001241 }
1242}
1243
1244/* buffer */
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001245 void
1246lua_buffer_free(buf_T *buf)
1247{
Bram Moolenaar2bd6a1b2010-08-12 22:14:01 +02001248 if (!lua_is_open()) return;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001249 luaV_getfield(L, LUAVIM_FREE);
1250 lua_pushlightuserdata(L, (void *) buf);
1251 lua_call(L, 1, 0);
1252}
1253
1254/* window */
Bram Moolenaar55d5c032010-07-17 23:52:29 +02001255 void
1256lua_window_free(win_T *win)
1257{
Bram Moolenaar2bd6a1b2010-08-12 22:14:01 +02001258 if (!lua_is_open()) return;
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001259 luaV_getfield(L, LUAVIM_FREE);
1260 lua_pushlightuserdata(L, (void *) win);
1261 lua_call(L, 1, 0);
1262}
1263
1264#endif