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 "vim.h" 13 14 #include <lua.h> 15 #include <lualib.h> 16 #include <lauxlib.h> 17 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 25 typedef buf_T *luaV_Buffer; 26 typedef win_T *luaV_Window; 27 typedef void (*msgfunc_T)(char_u *); 28 29 static const char LUAVIM_BUFFER[] = "buffer"; 30 static const char LUAVIM_WINDOW[] = "window"; 31 static 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 43 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 51 # define load_dll vimLoadLib 52 # define symbol_from_dll GetProcAddress 53 # define close_dll FreeLibrary 54 #endif 55 56 /* 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 111 #define luaopen_io dll_luaopen_io 112 #define luaopen_os dll_luaopen_os 113 #define luaopen_package dll_luaopen_package 114 #define luaopen_debug dll_luaopen_debug 115 #define luaL_openlibs dll_luaL_openlibs 116 117 /* lauxlib */ 118 void (*dll_luaL_register) (lua_State *L, const char *libname, const luaL_Reg *l); 119 int (*dll_luaL_typerror) (lua_State *L, int narg, const char *tname); 120 const char *(*dll_luaL_checklstring) (lua_State *L, int numArg, size_t *l); 121 lua_Integer (*dll_luaL_checkinteger) (lua_State *L, int numArg); 122 lua_Integer (*dll_luaL_optinteger) (lua_State *L, int nArg, lua_Integer def); 123 void (*dll_luaL_checktype) (lua_State *L, int narg, int t); 124 int (*dll_luaL_error) (lua_State *L, const char *fmt, ...); 125 int (*dll_luaL_loadfile) (lua_State *L, const char *filename); 126 int (*dll_luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, const char *name); 127 lua_State *(*dll_luaL_newstate) (void); 128 void (*dll_luaL_buffinit) (lua_State *L, luaL_Buffer *B); 129 char *(*dll_luaL_prepbuffer) (luaL_Buffer *B); 130 void (*dll_luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); 131 void (*dll_luaL_pushresult) (luaL_Buffer *B); 132 /* lua */ 133 void (*dll_lua_close) (lua_State *L); 134 int (*dll_lua_gettop) (lua_State *L); 135 void (*dll_lua_settop) (lua_State *L, int idx); 136 void (*dll_lua_pushvalue) (lua_State *L, int idx); 137 void (*dll_lua_replace) (lua_State *L, int idx); 138 int (*dll_lua_isnumber) (lua_State *L, int idx); 139 int (*dll_lua_isstring) (lua_State *L, int idx); 140 int (*dll_lua_type) (lua_State *L, int idx); 141 int (*dll_lua_rawequal) (lua_State *L, int idx1, int idx2); 142 lua_Number (*dll_lua_tonumber) (lua_State *L, int idx); 143 lua_Integer (*dll_lua_tointeger) (lua_State *L, int idx); 144 int (*dll_lua_toboolean) (lua_State *L, int idx); 145 const char *(*dll_lua_tolstring) (lua_State *L, int idx, size_t *len); 146 void *(*dll_lua_touserdata) (lua_State *L, int idx); 147 void (*dll_lua_pushnil) (lua_State *L); 148 void (*dll_lua_pushnumber) (lua_State *L, lua_Number n); 149 void (*dll_lua_pushinteger) (lua_State *L, lua_Integer n); 150 void (*dll_lua_pushlstring) (lua_State *L, const char *s, size_t l); 151 void (*dll_lua_pushstring) (lua_State *L, const char *s); 152 const char *(*dll_lua_pushfstring) (lua_State *L, const char *fmt, ...); 153 void (*dll_lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); 154 void (*dll_lua_pushboolean) (lua_State *L, int b); 155 void (*dll_lua_pushlightuserdata) (lua_State *L, void *p); 156 void (*dll_lua_getfield) (lua_State *L, int idx, const char *k); 157 void (*dll_lua_rawget) (lua_State *L, int idx); 158 void (*dll_lua_createtable) (lua_State *L, int narr, int nrec); 159 void *(*dll_lua_newuserdata) (lua_State *L, size_t sz); 160 int (*dll_lua_getmetatable) (lua_State *L, int objindex); 161 void (*dll_lua_setfield) (lua_State *L, int idx, const char *k); 162 void (*dll_lua_rawset) (lua_State *L, int idx); 163 void (*dll_lua_rawseti) (lua_State *L, int idx, int n); 164 int (*dll_lua_setmetatable) (lua_State *L, int objindex); 165 void (*dll_lua_call) (lua_State *L, int nargs, int nresults); 166 int (*dll_lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); 167 /* libs */ 168 int (*dll_luaopen_base) (lua_State *L); 169 int (*dll_luaopen_table) (lua_State *L); 170 int (*dll_luaopen_string) (lua_State *L); 171 int (*dll_luaopen_math) (lua_State *L); 172 int (*dll_luaopen_io) (lua_State *L); 173 int (*dll_luaopen_os) (lua_State *L); 174 int (*dll_luaopen_package) (lua_State *L); 175 int (*dll_luaopen_debug) (lua_State *L); 176 void (*dll_luaL_openlibs) (lua_State *L); 177 178 typedef void **luaV_function; 179 typedef struct { 180 const char *name; 181 luaV_function func; 182 } luaV_Reg; 183 184 static 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}, 240 {"luaopen_io", (luaV_function) &dll_luaopen_io}, 241 {"luaopen_os", (luaV_function) &dll_luaopen_os}, 242 {"luaopen_package", (luaV_function) &dll_luaopen_package}, 243 {"luaopen_debug", (luaV_function) &dll_luaopen_debug}, 244 {"luaL_openlibs", (luaV_function) &dll_luaL_openlibs}, 245 {NULL, NULL} 246 }; 247 248 static HANDLE hinstLua = NULL; 249 250 static void 251 end_dynamic_lua(void) 252 { 253 if (hinstLua) 254 { 255 close_dll(hinstLua); 256 hinstLua = 0; 257 } 258 } 259 260 static int 261 lua_link_init(char *libname, int verbose) 262 { 263 const luaV_Reg *reg; 264 if (hinstLua) return OK; 265 hinstLua = load_dll(libname); 266 if (!hinstLua) 267 { 268 if (verbose) 269 EMSG2(_(e_loadlib), libname); 270 return FAIL; 271 } 272 for (reg = luaV_dll; reg->func; reg++) 273 { 274 if ((*reg->func = symbol_from_dll(hinstLua, reg->name)) == NULL) 275 { 276 close_dll(hinstLua); 277 hinstLua = 0; 278 if (verbose) 279 EMSG2(_(e_loadfunc), reg->name); 280 return FAIL; 281 } 282 } 283 return OK; 284 } 285 286 int 287 lua_enabled(int verbose) 288 { 289 return lua_link_init(DYNAMIC_LUA_DLL, verbose) == OK; 290 } 291 292 #endif /* DYNAMIC_LUA */ 293 294 295 /* ======= Internal ======= */ 296 297 static void 298 luaV_newmetatable(lua_State *L, const char *tname) 299 { 300 lua_newtable(L); 301 lua_pushlightuserdata(L, (void *) tname); 302 lua_pushvalue(L, -2); 303 lua_rawset(L, LUA_REGISTRYINDEX); 304 } 305 306 static void * 307 luaV_toudata(lua_State *L, int ud, const char *tname) 308 { 309 void *p = lua_touserdata(L, ud); 310 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 } 322 } 323 return NULL; 324 } 325 326 static void * 327 luaV_checkudata(lua_State *L, int ud, const char *tname) 328 { 329 void *p = luaV_toudata(L, ud, tname); 330 if (p == NULL) luaL_typerror(L, ud, tname); 331 return p; 332 } 333 334 static void 335 luaV_pushtypval(lua_State *L, typval_T *tv) 336 { 337 if (tv == NULL) luaL_error(L, "null type"); 338 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; 346 #ifdef FEAT_FLOAT 347 case VAR_FLOAT: 348 lua_pushnumber(L, (lua_Number) tv->vval.v_float); 349 break; 350 #endif 351 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); 386 if (lua_isnil(L, -1)) /* not interned? */ 387 { 388 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"); 413 } 414 } 415 416 /* similar to luaL_addlstring, but replaces \0 with \n if toline and 417 * \n with \0 otherwise */ 418 static void 419 luaV_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++; 430 } 431 } 432 433 static void 434 luaV_pushline(lua_State *L, buf_T *buf, linenr_T n) 435 { 436 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 443 static char_u * 444 luaV_toline(lua_State *L, int pos) 445 { 446 size_t l; 447 const char *s = lua_tolstring(L, pos, &l); 448 449 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 */ 458 static void 459 luaV_msgfunc(lua_State *L, msgfunc_T mf) 460 { 461 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); 469 while (l--) 470 { 471 if (*p++ == '\0') /* break? */ 472 { 473 mf((char_u *) s); 474 s = p; 475 } 476 } 477 mf((char_u *) s); 478 lua_pop(L, 2); /* original and modified strings */ 479 } 480 481 482 /* ======= Buffer type ======= */ 483 484 static luaV_Buffer * 485 luaV_newbuffer(lua_State *L, buf_T *buf) 486 { 487 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 502 static luaV_Buffer * 503 luaV_pushbuffer (lua_State *L, buf_T *buf) 504 { 505 luaV_Buffer *b = NULL; 506 if (buf == NULL) 507 lua_pushnil(L); 508 else { 509 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); 518 } 519 return b; 520 } 521 522 /* Buffer metamethods */ 523 524 static int 525 luaV_buffer_tostring(lua_State *L) 526 { 527 lua_pushfstring(L, "%s: %p", LUAVIM_BUFFER, lua_touserdata(L, 1)); 528 return 1; 529 } 530 531 static int 532 luaV_buffer_len(lua_State *L) 533 { 534 luaV_Buffer *b = lua_touserdata(L, 1); 535 lua_pushinteger(L, (*b)->b_ml.ml_line_count); 536 return 1; 537 } 538 539 static int 540 luaV_buffer_call(lua_State *L) 541 { 542 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 548 static int 549 luaV_buffer_index(lua_State *L) 550 { 551 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) 554 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); 575 } 576 else 577 lua_pushnil(L); 578 return 1; 579 } 580 581 static int 582 luaV_buffer_newindex(lua_State *L) 583 { 584 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) 590 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; 623 } 624 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(); 642 } 643 else 644 luaL_error(L, "wrong argument to change line"); 645 return 0; 646 } 647 648 static int 649 luaV_buffer_insert(lua_State *L) 650 { 651 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; 665 if (u_save(n, n + 1) == FAIL) 666 { 667 curbuf = buf; 668 luaL_error(L, "cannot save undo information"); 669 } 670 else if (ml_append(n, luaV_toline(L, 2), 0, FALSE) == FAIL) 671 { 672 curbuf = buf; 673 luaL_error(L, "cannot insert line"); 674 } 675 else 676 appended_lines_mark(n, 1L); 677 curbuf = buf; 678 update_screen(VALID); 679 return 0; 680 } 681 682 static int 683 luaV_buffer_next(lua_State *L) 684 { 685 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); 686 luaV_pushbuffer(L, (*b)->b_next); 687 return 1; 688 } 689 690 static int 691 luaV_buffer_previous(lua_State *L) 692 { 693 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); 694 luaV_pushbuffer(L, (*b)->b_prev); 695 return 1; 696 } 697 698 static int 699 luaV_buffer_isvalid(lua_State *L) 700 { 701 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 708 static 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 724 static luaV_Window * 725 luaV_newwindow(lua_State *L, win_T *win) 726 { 727 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 742 static luaV_Window * 743 luaV_pushwindow(lua_State *L, win_T *win) 744 { 745 luaV_Window *w = NULL; 746 if (win == NULL) 747 lua_pushnil(L); 748 else { 749 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); 757 } 758 return w; 759 } 760 761 /* Window metamethods */ 762 763 static int 764 luaV_window_tostring(lua_State *L) 765 { 766 lua_pushfstring(L, "%s: %p", LUAVIM_WINDOW, lua_touserdata(L, 1)); 767 return 1; 768 } 769 770 static int 771 luaV_window_call(lua_State *L) 772 { 773 luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1); 774 lua_settop(L, 1); 775 win_goto(*w); 776 return 1; 777 } 778 779 static int 780 luaV_window_index(lua_State *L) 781 { 782 luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1); 783 const char *s = luaL_checkstring(L, 2); 784 if (strncmp(s, "buffer", 6) == 0) 785 luaV_pushbuffer(L, (*w)->w_buffer); 786 else if (strncmp(s, "line", 4) == 0) 787 lua_pushinteger(L, (*w)->w_cursor.lnum); 788 else if (strncmp(s, "col", 3) == 0) 789 lua_pushinteger(L, (*w)->w_cursor.col + 1); 790 #ifdef FEAT_VERTSPLIT 791 else if (strncmp(s, "width", 5) == 0) 792 lua_pushinteger(L, W_WIDTH((*w))); 793 #endif 794 else if (strncmp(s, "height", 6) == 0) 795 lua_pushinteger(L, (*w)->w_height); 796 /* methods */ 797 else if (strncmp(s, "next", 4) == 0 798 || strncmp(s, "previous", 8) == 0 799 || strncmp(s, "isvalid", 7) == 0) 800 { 801 lua_getmetatable(L, 1); 802 lua_getfield(L, -1, s); 803 } 804 else 805 lua_pushnil(L); 806 return 1; 807 } 808 809 static int 810 luaV_window_newindex (lua_State *L) 811 { 812 luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1); 813 const char *s = luaL_checkstring(L, 2); 814 int v = luaL_checkinteger(L, 3); 815 if (strncmp(s, "line", 4) == 0) 816 { 817 #ifdef HAVE_SANDBOX 818 luaV_checksandbox(L); 819 #endif 820 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); 824 } 825 else if (strncmp(s, "col", 3) == 0) 826 { 827 #ifdef HAVE_SANDBOX 828 luaV_checksandbox(L); 829 #endif 830 (*w)->w_cursor.col = v - 1; 831 update_screen(VALID); 832 } 833 #ifdef FEAT_VERTSPLIT 834 else if (strncmp(s, "width", 5) == 0) 835 { 836 win_T *win = curwin; 837 #ifdef FEAT_GUI 838 need_mouse_correct = TRUE; 839 #endif 840 curwin = *w; 841 win_setwidth(v); 842 curwin = win; 843 } 844 #endif 845 else if (strncmp(s, "height", 6) == 0) 846 { 847 win_T *win = curwin; 848 #ifdef FEAT_GUI 849 need_mouse_correct = TRUE; 850 #endif 851 curwin = *w; 852 win_setheight(v); 853 curwin = win; 854 } 855 else 856 luaL_error(L, "invalid window property: `%s'", s); 857 return 0; 858 } 859 860 static int 861 luaV_window_next(lua_State *L) 862 { 863 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); 864 luaV_pushwindow(L, (*w)->w_next); 865 return 1; 866 } 867 868 static int 869 luaV_window_previous(lua_State *L) 870 { 871 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); 872 luaV_pushwindow(L, (*w)->w_prev); 873 return 1; 874 } 875 876 static int 877 luaV_window_isvalid(lua_State *L) 878 { 879 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 886 static 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 900 static int 901 luaV_print(lua_State *L) 902 { 903 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"); 909 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); 920 } 921 luaL_pushresult(&b); 922 luaV_msg(L); 923 return 0; 924 } 925 926 static int 927 luaV_command(lua_State *L) 928 { 929 do_cmdline_cmd((char_u *) luaL_checkstring(L, 1)); 930 update_screen(VALID); 931 return 0; 932 } 933 934 static int 935 luaV_eval(lua_State *L) 936 { 937 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 943 static int 944 luaV_beep(lua_State *L UNUSED) 945 { 946 vim_beep(); 947 return 0; 948 } 949 950 static int 951 luaV_line(lua_State *L) 952 { 953 luaV_pushline(L, curbuf, curwin->w_cursor.lnum); 954 return 1; 955 } 956 957 static int 958 luaV_buffer(lua_State *L) 959 { 960 buf_T *buf; 961 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 } 978 else if (strncmp(s, (char *)buf->b_ffname, l) == 0 979 || strncmp(s, (char *)buf->b_sfname, l) == 0) 980 break; 981 } 982 } 983 if (buf == NULL) /* not found? */ 984 lua_pushnil(L); 985 else 986 luaV_pushbuffer(L, buf); 987 } 988 else { 989 buf = (lua_toboolean(L, 1)) ? firstbuf : curbuf; /* first buffer? */ 990 luaV_pushbuffer(L, buf); 991 } 992 return 1; 993 } 994 995 static int 996 luaV_window(lua_State *L) 997 { 998 win_T *win; 999 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); 1008 } 1009 else { 1010 win = (lua_toboolean(L, 1)) ? firstwin : curwin; /* first window? */ 1011 luaV_pushwindow(L, win); 1012 } 1013 return 1; 1014 } 1015 1016 static int 1017 luaV_open(lua_State *L) 1018 { 1019 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 1029 static int 1030 luaV_isbuffer(lua_State *L) 1031 { 1032 lua_pushboolean(L, luaV_toudata(L, 1, LUAVIM_BUFFER) != NULL); 1033 return 1; 1034 } 1035 1036 static int 1037 luaV_iswindow(lua_State *L) 1038 { 1039 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 */ 1044 static int 1045 luaV_free(lua_State *L) 1046 { 1047 lua_pushvalue(L, 1); /* lightudata */ 1048 lua_rawget(L, LUA_ENVIRONINDEX); 1049 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 */ 1055 } 1056 return 0; 1057 } 1058 1059 static 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 1072 static int 1073 luaopen_vim(lua_State *L) 1074 { 1075 /* 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 1098 static lua_State * 1099 luaV_newstate(void) 1100 { 1101 lua_State *L = luaL_newstate(); 1102 luaL_openlibs(L); /* core libs */ 1103 lua_pushcfunction(L, luaopen_vim); /* vim */ 1104 lua_call(L, 0, 0); 1105 return L; 1106 } 1107 1108 static void 1109 luaV_setrange(lua_State *L, int line1, int line2) 1110 { 1111 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 1122 static lua_State *L = NULL; 1123 1124 static int 1125 lua_is_open(void) 1126 { 1127 return L != NULL; 1128 } 1129 1130 static int 1131 lua_init(void) 1132 { 1133 if (L == NULL) 1134 { 1135 #ifdef DYNAMIC_LUA 1136 if (!lua_enabled(TRUE)) 1137 { 1138 EMSG(_("Lua library cannot be loaded.")); 1139 return FAIL; 1140 } 1141 #endif 1142 L = luaV_newstate(); 1143 } 1144 return OK; 1145 } 1146 1147 void 1148 lua_end(void) 1149 { 1150 if (L != NULL) 1151 { 1152 lua_close(L); 1153 L = NULL; 1154 #ifdef DYNAMIC_LUA 1155 end_dynamic_lua(); 1156 #endif 1157 } 1158 } 1159 1160 /* ex commands */ 1161 void 1162 ex_lua(exarg_T *eap) 1163 { 1164 char *script; 1165 if (lua_init() == FAIL) return; 1166 script = (char *) script_get(eap, eap->arg); 1167 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); 1174 } 1175 if (script != NULL) vim_free(script); 1176 } 1177 1178 void 1179 ex_luado(exarg_T *eap) 1180 { 1181 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; 1186 if (u_save(eap->line1 - 1, eap->line2 + 1) == FAIL) 1187 { 1188 EMSG(_("cannot save undo information")); 1189 return; 1190 } 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); 1198 if (luaL_loadbuffer(L, s, len, LUAVIM_CHUNKNAME)) 1199 { 1200 luaV_emsg(L); 1201 lua_pop(L, 1); /* function body */ 1202 return; 1203 } 1204 lua_call(L, 0, 1); 1205 lua_replace(L, -2); /* function -> body */ 1206 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 { 1217 #ifdef HAVE_SANDBOX 1218 luaV_checksandbox(L); 1219 #endif 1220 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 */ 1225 } 1226 lua_pop(L, 1); /* function */ 1227 check_cursor(); 1228 update_screen(NOT_VALID); 1229 } 1230 1231 void 1232 ex_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); 1241 } 1242 } 1243 1244 /* buffer */ 1245 void 1246 lua_buffer_free(buf_T *buf) 1247 { 1248 if (!lua_is_open()) return; 1249 luaV_getfield(L, LUAVIM_FREE); 1250 lua_pushlightuserdata(L, (void *) buf); 1251 lua_call(L, 1, 0); 1252 } 1253 1254 /* window */ 1255 void 1256 lua_window_free(win_T *win) 1257 { 1258 if (!lua_is_open()) return; 1259 luaV_getfield(L, LUAVIM_FREE); 1260 lua_pushlightuserdata(L, (void *) win); 1261 lua_call(L, 1, 0); 1262 } 1263 1264 #endif 1265