Mercurial > vim
comparison src/if_lua.c @ 2320:966a5609669e vim73
Added Lua interfae. (Luis Carvalho)
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Wed, 14 Jul 2010 23:23:17 +0200 |
parents | |
children | ea4bf6df1a8a |
comparison
equal
deleted
inserted
replaced
2319:c79ccf947487 | 2320:966a5609669e |
---|---|
1 /* 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 | |
12 #include <stdio.h> | |
13 #include <string.h> | |
14 #include <lua.h> | |
15 #include <lualib.h> | |
16 #include <lauxlib.h> | |
17 #include "vim.h" | |
18 | |
19 /* Only do the following when the feature is enabled. Needed for "make | |
20 * depend". */ | |
21 #if defined(FEAT_LUA) || defined(PROTO) | |
22 | |
23 #define LUAVIM_CHUNKNAME "vim chunk" | |
24 #define LUAVIM_NAME "vim" | |
25 | |
26 typedef buf_T *luaV_Buffer; | |
27 typedef win_T *luaV_Window; | |
28 typedef void (*msgfunc_T)(char_u *); | |
29 | |
30 static const char LUAVIM_BUFFER[] = "buffer"; | |
31 static const char LUAVIM_WINDOW[] = "window"; | |
32 static const char LUAVIM_FREE[] = "luaV_free"; | |
33 | |
34 #define luaV_getfield(L, s) \ | |
35 lua_pushlightuserdata((L), (void *)(s)); \ | |
36 lua_rawget((L), LUA_REGISTRYINDEX) | |
37 #define luaV_checksandbox(L) \ | |
38 if (sandbox) luaL_error((L), "not allowed in sandbox") | |
39 #define luaV_msg(L) luaV_msgfunc((L), (msgfunc_T) msg) | |
40 #define luaV_emsg(L) luaV_msgfunc((L), (msgfunc_T) emsg) | |
41 | |
42 | |
43 #ifdef DYNAMIC_LUA | |
44 /* lauxlib */ | |
45 #define luaL_register dll_luaL_register | |
46 #define luaL_typerror dll_luaL_typerror | |
47 #define luaL_checklstring dll_luaL_checklstring | |
48 #define luaL_checkinteger dll_luaL_checkinteger | |
49 #define luaL_optinteger dll_luaL_optinteger | |
50 #define luaL_checktype dll_luaL_checktype | |
51 #define luaL_error dll_luaL_error | |
52 #define luaL_loadfile dll_luaL_loadfile | |
53 #define luaL_loadbuffer dll_luaL_loadbuffer | |
54 #define luaL_newstate dll_luaL_newstate | |
55 #define luaL_buffinit dll_luaL_buffinit | |
56 #define luaL_prepbuffer dll_luaL_prepbuffer | |
57 #define luaL_addlstring dll_luaL_addlstring | |
58 #define luaL_pushresult dll_luaL_pushresult | |
59 /* lua */ | |
60 #define lua_close dll_lua_close | |
61 #define lua_gettop dll_lua_gettop | |
62 #define lua_settop dll_lua_settop | |
63 #define lua_pushvalue dll_lua_pushvalue | |
64 #define lua_replace dll_lua_replace | |
65 #define lua_isnumber dll_lua_isnumber | |
66 #define lua_isstring dll_lua_isstring | |
67 #define lua_type dll_lua_type | |
68 #define lua_rawequal dll_lua_rawequal | |
69 #define lua_tonumber dll_lua_tonumber | |
70 #define lua_tointeger dll_lua_tointeger | |
71 #define lua_toboolean dll_lua_toboolean | |
72 #define lua_tolstring dll_lua_tolstring | |
73 #define lua_touserdata dll_lua_touserdata | |
74 #define lua_pushnil dll_lua_pushnil | |
75 #define lua_pushnumber dll_lua_pushnumber | |
76 #define lua_pushinteger dll_lua_pushinteger | |
77 #define lua_pushlstring dll_lua_pushlstring | |
78 #define lua_pushstring dll_lua_pushstring | |
79 #define lua_pushfstring dll_lua_pushfstring | |
80 #define lua_pushcclosure dll_lua_pushcclosure | |
81 #define lua_pushboolean dll_lua_pushboolean | |
82 #define lua_pushlightuserdata dll_lua_pushlightuserdata | |
83 #define lua_getfield dll_lua_getfield | |
84 #define lua_rawget dll_lua_rawget | |
85 #define lua_createtable dll_lua_createtable | |
86 #define lua_newuserdata dll_lua_newuserdata | |
87 #define lua_getmetatable dll_lua_getmetatable | |
88 #define lua_setfield dll_lua_setfield | |
89 #define lua_rawset dll_lua_rawset | |
90 #define lua_rawseti dll_lua_rawseti | |
91 #define lua_setmetatable dll_lua_setmetatable | |
92 #define lua_call dll_lua_call | |
93 #define lua_pcall dll_lua_pcall | |
94 /* libs */ | |
95 #define luaopen_base dll_luaopen_base | |
96 #define luaopen_table dll_luaopen_table | |
97 #define luaopen_string dll_luaopen_string | |
98 #define luaopen_math dll_luaopen_math | |
99 #define luaopen_os dll_luaopen_os | |
100 #define luaopen_package dll_luaopen_package | |
101 #define luaopen_debug dll_luaopen_debug | |
102 | |
103 /* lauxlib */ | |
104 void (*dll_luaL_register) (lua_State *L, const char *libname, const luaL_Reg *l); | |
105 int (*dll_luaL_typerror) (lua_State *L, int narg, const char *tname); | |
106 const char *(*dll_luaL_checklstring) (lua_State *L, int numArg, size_t *l); | |
107 lua_Integer (*dll_luaL_checkinteger) (lua_State *L, int numArg); | |
108 lua_Integer (*dll_luaL_optinteger) (lua_State *L, int nArg, lua_Integer def); | |
109 void (*dll_luaL_checktype) (lua_State *L, int narg, int t); | |
110 int (*dll_luaL_error) (lua_State *L, const char *fmt, ...); | |
111 int (*dll_luaL_loadfile) (lua_State *L, const char *filename); | |
112 int (*dll_luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, const char *name); | |
113 lua_State *(*dll_luaL_newstate) (void); | |
114 void (*dll_luaL_buffinit) (lua_State *L, luaL_Buffer *B); | |
115 char *(*dll_luaL_prepbuffer) (luaL_Buffer *B); | |
116 void (*dll_luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); | |
117 void (*dll_luaL_pushresult) (luaL_Buffer *B); | |
118 /* lua */ | |
119 void (*dll_lua_close) (lua_State *L); | |
120 int (*dll_lua_gettop) (lua_State *L); | |
121 void (*dll_lua_settop) (lua_State *L, int idx); | |
122 void (*dll_lua_pushvalue) (lua_State *L, int idx); | |
123 void (*dll_lua_replace) (lua_State *L, int idx); | |
124 int (*dll_lua_isnumber) (lua_State *L, int idx); | |
125 int (*dll_lua_isstring) (lua_State *L, int idx); | |
126 int (*dll_lua_type) (lua_State *L, int idx); | |
127 int (*dll_lua_rawequal) (lua_State *L, int idx1, int idx2); | |
128 lua_Number (*dll_lua_tonumber) (lua_State *L, int idx); | |
129 lua_Integer (*dll_lua_tointeger) (lua_State *L, int idx); | |
130 int (*dll_lua_toboolean) (lua_State *L, int idx); | |
131 const char *(*dll_lua_tolstring) (lua_State *L, int idx, size_t *len); | |
132 void *(*dll_lua_touserdata) (lua_State *L, int idx); | |
133 void (*dll_lua_pushnil) (lua_State *L); | |
134 void (*dll_lua_pushnumber) (lua_State *L, lua_Number n); | |
135 void (*dll_lua_pushinteger) (lua_State *L, lua_Integer n); | |
136 void (*dll_lua_pushlstring) (lua_State *L, const char *s, size_t l); | |
137 void (*dll_lua_pushstring) (lua_State *L, const char *s); | |
138 const char *(*dll_lua_pushfstring) (lua_State *L, const char *fmt, ...); | |
139 void (*dll_lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); | |
140 void (*dll_lua_pushboolean) (lua_State *L, int b); | |
141 void (*dll_lua_pushlightuserdata) (lua_State *L, void *p); | |
142 void (*dll_lua_getfield) (lua_State *L, int idx, const char *k); | |
143 void (*dll_lua_rawget) (lua_State *L, int idx); | |
144 void (*dll_lua_createtable) (lua_State *L, int narr, int nrec); | |
145 void *(*dll_lua_newuserdata) (lua_State *L, size_t sz); | |
146 int (*dll_lua_getmetatable) (lua_State *L, int objindex); | |
147 void (*dll_lua_setfield) (lua_State *L, int idx, const char *k); | |
148 void (*dll_lua_rawset) (lua_State *L, int idx); | |
149 void (*dll_lua_rawseti) (lua_State *L, int idx, int n); | |
150 int (*dll_lua_setmetatable) (lua_State *L, int objindex); | |
151 void (*dll_lua_call) (lua_State *L, int nargs, int nresults); | |
152 int (*dll_lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); | |
153 /* libs */ | |
154 int (*dll_luaopen_base) (lua_State *L); | |
155 int (*dll_luaopen_table) (lua_State *L); | |
156 int (*dll_luaopen_string) (lua_State *L); | |
157 int (*dll_luaopen_math) (lua_State *L); | |
158 int (*dll_luaopen_os) (lua_State *L); | |
159 int (*dll_luaopen_package) (lua_State *L); | |
160 int (*dll_luaopen_debug) (lua_State *L); | |
161 | |
162 typedef void **luaV_function; | |
163 typedef struct { | |
164 const char *name; | |
165 luaV_function func; | |
166 } luaV_Reg; | |
167 | |
168 static const luaV_Reg luaV_dll[] = { | |
169 /* lauxlib */ | |
170 {"luaL_register", (luaV_function) &dll_luaL_register}, | |
171 {"luaL_typerror", (luaV_function) &dll_luaL_typerror}, | |
172 {"luaL_checklstring", (luaV_function) &dll_luaL_checklstring}, | |
173 {"luaL_checkinteger", (luaV_function) &dll_luaL_checkinteger}, | |
174 {"luaL_optinteger", (luaV_function) &dll_luaL_optinteger}, | |
175 {"luaL_checktype", (luaV_function) &dll_luaL_checktype}, | |
176 {"luaL_error", (luaV_function) &dll_luaL_error}, | |
177 {"luaL_loadfile", (luaV_function) &dll_luaL_loadfile}, | |
178 {"luaL_loadbuffer", (luaV_function) &dll_luaL_loadbuffer}, | |
179 {"luaL_newstate", (luaV_function) &dll_luaL_newstate}, | |
180 {"luaL_buffinit", (luaV_function) &dll_luaL_buffinit}, | |
181 {"luaL_prepbuffer", (luaV_function) &dll_luaL_prepbuffer}, | |
182 {"luaL_addlstring", (luaV_function) &dll_luaL_addlstring}, | |
183 {"luaL_pushresult", (luaV_function) &dll_luaL_pushresult}, | |
184 /* lua */ | |
185 {"lua_close", (luaV_function) &dll_lua_close}, | |
186 {"lua_gettop", (luaV_function) &dll_lua_gettop}, | |
187 {"lua_settop", (luaV_function) &dll_lua_settop}, | |
188 {"lua_pushvalue", (luaV_function) &dll_lua_pushvalue}, | |
189 {"lua_replace", (luaV_function) &dll_lua_replace}, | |
190 {"lua_isnumber", (luaV_function) &dll_lua_isnumber}, | |
191 {"lua_isstring", (luaV_function) &dll_lua_isstring}, | |
192 {"lua_type", (luaV_function) &dll_lua_type}, | |
193 {"lua_rawequal", (luaV_function) &dll_lua_rawequal}, | |
194 {"lua_tonumber", (luaV_function) &dll_lua_tonumber}, | |
195 {"lua_tointeger", (luaV_function) &dll_lua_tointeger}, | |
196 {"lua_toboolean", (luaV_function) &dll_lua_toboolean}, | |
197 {"lua_tolstring", (luaV_function) &dll_lua_tolstring}, | |
198 {"lua_touserdata", (luaV_function) &dll_lua_touserdata}, | |
199 {"lua_pushnil", (luaV_function) &dll_lua_pushnil}, | |
200 {"lua_pushnumber", (luaV_function) &dll_lua_pushnumber}, | |
201 {"lua_pushinteger", (luaV_function) &dll_lua_pushinteger}, | |
202 {"lua_pushlstring", (luaV_function) &dll_lua_pushlstring}, | |
203 {"lua_pushstring", (luaV_function) &dll_lua_pushstring}, | |
204 {"lua_pushfstring", (luaV_function) &dll_lua_pushfstring}, | |
205 {"lua_pushcclosure", (luaV_function) &dll_lua_pushcclosure}, | |
206 {"lua_pushboolean", (luaV_function) &dll_lua_pushboolean}, | |
207 {"lua_pushlightuserdata", (luaV_function) &dll_lua_pushlightuserdata}, | |
208 {"lua_getfield", (luaV_function) &dll_lua_getfield}, | |
209 {"lua_rawget", (luaV_function) &dll_lua_rawget}, | |
210 {"lua_createtable", (luaV_function) &dll_lua_createtable}, | |
211 {"lua_newuserdata", (luaV_function) &dll_lua_newuserdata}, | |
212 {"lua_getmetatable", (luaV_function) &dll_lua_getmetatable}, | |
213 {"lua_setfield", (luaV_function) &dll_lua_setfield}, | |
214 {"lua_rawset", (luaV_function) &dll_lua_rawset}, | |
215 {"lua_rawseti", (luaV_function) &dll_lua_rawseti}, | |
216 {"lua_setmetatable", (luaV_function) &dll_lua_setmetatable}, | |
217 {"lua_call", (luaV_function) &dll_lua_call}, | |
218 {"lua_pcall", (luaV_function) &dll_lua_pcall}, | |
219 /* libs */ | |
220 {"luaopen_base", (luaV_function) &dll_luaopen_base}, | |
221 {"luaopen_table", (luaV_function) &dll_luaopen_table}, | |
222 {"luaopen_string", (luaV_function) &dll_luaopen_string}, | |
223 {"luaopen_math", (luaV_function) &dll_luaopen_math}, | |
224 {"luaopen_os", (luaV_function) &dll_luaopen_os}, | |
225 {"luaopen_package", (luaV_function) &dll_luaopen_package}, | |
226 {"luaopen_debug", (luaV_function) &dll_luaopen_debug}, | |
227 {NULL, NULL} | |
228 }; | |
229 | |
230 static HINSTANCE hinstLua = 0; | |
231 | |
232 static void end_dynamic_lua (void) { | |
233 if (hinstLua) { | |
234 FreeLibrary(hinstLua); | |
235 hinstLua = 0; | |
236 } | |
237 } | |
238 | |
239 static int lua_link_init (char *libname, int verbose) { | |
240 const luaV_Reg *reg; | |
241 if (hinstLua) return OK; | |
242 hinstLua = LoadLibrary(libname); | |
243 if (!hinstLua) { | |
244 if (verbose) EMSG2(_(e_loadlib), libname); | |
245 return FAIL; | |
246 } | |
247 for (reg = luaV_dll; reg->func; reg++) { | |
248 if ((*reg->func = GetProcAddress(hinstLua, reg->name)) == NULL) { | |
249 FreeLibrary(hinstLua); | |
250 hinstLua = 0; | |
251 if (verbose) EMSG2(_(e_loadfunc), reg->name); | |
252 return FAIL; | |
253 } | |
254 } | |
255 return OK; | |
256 } | |
257 | |
258 int lua_enabled (int verbose) { | |
259 return lua_link_init(DYNAMIC_LUA_DLL, verbose) == OK; | |
260 } | |
261 | |
262 #endif /* DYNAMIC_LUA */ | |
263 | |
264 | |
265 /* ======= Internal ======= */ | |
266 | |
267 static void luaV_newmetatable (lua_State *L, const char *tname) { | |
268 lua_newtable(L); | |
269 lua_pushlightuserdata(L, (void *) tname); | |
270 lua_pushvalue(L, -2); | |
271 lua_rawset(L, LUA_REGISTRYINDEX); | |
272 } | |
273 | |
274 static void *luaV_toudata (lua_State *L, int ud, const char *tname) { | |
275 void *p = lua_touserdata(L, ud); | |
276 if (p != NULL) { /* value is userdata? */ | |
277 if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ | |
278 luaV_getfield(L, tname); /* get metatable */ | |
279 if (lua_rawequal(L, -1, -2)) { /* MTs match? */ | |
280 lua_pop(L, 2); /* MTs */ | |
281 return p; | |
282 } | |
283 } | |
284 } | |
285 return NULL; | |
286 } | |
287 | |
288 static void *luaV_checkudata (lua_State *L, int ud, const char *tname) { | |
289 void *p = luaV_toudata(L, ud, tname); | |
290 if (p == NULL) luaL_typerror(L, ud, tname); | |
291 return p; | |
292 } | |
293 | |
294 static void luaV_pushtypval (lua_State *L, typval_T *tv) { | |
295 if (tv == NULL) luaL_error(L, "null type"); | |
296 switch (tv->v_type) { | |
297 case VAR_STRING: | |
298 lua_pushstring(L, (char *) tv->vval.v_string); | |
299 break; | |
300 case VAR_NUMBER: | |
301 lua_pushinteger(L, (int) tv->vval.v_number); | |
302 break; | |
303 #ifdef FEAT_FLOAT | |
304 case VAR_FLOAT: | |
305 lua_pushnumber(L, (lua_Number) tv->vval.v_float); | |
306 break; | |
307 #endif | |
308 case VAR_LIST: { | |
309 list_T *l = tv->vval.v_list; | |
310 if (l != NULL) { | |
311 /* check cache */ | |
312 lua_pushlightuserdata(L, (void *) l); | |
313 lua_rawget(L, LUA_ENVIRONINDEX); | |
314 if (lua_isnil(L, -1)) { /* not interned? */ | |
315 listitem_T *li; | |
316 int n = 0; | |
317 lua_pop(L, 1); /* nil */ | |
318 lua_newtable(L); | |
319 lua_pushlightuserdata(L, (void *) l); | |
320 lua_pushvalue(L, -2); | |
321 lua_rawset(L, LUA_ENVIRONINDEX); | |
322 for (li = l->lv_first; li != NULL; li = li->li_next) { | |
323 luaV_pushtypval(L, &li->li_tv); | |
324 lua_rawseti(L, -2, ++n); | |
325 } | |
326 } | |
327 } | |
328 else lua_pushnil(L); | |
329 break; | |
330 } | |
331 case VAR_DICT: { | |
332 dict_T *d = tv->vval.v_dict; | |
333 if (d != NULL) { | |
334 /* check cache */ | |
335 lua_pushlightuserdata(L, (void *) d); | |
336 lua_rawget(L, LUA_ENVIRONINDEX); | |
337 if (lua_isnil(L, -1)) { /* not interned? */ | |
338 hashtab_T *ht = &d->dv_hashtab; | |
339 hashitem_T *hi; | |
340 int n = ht->ht_used; /* remaining items */ | |
341 lua_pop(L, 1); /* nil */ | |
342 lua_newtable(L); | |
343 lua_pushlightuserdata(L, (void *) d); | |
344 lua_pushvalue(L, -2); | |
345 lua_rawset(L, LUA_ENVIRONINDEX); | |
346 for (hi = ht->ht_array; n > 0; hi++) { | |
347 if (!HASHITEM_EMPTY(hi)) { | |
348 dictitem_T *di = dict_lookup(hi); | |
349 luaV_pushtypval(L, &di->di_tv); | |
350 lua_setfield(L, -2, (char *) hi->hi_key); | |
351 n--; | |
352 } | |
353 } | |
354 } | |
355 } | |
356 else lua_pushnil(L); | |
357 break; | |
358 } | |
359 default: | |
360 luaL_error(L, "invalid type"); | |
361 } | |
362 } | |
363 | |
364 /* similar to luaL_addlstring, but replaces \0 with \n if toline and | |
365 * \n with \0 otherwise */ | |
366 static void luaV_addlstring (luaL_Buffer *b, const char *s, size_t l, | |
367 int toline) { | |
368 while (l--) { | |
369 if (*s == '\0' && toline) luaL_addchar(b, '\n'); | |
370 else if (*s == '\n' && !toline) luaL_addchar(b, '\0'); | |
371 else luaL_addchar(b, *s); | |
372 s++; | |
373 } | |
374 } | |
375 | |
376 static void luaV_pushline (lua_State *L, buf_T *buf, linenr_T n) { | |
377 const char *s = (const char *) ml_get_buf(buf, n, FALSE); | |
378 luaL_Buffer b; | |
379 luaL_buffinit(L, &b); | |
380 luaV_addlstring(&b, s, strlen(s), 0); | |
381 luaL_pushresult(&b); | |
382 } | |
383 | |
384 static char_u *luaV_toline (lua_State *L, int pos) { | |
385 size_t l; | |
386 const char *s = lua_tolstring(L, pos, &l); | |
387 luaL_Buffer b; | |
388 luaL_buffinit(L, &b); | |
389 luaV_addlstring(&b, s, l, 1); | |
390 luaL_pushresult(&b); | |
391 return (char_u *) lua_tostring(L, -1); | |
392 } | |
393 | |
394 /* pops a string s from the top of the stack and calls mf(t) for pieces t of | |
395 * s separated by newlines */ | |
396 static void luaV_msgfunc (lua_State *L, msgfunc_T mf) { | |
397 luaL_Buffer b; | |
398 size_t l; | |
399 const char *p, *s = lua_tolstring(L, -1, &l); | |
400 luaL_buffinit(L, &b); | |
401 luaV_addlstring(&b, s, l, 0); | |
402 luaL_pushresult(&b); | |
403 /* break string */ | |
404 p = s = lua_tolstring(L, -1, &l); | |
405 while (l--) { | |
406 if (*p++ == '\0') { /* break? */ | |
407 mf((char_u *) s); | |
408 s = p; | |
409 } | |
410 } | |
411 mf((char_u *) s); | |
412 lua_pop(L, 2); /* original and modified strings */ | |
413 } | |
414 | |
415 | |
416 /* ======= Buffer type ======= */ | |
417 | |
418 static luaV_Buffer *luaV_newbuffer (lua_State *L, buf_T *buf) { | |
419 luaV_Buffer *b = (luaV_Buffer *) lua_newuserdata(L, sizeof(luaV_Buffer)); | |
420 *b = buf; | |
421 lua_pushlightuserdata(L, (void *) buf); | |
422 lua_pushvalue(L, -2); | |
423 lua_rawset(L, LUA_ENVIRONINDEX); /* env[buf] = udata */ | |
424 /* to avoid GC, store as key in env */ | |
425 lua_pushvalue(L, -1); | |
426 lua_pushboolean(L, 1); | |
427 lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = true */ | |
428 /* set metatable */ | |
429 luaV_getfield(L, LUAVIM_BUFFER); | |
430 lua_setmetatable(L, -2); | |
431 return b; | |
432 } | |
433 | |
434 static luaV_Buffer *luaV_pushbuffer (lua_State *L, buf_T *buf) { | |
435 luaV_Buffer *b = NULL; | |
436 if (buf == NULL) | |
437 lua_pushnil(L); | |
438 else { | |
439 lua_pushlightuserdata(L, (void *) buf); | |
440 lua_rawget(L, LUA_ENVIRONINDEX); | |
441 if (lua_isnil(L, -1)) { /* not interned? */ | |
442 lua_pop(L, 1); | |
443 b = luaV_newbuffer(L, buf); | |
444 } | |
445 else b = (luaV_Buffer *) lua_touserdata(L, -1); | |
446 } | |
447 return b; | |
448 } | |
449 | |
450 /* Buffer metamethods */ | |
451 | |
452 static int luaV_buffer_tostring (lua_State *L) { | |
453 lua_pushfstring(L, "%s: %p", LUAVIM_BUFFER, lua_touserdata(L, 1)); | |
454 return 1; | |
455 } | |
456 | |
457 static int luaV_buffer_len (lua_State *L) { | |
458 luaV_Buffer *b = lua_touserdata(L, 1); | |
459 lua_pushinteger(L, (*b)->b_ml.ml_line_count); | |
460 return 1; | |
461 } | |
462 | |
463 static int luaV_buffer_call (lua_State *L) { | |
464 luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1); | |
465 lua_settop(L, 1); | |
466 set_curbuf(*b, DOBUF_SPLIT); | |
467 return 1; | |
468 } | |
469 | |
470 static int luaV_buffer_index (lua_State *L) { | |
471 luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1); | |
472 linenr_T n = (linenr_T) lua_tointeger(L, 2); | |
473 if (n > 0 && n <= (*b)->b_ml.ml_line_count) | |
474 luaV_pushline(L, *b, n); | |
475 else if (lua_isstring(L, 2)) { | |
476 const char *s = lua_tostring(L, 2); | |
477 if (strncmp(s, "name", 4) == 0) | |
478 lua_pushstring(L, (char *) (*b)->b_sfname); | |
479 else if (strncmp(s, "fname", 5) == 0) | |
480 lua_pushstring(L, (char *) (*b)->b_ffname); | |
481 else if (strncmp(s, "number", 6) == 0) | |
482 lua_pushinteger(L, (*b)->b_fnum); | |
483 /* methods */ | |
484 else if (strncmp(s, "insert", 6) == 0 | |
485 || strncmp(s, "next", 4) == 0 | |
486 || strncmp(s, "previous", 8) == 0 | |
487 || strncmp(s, "isvalid", 7) == 0) { | |
488 lua_getmetatable(L, 1); | |
489 lua_getfield(L, -1, s); | |
490 } | |
491 else lua_pushnil(L); | |
492 } | |
493 else lua_pushnil(L); | |
494 return 1; | |
495 } | |
496 | |
497 static int luaV_buffer_newindex (lua_State *L) { | |
498 luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1); | |
499 linenr_T n = (linenr_T) luaL_checkinteger(L, 2); | |
500 #ifdef HAVE_SANDBOX | |
501 luaV_checksandbox(L); | |
502 #endif | |
503 if (n < 1 || n > (*b)->b_ml.ml_line_count) | |
504 luaL_error(L, "invalid line number"); | |
505 if (lua_isnil(L, 3)) { /* delete line */ | |
506 buf_T *buf = curbuf; | |
507 curbuf = *b; | |
508 if (u_savedel(n, 1L) == FAIL) { | |
509 curbuf = buf; | |
510 luaL_error(L, "cannot save undo information"); | |
511 } | |
512 else if (ml_delete(n, FALSE) == FAIL) { | |
513 curbuf = buf; | |
514 luaL_error(L, "cannot delete line"); | |
515 } | |
516 else { | |
517 deleted_lines_mark(n, 1L); | |
518 if (*b == curwin->w_buffer) { /* fix cursor in current window? */ | |
519 if (curwin->w_cursor.lnum >= n) { | |
520 if (curwin->w_cursor.lnum > n) { | |
521 curwin->w_cursor.lnum -= 1; | |
522 check_cursor_col(); | |
523 } | |
524 else check_cursor(); | |
525 changed_cline_bef_curs(); | |
526 } | |
527 invalidate_botline(); | |
528 } | |
529 } | |
530 curbuf = buf; | |
531 } | |
532 else if (lua_isstring(L, 3)) { /* update line */ | |
533 buf_T *buf = curbuf; | |
534 curbuf = *b; | |
535 if (u_savesub(n) == FAIL) { | |
536 curbuf = buf; | |
537 luaL_error(L, "cannot save undo information"); | |
538 } | |
539 else if (ml_replace(n, luaV_toline(L, 3), TRUE) == FAIL) { | |
540 curbuf = buf; | |
541 luaL_error(L, "cannot replace line"); | |
542 } | |
543 else changed_bytes(n, 0); | |
544 curbuf = buf; | |
545 if (*b == curwin->w_buffer) | |
546 check_cursor_col(); | |
547 } | |
548 else | |
549 luaL_error(L, "wrong argument to change line"); | |
550 return 0; | |
551 } | |
552 | |
553 static int luaV_buffer_insert (lua_State *L) { | |
554 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); | |
555 linenr_T last = (*b)->b_ml.ml_line_count; | |
556 linenr_T n = (linenr_T) luaL_optinteger(L, 3, last); | |
557 buf_T *buf; | |
558 luaL_checktype(L, 2, LUA_TSTRING); | |
559 #ifdef HAVE_SANDBOX | |
560 luaV_checksandbox(L); | |
561 #endif | |
562 /* fix insertion line */ | |
563 if (n < 0) n = 0; | |
564 if (n > last) n = last; | |
565 /* insert */ | |
566 buf = curbuf; | |
567 curbuf = *b; | |
568 if (u_save(n, n + 1) == FAIL) { | |
569 curbuf = buf; | |
570 luaL_error(L, "cannot save undo information"); | |
571 } | |
572 else if (ml_append(n, luaV_toline(L, 2), 0, FALSE) == FAIL) { | |
573 curbuf = buf; | |
574 luaL_error(L, "cannot insert line"); | |
575 } | |
576 else | |
577 appended_lines_mark(n, 1L); | |
578 curbuf = buf; | |
579 update_screen(VALID); | |
580 return 0; | |
581 } | |
582 | |
583 static int luaV_buffer_next (lua_State *L) { | |
584 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); | |
585 luaV_pushbuffer(L, (*b)->b_next); | |
586 return 1; | |
587 } | |
588 | |
589 static int luaV_buffer_previous (lua_State *L) { | |
590 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); | |
591 luaV_pushbuffer(L, (*b)->b_prev); | |
592 return 1; | |
593 } | |
594 | |
595 static int luaV_buffer_isvalid (lua_State *L) { | |
596 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); | |
597 lua_pushlightuserdata(L, (void *) (*b)); | |
598 lua_rawget(L, LUA_ENVIRONINDEX); | |
599 lua_pushboolean(L, !lua_isnil(L, -1)); | |
600 return 1; | |
601 } | |
602 | |
603 static const luaL_Reg luaV_Buffer_mt[] = { | |
604 {"__tostring", luaV_buffer_tostring}, | |
605 {"__len", luaV_buffer_len}, | |
606 {"__call", luaV_buffer_call}, | |
607 {"__index", luaV_buffer_index}, | |
608 {"__newindex", luaV_buffer_newindex}, | |
609 {"insert", luaV_buffer_insert}, | |
610 {"next", luaV_buffer_next}, | |
611 {"previous", luaV_buffer_previous}, | |
612 {"isvalid", luaV_buffer_isvalid}, | |
613 {NULL, NULL} | |
614 }; | |
615 | |
616 | |
617 /* ======= Window type ======= */ | |
618 | |
619 static luaV_Window *luaV_newwindow (lua_State *L, win_T *win) { | |
620 luaV_Window *w = (luaV_Window *) lua_newuserdata(L, sizeof(luaV_Window)); | |
621 *w = win; | |
622 lua_pushlightuserdata(L, (void *) win); | |
623 lua_pushvalue(L, -2); | |
624 lua_rawset(L, LUA_ENVIRONINDEX); /* env[win] = udata */ | |
625 /* to avoid GC, store as key in env */ | |
626 lua_pushvalue(L, -1); | |
627 lua_pushboolean(L, 1); | |
628 lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = true */ | |
629 /* set metatable */ | |
630 luaV_getfield(L, LUAVIM_WINDOW); | |
631 lua_setmetatable(L, -2); | |
632 return w; | |
633 } | |
634 | |
635 static luaV_Window *luaV_pushwindow (lua_State *L, win_T *win) { | |
636 luaV_Window *w = NULL; | |
637 if (win == NULL) | |
638 lua_pushnil(L); | |
639 else { | |
640 lua_pushlightuserdata(L, (void *) win); | |
641 lua_rawget(L, LUA_ENVIRONINDEX); | |
642 if (lua_isnil(L, -1)) { /* not interned? */ | |
643 lua_pop(L, 1); | |
644 w = luaV_newwindow(L, win); | |
645 } | |
646 else w = (luaV_Window *) lua_touserdata(L, -1); | |
647 } | |
648 return w; | |
649 } | |
650 | |
651 /* Window metamethods */ | |
652 | |
653 static int luaV_window_tostring (lua_State *L) { | |
654 lua_pushfstring(L, "%s: %p", LUAVIM_WINDOW, lua_touserdata(L, 1)); | |
655 return 1; | |
656 } | |
657 | |
658 static int luaV_window_call (lua_State *L) { | |
659 luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1); | |
660 lua_settop(L, 1); | |
661 win_goto(*w); | |
662 return 1; | |
663 } | |
664 | |
665 static int luaV_window_index (lua_State *L) { | |
666 luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1); | |
667 const char *s = luaL_checkstring(L, 2); | |
668 if (strncmp(s, "buffer", 6) == 0) | |
669 luaV_pushbuffer(L, (*w)->w_buffer); | |
670 else if (strncmp(s, "line", 4) == 0) | |
671 lua_pushinteger(L, (*w)->w_cursor.lnum); | |
672 else if (strncmp(s, "col", 3) == 0) | |
673 lua_pushinteger(L, (*w)->w_cursor.col + 1); | |
674 #ifdef FEAT_VERTSPLIT | |
675 else if (strncmp(s, "width", 5) == 0) | |
676 lua_pushinteger(L, W_WIDTH((*w))); | |
677 #endif | |
678 else if (strncmp(s, "height", 6) == 0) | |
679 lua_pushinteger(L, (*w)->w_height); | |
680 /* methods */ | |
681 else if (strncmp(s, "next", 4) == 0 | |
682 || strncmp(s, "previous", 8) == 0 | |
683 || strncmp(s, "isvalid", 7) == 0) { | |
684 lua_getmetatable(L, 1); | |
685 lua_getfield(L, -1, s); | |
686 } | |
687 else | |
688 lua_pushnil(L); | |
689 return 1; | |
690 } | |
691 | |
692 static int luaV_window_newindex (lua_State *L) { | |
693 luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1); | |
694 const char *s = luaL_checkstring(L, 2); | |
695 int v = luaL_checkinteger(L, 3); | |
696 if (strncmp(s, "line", 4) == 0) { | |
697 #ifdef HAVE_SANDBOX | |
698 luaV_checksandbox(L); | |
699 #endif | |
700 if (v < 1 || v > (*w)->w_buffer->b_ml.ml_line_count) | |
701 luaL_error(L, "line out of range"); | |
702 (*w)->w_cursor.lnum = v; | |
703 update_screen(VALID); | |
704 } | |
705 else if (strncmp(s, "col", 3) == 0) { | |
706 #ifdef HAVE_SANDBOX | |
707 luaV_checksandbox(L); | |
708 #endif | |
709 (*w)->w_cursor.col = v - 1; | |
710 update_screen(VALID); | |
711 } | |
712 #ifdef FEAT_VERTSPLIT | |
713 else if (strncmp(s, "width", 5) == 0) { | |
714 win_T *win = curwin; | |
715 #ifdef FEAT_GUI | |
716 need_mouse_correct = TRUE; | |
717 #endif | |
718 curwin = *w; | |
719 win_setwidth(v); | |
720 curwin = win; | |
721 } | |
722 #endif | |
723 else if (strncmp(s, "height", 6) == 0) { | |
724 win_T *win = curwin; | |
725 #ifdef FEAT_GUI | |
726 need_mouse_correct = TRUE; | |
727 #endif | |
728 curwin = *w; | |
729 win_setheight(v); | |
730 curwin = win; | |
731 } | |
732 else | |
733 luaL_error(L, "invalid window property: `%s'", s); | |
734 return 0; | |
735 } | |
736 | |
737 static int luaV_window_next (lua_State *L) { | |
738 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); | |
739 luaV_pushwindow(L, (*w)->w_next); | |
740 return 1; | |
741 } | |
742 | |
743 static int luaV_window_previous (lua_State *L) { | |
744 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); | |
745 luaV_pushwindow(L, (*w)->w_prev); | |
746 return 1; | |
747 } | |
748 | |
749 static int luaV_window_isvalid (lua_State *L) { | |
750 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); | |
751 lua_pushlightuserdata(L, (void *) (*w)); | |
752 lua_rawget(L, LUA_ENVIRONINDEX); | |
753 lua_pushboolean(L, !lua_isnil(L, -1)); | |
754 return 1; | |
755 } | |
756 | |
757 static const luaL_Reg luaV_Window_mt[] = { | |
758 {"__tostring", luaV_window_tostring}, | |
759 {"__call", luaV_window_call}, | |
760 {"__index", luaV_window_index}, | |
761 {"__newindex", luaV_window_newindex}, | |
762 {"next", luaV_window_next}, | |
763 {"previous", luaV_window_previous}, | |
764 {"isvalid", luaV_window_isvalid}, | |
765 {NULL, NULL} | |
766 }; | |
767 | |
768 | |
769 /* ======= Vim module ======= */ | |
770 | |
771 static int luaV_print (lua_State *L) { | |
772 int i, n = lua_gettop(L); /* nargs */ | |
773 const char *s; | |
774 size_t l; | |
775 luaL_Buffer b; | |
776 luaL_buffinit(L, &b); | |
777 lua_getglobal(L, "tostring"); | |
778 for (i = 1; i <= n; i++) { | |
779 lua_pushvalue(L, -1); /* tostring */ | |
780 lua_pushvalue(L, i); /* arg */ | |
781 lua_call(L, 1, 1); | |
782 s = lua_tolstring(L, -1, &l); | |
783 if (s == NULL) | |
784 return luaL_error(L, "cannot convert to string"); | |
785 if (i > 1) luaL_addchar(&b, ' '); /* use space instead of tab */ | |
786 luaV_addlstring(&b, s, l, 0); | |
787 lua_pop(L, 1); | |
788 } | |
789 luaL_pushresult(&b); | |
790 luaV_msg(L); | |
791 return 0; | |
792 } | |
793 | |
794 static int luaV_command (lua_State *L) { | |
795 do_cmdline_cmd((char_u *) luaL_checkstring(L, 1)); | |
796 update_screen(VALID); | |
797 return 0; | |
798 } | |
799 | |
800 static int luaV_eval (lua_State *L) { | |
801 typval_T *tv = eval_expr((char_u *) luaL_checkstring(L, 1), NULL); | |
802 if (tv == NULL) luaL_error(L, "invalid expression"); | |
803 luaV_pushtypval(L, tv); | |
804 return 1; | |
805 } | |
806 | |
807 static int luaV_beep (lua_State *L) { | |
808 vim_beep(); | |
809 return 0; | |
810 } | |
811 | |
812 static int luaV_line (lua_State *L) { | |
813 luaV_pushline(L, curbuf, curwin->w_cursor.lnum); | |
814 return 1; | |
815 } | |
816 | |
817 static int luaV_buffer (lua_State *L) { | |
818 buf_T *buf; | |
819 if (lua_isstring(L, 1)) { /* get by number or name? */ | |
820 if (lua_isnumber(L, 1)) { /* by number? */ | |
821 int n = lua_tointeger(L, 1); | |
822 for (buf = firstbuf; buf != NULL; buf = buf->b_next) | |
823 if (buf->b_fnum == n) break; | |
824 } | |
825 else { /* by name */ | |
826 size_t l; | |
827 const char *s = lua_tolstring(L, 1, &l); | |
828 for (buf = firstbuf; buf != NULL; buf = buf->b_next) { | |
829 if (buf->b_ffname == NULL || buf->b_sfname == NULL) { | |
830 if (l == 0) break; | |
831 } | |
832 else if (strncmp(s, buf->b_ffname, l) == 0 | |
833 || strncmp(s, buf->b_sfname, l) == 0) | |
834 break; | |
835 } | |
836 } | |
837 if (buf == NULL) /* not found? */ | |
838 lua_pushnil(L); | |
839 else | |
840 luaV_pushbuffer(L, buf); | |
841 } | |
842 else { | |
843 buf = (lua_toboolean(L, 1)) ? firstbuf : curbuf; /* first buffer? */ | |
844 luaV_pushbuffer(L, buf); | |
845 } | |
846 return 1; | |
847 } | |
848 | |
849 static int luaV_window (lua_State *L) { | |
850 win_T *win; | |
851 if (lua_isnumber(L, 1)) { /* get by number? */ | |
852 int n = lua_tointeger(L, 1); | |
853 for (win = firstwin; win != NULL; win = win->w_next, n--) | |
854 if (n == 1) break; | |
855 if (win == NULL) /* not found? */ | |
856 lua_pushnil(L); | |
857 else | |
858 luaV_pushwindow(L, win); | |
859 } | |
860 else { | |
861 win = (lua_toboolean(L, 1)) ? firstwin : curwin; /* first window? */ | |
862 luaV_pushwindow(L, win); | |
863 } | |
864 return 1; | |
865 } | |
866 | |
867 static int luaV_open (lua_State *L) { | |
868 luaV_Buffer *b; | |
869 char_u *s = NULL; | |
870 #ifdef HAVE_SANDBOX | |
871 luaV_checksandbox(L); | |
872 #endif | |
873 if (lua_isstring(L, 1)) s = (char_u *) lua_tostring(L, 1); | |
874 b = luaV_pushbuffer(L, buflist_new(s, NULL, 1L, BLN_LISTED)); | |
875 return 1; | |
876 } | |
877 | |
878 static int luaV_isbuffer (lua_State *L) { | |
879 lua_pushboolean(L, luaV_toudata(L, 1, LUAVIM_BUFFER) != NULL); | |
880 return 1; | |
881 } | |
882 | |
883 static int luaV_iswindow (lua_State *L) { | |
884 lua_pushboolean(L, luaV_toudata(L, 1, LUAVIM_WINDOW) != NULL); | |
885 return 1; | |
886 } | |
887 | |
888 /* for freeing buffer and window objects; lightuserdata as arg */ | |
889 static luaV_free (lua_State *L) { | |
890 lua_pushvalue(L, 1); /* lightudata */ | |
891 lua_rawget(L, LUA_ENVIRONINDEX); | |
892 if (!lua_isnil(L, -1)) { | |
893 lua_pushnil(L); | |
894 lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = nil */ | |
895 lua_pushnil(L); | |
896 lua_rawset(L, LUA_ENVIRONINDEX); /* env[lightudata] = nil */ | |
897 } | |
898 return 0; | |
899 } | |
900 | |
901 static const luaL_Reg luaV_module[] = { | |
902 {"command", luaV_command}, | |
903 {"eval", luaV_eval}, | |
904 {"beep", luaV_beep}, | |
905 {"line", luaV_line}, | |
906 {"buffer", luaV_buffer}, | |
907 {"window", luaV_window}, | |
908 {"open", luaV_open}, | |
909 {"isbuffer", luaV_isbuffer}, | |
910 {"iswindow", luaV_iswindow}, | |
911 {NULL, NULL} | |
912 }; | |
913 | |
914 static int luaopen_vim (lua_State *L) { | |
915 /* set environment */ | |
916 lua_newtable(L); | |
917 lua_newtable(L); | |
918 lua_pushliteral(L, "v"); | |
919 lua_setfield(L, -2, "__mode"); | |
920 lua_setmetatable(L, -2); | |
921 lua_replace(L, LUA_ENVIRONINDEX); | |
922 /* print */ | |
923 lua_pushcfunction(L, luaV_print); | |
924 lua_setglobal(L, "print"); | |
925 /* free */ | |
926 lua_pushlightuserdata(L, (void *) LUAVIM_FREE); | |
927 lua_pushcfunction(L, luaV_free); | |
928 lua_rawset(L, LUA_REGISTRYINDEX); | |
929 /* register */ | |
930 luaV_newmetatable(L, LUAVIM_BUFFER); | |
931 luaL_register(L, NULL, luaV_Buffer_mt); | |
932 luaV_newmetatable(L, LUAVIM_WINDOW); | |
933 luaL_register(L, NULL, luaV_Window_mt); | |
934 luaL_register(L, LUAVIM_NAME, luaV_module); | |
935 return 0; | |
936 } | |
937 | |
938 static lua_State *luaV_newstate (void) { | |
939 lua_State *L = luaL_newstate(); | |
940 const luaL_Reg luaV_core_libs[] = { | |
941 {"", luaopen_base}, | |
942 {LUA_TABLIBNAME, luaopen_table}, | |
943 {LUA_STRLIBNAME, luaopen_string}, | |
944 {LUA_MATHLIBNAME, luaopen_math}, | |
945 {LUA_OSLIBNAME, luaopen_os}, /* restricted */ | |
946 {LUA_LOADLIBNAME, luaopen_package}, | |
947 {LUA_DBLIBNAME, luaopen_debug}, | |
948 {NULL, NULL} | |
949 }; | |
950 const char *os_funcs[] = { | |
951 "date", "clock", "time", "difftime", "getenv", NULL | |
952 }; | |
953 const luaL_Reg *reg = luaV_core_libs; | |
954 const char **s = os_funcs; | |
955 /* core libs */ | |
956 for ( ; reg->func; reg++) { | |
957 lua_pushcfunction(L, reg->func); | |
958 lua_pushstring(L, reg->name); | |
959 lua_call(L, 1, 0); | |
960 } | |
961 /* restricted os lib */ | |
962 lua_getglobal(L, LUA_OSLIBNAME); | |
963 lua_newtable(L); | |
964 for ( ; *s; s++) { | |
965 lua_getfield(L, -2, *s); | |
966 lua_setfield(L, -2, *s); | |
967 } | |
968 lua_setglobal(L, LUA_OSLIBNAME); | |
969 lua_pop(L, 1); /* os table */ | |
970 /* vim */ | |
971 lua_pushcfunction(L, luaopen_vim); | |
972 lua_call(L, 0, 0); | |
973 return L; | |
974 } | |
975 | |
976 static void luaV_setrange (lua_State *L, int line1, int line2) { | |
977 lua_getglobal(L, LUAVIM_NAME); | |
978 lua_pushinteger(L, line1); | |
979 lua_setfield(L, -2, "firstline"); | |
980 lua_pushinteger(L, line2); | |
981 lua_setfield(L, -2, "lastline"); | |
982 lua_pop(L, 1); /* vim table */ | |
983 } | |
984 | |
985 | |
986 /* ======= Interface ======= */ | |
987 | |
988 static lua_State *L = NULL; | |
989 | |
990 static int lua_init (void) { | |
991 if (L == NULL) { | |
992 #ifdef DYNAMIC_LUA | |
993 if (!lua_enabled(TRUE)) { | |
994 EMSG(_("Lua library cannot be loaded.")); | |
995 return FAIL; | |
996 } | |
997 #endif | |
998 L = luaV_newstate(); | |
999 } | |
1000 return OK; | |
1001 } | |
1002 | |
1003 void lua_end (void) { | |
1004 if (L != NULL) { | |
1005 lua_close(L); | |
1006 L = NULL; | |
1007 #ifdef DYNAMIC_LUA | |
1008 end_dynamic_lua(); | |
1009 #endif | |
1010 } | |
1011 } | |
1012 | |
1013 /* ex commands */ | |
1014 void ex_lua (exarg_T *eap) { | |
1015 char *script; | |
1016 if (lua_init() == FAIL) return; | |
1017 script = (char *) script_get(eap, eap->arg); | |
1018 if (!eap->skip) { | |
1019 char *s = (script) ? script : (char *) eap->arg; | |
1020 luaV_setrange(L, eap->line1, eap->line2); | |
1021 if (luaL_loadbuffer(L, s, strlen(s), LUAVIM_CHUNKNAME) | |
1022 || lua_pcall(L, 0, 0, 0)) | |
1023 luaV_emsg(L); | |
1024 } | |
1025 if (script != NULL) vim_free(script); | |
1026 } | |
1027 | |
1028 void ex_luado (exarg_T *eap) { | |
1029 linenr_T l; | |
1030 const char *s = (const char *) eap->arg; | |
1031 luaL_Buffer b; | |
1032 size_t len; | |
1033 if (lua_init() == FAIL) return; | |
1034 if (u_save(eap->line1 - 1, eap->line2 + 1) == FAIL) { | |
1035 EMSG(_("cannot save undo information")); | |
1036 return; | |
1037 } | |
1038 luaV_setrange(L, eap->line1, eap->line2); | |
1039 luaL_buffinit(L, &b); | |
1040 luaL_addlstring(&b, "return function(line) ", 22); /* header */ | |
1041 luaL_addlstring(&b, s, strlen(s)); | |
1042 luaL_addlstring(&b, " end", 4); /* footer */ | |
1043 luaL_pushresult(&b); | |
1044 s = lua_tolstring(L, -1, &len); | |
1045 if (luaL_loadbuffer(L, s, len, LUAVIM_CHUNKNAME)) { | |
1046 luaV_emsg(L); | |
1047 lua_pop(L, 1); /* function body */ | |
1048 return; | |
1049 } | |
1050 lua_call(L, 0, 1); | |
1051 lua_replace(L, -2); /* function -> body */ | |
1052 for (l = eap->line1; l <= eap->line2; l++) { | |
1053 lua_pushvalue(L, -1); /* function */ | |
1054 luaV_pushline(L, curbuf, l); /* current line as arg */ | |
1055 if (lua_pcall(L, 1, 1, 0)) { | |
1056 luaV_emsg(L); | |
1057 break; | |
1058 } | |
1059 if (lua_isstring(L, -1)) { /* update line? */ | |
1060 #ifdef HAVE_SANDBOX | |
1061 luaV_checksandbox(L); | |
1062 #endif | |
1063 ml_replace(l, luaV_toline(L, -1), TRUE); | |
1064 changed_bytes(l, 0); | |
1065 lua_pop(L, 1); /* result from luaV_toline */ | |
1066 } | |
1067 lua_pop(L, 1); /* line */ | |
1068 } | |
1069 lua_pop(L, 1); /* function */ | |
1070 check_cursor(); | |
1071 update_screen(NOT_VALID); | |
1072 } | |
1073 | |
1074 void ex_luafile (exarg_T *eap) { | |
1075 if (lua_init() == FAIL) return; | |
1076 if (!eap->skip) { | |
1077 luaV_setrange(L, eap->line1, eap->line2); | |
1078 if (luaL_loadfile(L, (char *) eap->arg) || lua_pcall(L, 0, 0, 0)) | |
1079 luaV_emsg(L); | |
1080 } | |
1081 } | |
1082 | |
1083 /* buffer */ | |
1084 void lua_buffer_free (buf_T *buf) { | |
1085 if (lua_init() == FAIL) return; | |
1086 luaV_getfield(L, LUAVIM_FREE); | |
1087 lua_pushlightuserdata(L, (void *) buf); | |
1088 lua_call(L, 1, 0); | |
1089 } | |
1090 | |
1091 /* window */ | |
1092 void lua_window_free (win_T *win) { | |
1093 if (lua_init() == FAIL) return; | |
1094 luaV_getfield(L, LUAVIM_FREE); | |
1095 lua_pushlightuserdata(L, (void *) win); | |
1096 lua_call(L, 1, 0); | |
1097 } | |
1098 | |
1099 #endif |