1 /* vi:set ts=8 sts=4 sw=4:
3 * VIM - Vi IMproved by Bram Moolenaar
5 * Lua interface by Luis Carvalho
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.
19 /* Only do the following when the feature is enabled. Needed for "make
21 #if defined(FEAT_LUA) || defined(PROTO)
23 #define LUAVIM_CHUNKNAME "vim chunk"
24 #define LUAVIM_NAME "vim"
26 typedef buf_T
*luaV_Buffer
;
27 typedef win_T
*luaV_Window
;
28 typedef void (*msgfunc_T
)(char_u
*);
30 static const char LUAVIM_BUFFER
[] = "buffer";
31 static const char LUAVIM_WINDOW
[] = "window";
32 static const char LUAVIM_FREE
[] = "luaV_free";
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)
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
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
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
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
);
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
);
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
);
162 typedef void **luaV_function
;
168 static const luaV_Reg luaV_dll
[] = {
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
},
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
},
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
},
230 static HINSTANCE hinstLua
= 0;
232 static void end_dynamic_lua (void) {
234 FreeLibrary(hinstLua
);
239 static int lua_link_init (char *libname
, int verbose
) {
241 if (hinstLua
) return OK
;
242 hinstLua
= LoadLibrary(libname
);
244 if (verbose
) EMSG2(_(e_loadlib
), libname
);
247 for (reg
= luaV_dll
; reg
->func
; reg
++) {
248 if ((*reg
->func
= GetProcAddress(hinstLua
, reg
->name
)) == NULL
) {
249 FreeLibrary(hinstLua
);
251 if (verbose
) EMSG2(_(e_loadfunc
), reg
->name
);
258 int lua_enabled (int verbose
) {
259 return lua_link_init(DYNAMIC_LUA_DLL
, verbose
) == OK
;
262 #endif /* DYNAMIC_LUA */
265 /* ======= Internal ======= */
267 static void luaV_newmetatable (lua_State
*L
, const char *tname
) {
269 lua_pushlightuserdata(L
, (void *) tname
);
270 lua_pushvalue(L
, -2);
271 lua_rawset(L
, LUA_REGISTRYINDEX
);
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 */
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
);
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
) {
298 lua_pushstring(L
, (char *) tv
->vval
.v_string
);
301 lua_pushinteger(L
, (int) tv
->vval
.v_number
);
305 lua_pushnumber(L
, (lua_Number
) tv
->vval
.v_float
);
309 list_T
*l
= tv
->vval
.v_list
;
312 lua_pushlightuserdata(L
, (void *) l
);
313 lua_rawget(L
, LUA_ENVIRONINDEX
);
314 if (lua_isnil(L
, -1)) { /* not interned? */
317 lua_pop(L
, 1); /* nil */
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
);
332 dict_T
*d
= tv
->vval
.v_dict
;
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
;
340 int n
= ht
->ht_used
; /* remaining items */
341 lua_pop(L
, 1); /* nil */
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
);
360 luaL_error(L
, "invalid type");
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
,
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
);
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
);
379 luaL_buffinit(L
, &b
);
380 luaV_addlstring(&b
, s
, strlen(s
), 0);
384 static char_u
*luaV_toline (lua_State
*L
, int pos
) {
386 const char *s
= lua_tolstring(L
, pos
, &l
);
388 luaL_buffinit(L
, &b
);
389 luaV_addlstring(&b
, s
, l
, 1);
391 return (char_u
*) lua_tostring(L
, -1);
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
) {
399 const char *p
, *s
= lua_tolstring(L
, -1, &l
);
400 luaL_buffinit(L
, &b
);
401 luaV_addlstring(&b
, s
, l
, 0);
404 p
= s
= lua_tolstring(L
, -1, &l
);
406 if (*p
++ == '\0') { /* break? */
412 lua_pop(L
, 2); /* original and modified strings */
416 /* ======= Buffer type ======= */
418 static luaV_Buffer
*luaV_newbuffer (lua_State
*L
, buf_T
*buf
) {
419 luaV_Buffer
*b
= (luaV_Buffer
*) lua_newuserdata(L
, sizeof(luaV_Buffer
));
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 */
429 luaV_getfield(L
, LUAVIM_BUFFER
);
430 lua_setmetatable(L
, -2);
434 static luaV_Buffer
*luaV_pushbuffer (lua_State
*L
, buf_T
*buf
) {
435 luaV_Buffer
*b
= NULL
;
439 lua_pushlightuserdata(L
, (void *) buf
);
440 lua_rawget(L
, LUA_ENVIRONINDEX
);
441 if (lua_isnil(L
, -1)) { /* not interned? */
443 b
= luaV_newbuffer(L
, buf
);
445 else b
= (luaV_Buffer
*) lua_touserdata(L
, -1);
450 /* Buffer metamethods */
452 static int luaV_buffer_tostring (lua_State
*L
) {
453 lua_pushfstring(L
, "%s: %p", LUAVIM_BUFFER
, lua_touserdata(L
, 1));
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
);
463 static int luaV_buffer_call (lua_State
*L
) {
464 luaV_Buffer
*b
= (luaV_Buffer
*) lua_touserdata(L
, 1);
466 set_curbuf(*b
, DOBUF_SPLIT
);
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
);
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
);
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);
501 luaV_checksandbox(L
);
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 */
508 if (u_savedel(n
, 1L) == FAIL
) {
510 luaL_error(L
, "cannot save undo information");
512 else if (ml_delete(n
, FALSE
) == FAIL
) {
514 luaL_error(L
, "cannot delete line");
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;
525 changed_cline_bef_curs();
527 invalidate_botline();
532 else if (lua_isstring(L
, 3)) { /* update line */
535 if (u_savesub(n
) == FAIL
) {
537 luaL_error(L
, "cannot save undo information");
539 else if (ml_replace(n
, luaV_toline(L
, 3), TRUE
) == FAIL
) {
541 luaL_error(L
, "cannot replace line");
543 else changed_bytes(n
, 0);
545 if (*b
== curwin
->w_buffer
)
549 luaL_error(L
, "wrong argument to change line");
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
);
558 luaL_checktype(L
, 2, LUA_TSTRING
);
560 luaV_checksandbox(L
);
562 /* fix insertion line */
564 if (n
> last
) n
= last
;
568 if (u_save(n
, n
+ 1) == FAIL
) {
570 luaL_error(L
, "cannot save undo information");
572 else if (ml_append(n
, luaV_toline(L
, 2), 0, FALSE
) == FAIL
) {
574 luaL_error(L
, "cannot insert line");
577 appended_lines_mark(n
, 1L);
579 update_screen(VALID
);
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
);
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
);
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));
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
},
617 /* ======= Window type ======= */
619 static luaV_Window
*luaV_newwindow (lua_State
*L
, win_T
*win
) {
620 luaV_Window
*w
= (luaV_Window
*) lua_newuserdata(L
, sizeof(luaV_Window
));
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 */
630 luaV_getfield(L
, LUAVIM_WINDOW
);
631 lua_setmetatable(L
, -2);
635 static luaV_Window
*luaV_pushwindow (lua_State
*L
, win_T
*win
) {
636 luaV_Window
*w
= NULL
;
640 lua_pushlightuserdata(L
, (void *) win
);
641 lua_rawget(L
, LUA_ENVIRONINDEX
);
642 if (lua_isnil(L
, -1)) { /* not interned? */
644 w
= luaV_newwindow(L
, win
);
646 else w
= (luaV_Window
*) lua_touserdata(L
, -1);
651 /* Window metamethods */
653 static int luaV_window_tostring (lua_State
*L
) {
654 lua_pushfstring(L
, "%s: %p", LUAVIM_WINDOW
, lua_touserdata(L
, 1));
658 static int luaV_window_call (lua_State
*L
) {
659 luaV_Window
*w
= (luaV_Window
*) lua_touserdata(L
, 1);
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
)));
678 else if (strncmp(s
, "height", 6) == 0)
679 lua_pushinteger(L
, (*w
)->w_height
);
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
);
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) {
698 luaV_checksandbox(L
);
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
);
705 else if (strncmp(s
, "col", 3) == 0) {
707 luaV_checksandbox(L
);
709 (*w
)->w_cursor
.col
= v
- 1;
710 update_screen(VALID
);
712 #ifdef FEAT_VERTSPLIT
713 else if (strncmp(s
, "width", 5) == 0) {
716 need_mouse_correct
= TRUE
;
723 else if (strncmp(s
, "height", 6) == 0) {
726 need_mouse_correct
= TRUE
;
733 luaL_error(L
, "invalid window property: `%s'", s
);
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
);
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
);
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));
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
},
769 /* ======= Vim module ======= */
771 static int luaV_print (lua_State
*L
) {
772 int i
, n
= lua_gettop(L
); /* nargs */
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 */
782 s
= lua_tolstring(L
, -1, &l
);
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);
794 static int luaV_command (lua_State
*L
) {
795 do_cmdline_cmd((char_u
*) luaL_checkstring(L
, 1));
796 update_screen(VALID
);
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
);
807 static int luaV_beep (lua_State
*L
) {
812 static int luaV_line (lua_State
*L
) {
813 luaV_pushline(L
, curbuf
, curwin
->w_cursor
.lnum
);
817 static int luaV_buffer (lua_State
*L
) {
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;
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
) {
832 else if (strncmp(s
, buf
->b_ffname
, l
) == 0
833 || strncmp(s
, buf
->b_sfname
, l
) == 0)
837 if (buf
== NULL
) /* not found? */
840 luaV_pushbuffer(L
, buf
);
843 buf
= (lua_toboolean(L
, 1)) ? firstbuf
: curbuf
; /* first buffer? */
844 luaV_pushbuffer(L
, buf
);
849 static int luaV_window (lua_State
*L
) {
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
--)
855 if (win
== NULL
) /* not found? */
858 luaV_pushwindow(L
, win
);
861 win
= (lua_toboolean(L
, 1)) ? firstwin
: curwin
; /* first window? */
862 luaV_pushwindow(L
, win
);
867 static int luaV_open (lua_State
*L
) {
871 luaV_checksandbox(L
);
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
));
878 static int luaV_isbuffer (lua_State
*L
) {
879 lua_pushboolean(L
, luaV_toudata(L
, 1, LUAVIM_BUFFER
) != NULL
);
883 static int luaV_iswindow (lua_State
*L
) {
884 lua_pushboolean(L
, luaV_toudata(L
, 1, LUAVIM_WINDOW
) != NULL
);
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)) {
894 lua_rawset(L
, LUA_ENVIRONINDEX
); /* env[udata] = nil */
896 lua_rawset(L
, LUA_ENVIRONINDEX
); /* env[lightudata] = nil */
901 static const luaL_Reg luaV_module
[] = {
902 {"command", luaV_command
},
906 {"buffer", luaV_buffer
},
907 {"window", luaV_window
},
909 {"isbuffer", luaV_isbuffer
},
910 {"iswindow", luaV_iswindow
},
914 static int luaopen_vim (lua_State
*L
) {
915 /* set environment */
918 lua_pushliteral(L
, "v");
919 lua_setfield(L
, -2, "__mode");
920 lua_setmetatable(L
, -2);
921 lua_replace(L
, LUA_ENVIRONINDEX
);
923 lua_pushcfunction(L
, luaV_print
);
924 lua_setglobal(L
, "print");
926 lua_pushlightuserdata(L
, (void *) LUAVIM_FREE
);
927 lua_pushcfunction(L
, luaV_free
);
928 lua_rawset(L
, LUA_REGISTRYINDEX
);
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
);
938 static lua_State
*luaV_newstate (void) {
939 lua_State
*L
= luaL_newstate();
940 const luaL_Reg luaV_core_libs
[] = {
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
},
950 const char *os_funcs
[] = {
951 "date", "clock", "time", "difftime", "getenv", NULL
953 const luaL_Reg
*reg
= luaV_core_libs
;
954 const char **s
= os_funcs
;
956 for ( ; reg
->func
; reg
++) {
957 lua_pushcfunction(L
, reg
->func
);
958 lua_pushstring(L
, reg
->name
);
961 /* restricted os lib */
962 lua_getglobal(L
, LUA_OSLIBNAME
);
965 lua_getfield(L
, -2, *s
);
966 lua_setfield(L
, -2, *s
);
968 lua_setglobal(L
, LUA_OSLIBNAME
);
969 lua_pop(L
, 1); /* os table */
971 lua_pushcfunction(L
, luaopen_vim
);
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 */
986 /* ======= Interface ======= */
988 static lua_State
*L
= NULL
;
990 static int lua_init (void) {
993 if (!lua_enabled(TRUE
)) {
994 EMSG(_("Lua library cannot be loaded."));
1003 void lua_end (void) {
1014 void ex_lua (exarg_T
*eap
) {
1016 if (lua_init() == FAIL
) return;
1017 script
= (char *) script_get(eap
, eap
->arg
);
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))
1025 if (script
!= NULL
) vim_free(script
);
1028 void ex_luado (exarg_T
*eap
) {
1030 const char *s
= (const char *) eap
->arg
;
1033 if (lua_init() == FAIL
) return;
1034 if (u_save(eap
->line1
- 1, eap
->line2
+ 1) == FAIL
) {
1035 EMSG(_("cannot save undo information"));
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
)) {
1047 lua_pop(L
, 1); /* function body */
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)) {
1059 if (lua_isstring(L
, -1)) { /* update line? */
1061 luaV_checksandbox(L
);
1063 ml_replace(l
, luaV_toline(L
, -1), TRUE
);
1064 changed_bytes(l
, 0);
1065 lua_pop(L
, 1); /* result from luaV_toline */
1067 lua_pop(L
, 1); /* line */
1069 lua_pop(L
, 1); /* function */
1071 update_screen(NOT_VALID
);
1074 void ex_luafile (exarg_T
*eap
) {
1075 if (lua_init() == FAIL
) return;
1077 luaV_setrange(L
, eap
->line1
, eap
->line2
);
1078 if (luaL_loadfile(L
, (char *) eap
->arg
) || lua_pcall(L
, 0, 0, 0))
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
);
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
);