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 233 end_dynamic_lua(void) 234 { 235 if (hinstLua) 236 { 237 FreeLibrary(hinstLua); 238 hinstLua = 0; 239 } 240 } 241 242 static int 243 lua_link_init(char *libname, int verbose) 244 { 245 const luaV_Reg *reg; 246 if (hinstLua) return OK; 247 hinstLua = LoadLibrary(libname); 248 if (!hinstLua) 249 { 250 if (verbose) 251 EMSG2(_(e_loadlib), libname); 252 return FAIL; 253 } 254 for (reg = luaV_dll; reg->func; reg++) 255 { 256 if ((*reg->func = GetProcAddress(hinstLua, reg->name)) == NULL) { 257 FreeLibrary(hinstLua); 258 hinstLua = 0; 259 if (verbose) 260 EMSG2(_(e_loadfunc), reg->name); 261 return FAIL; 262 } 263 } 264 return OK; 265 } 266 267 int 268 lua_enabled(int verbose) 269 { 270 return lua_link_init(DYNAMIC_LUA_DLL, verbose) == OK; 271 } 272 273 #endif /* DYNAMIC_LUA */ 274 275 276 /* ======= Internal ======= */ 277 278 static void 279 luaV_newmetatable(lua_State *L, const char *tname) 280 { 281 lua_newtable(L); 282 lua_pushlightuserdata(L, (void *) tname); 283 lua_pushvalue(L, -2); 284 lua_rawset(L, LUA_REGISTRYINDEX); 285 } 286 287 static void * 288 luaV_toudata(lua_State *L, int ud, const char *tname) 289 { 290 void *p = lua_touserdata(L, ud); 291 292 if (p != NULL) /* value is userdata? */ 293 { 294 if (lua_getmetatable(L, ud)) /* does it have a metatable? */ 295 { 296 luaV_getfield(L, tname); /* get metatable */ 297 if (lua_rawequal(L, -1, -2)) /* MTs match? */ 298 { 299 lua_pop(L, 2); /* MTs */ 300 return p; 301 } 302 } 303 } 304 return NULL; 305 } 306 307 static void * 308 luaV_checkudata(lua_State *L, int ud, const char *tname) 309 { 310 void *p = luaV_toudata(L, ud, tname); 311 if (p == NULL) luaL_typerror(L, ud, tname); 312 return p; 313 } 314 315 static void 316 luaV_pushtypval(lua_State *L, typval_T *tv) 317 { 318 if (tv == NULL) luaL_error(L, "null type"); 319 switch (tv->v_type) 320 { 321 case VAR_STRING: 322 lua_pushstring(L, (char *) tv->vval.v_string); 323 break; 324 case VAR_NUMBER: 325 lua_pushinteger(L, (int) tv->vval.v_number); 326 break; 327 #ifdef FEAT_FLOAT 328 case VAR_FLOAT: 329 lua_pushnumber(L, (lua_Number) tv->vval.v_float); 330 break; 331 #endif 332 case VAR_LIST: { 333 list_T *l = tv->vval.v_list; 334 335 if (l != NULL) 336 { 337 /* check cache */ 338 lua_pushlightuserdata(L, (void *) l); 339 lua_rawget(L, LUA_ENVIRONINDEX); 340 if (lua_isnil(L, -1)) /* not interned? */ 341 { 342 listitem_T *li; 343 int n = 0; 344 lua_pop(L, 1); /* nil */ 345 lua_newtable(L); 346 lua_pushlightuserdata(L, (void *) l); 347 lua_pushvalue(L, -2); 348 lua_rawset(L, LUA_ENVIRONINDEX); 349 for (li = l->lv_first; li != NULL; li = li->li_next) 350 { 351 luaV_pushtypval(L, &li->li_tv); 352 lua_rawseti(L, -2, ++n); 353 } 354 } 355 } 356 else lua_pushnil(L); 357 break; 358 } 359 case VAR_DICT: { 360 dict_T *d = tv->vval.v_dict; 361 362 if (d != NULL) 363 { 364 /* check cache */ 365 lua_pushlightuserdata(L, (void *) d); 366 lua_rawget(L, LUA_ENVIRONINDEX); 367 if (lua_isnil(L, -1)) { /* not interned? */ 368 hashtab_T *ht = &d->dv_hashtab; 369 hashitem_T *hi; 370 int n = ht->ht_used; /* remaining items */ 371 lua_pop(L, 1); /* nil */ 372 lua_newtable(L); 373 lua_pushlightuserdata(L, (void *) d); 374 lua_pushvalue(L, -2); 375 lua_rawset(L, LUA_ENVIRONINDEX); 376 for (hi = ht->ht_array; n > 0; hi++) 377 { 378 if (!HASHITEM_EMPTY(hi)) 379 { 380 dictitem_T *di = dict_lookup(hi); 381 luaV_pushtypval(L, &di->di_tv); 382 lua_setfield(L, -2, (char *) hi->hi_key); 383 n--; 384 } 385 } 386 } 387 } 388 else lua_pushnil(L); 389 break; 390 } 391 default: 392 luaL_error(L, "invalid type"); 393 } 394 } 395 396 /* similar to luaL_addlstring, but replaces \0 with \n if toline and 397 * \n with \0 otherwise */ 398 static void 399 luaV_addlstring(luaL_Buffer *b, const char *s, size_t l, int toline) 400 { 401 while (l--) 402 { 403 if (*s == '\0' && toline) 404 luaL_addchar(b, '\n'); 405 else if (*s == '\n' && !toline) 406 luaL_addchar(b, '\0'); 407 else 408 luaL_addchar(b, *s); 409 s++; 410 } 411 } 412 413 static void 414 luaV_pushline(lua_State *L, buf_T *buf, linenr_T n) 415 { 416 const char *s = (const char *) ml_get_buf(buf, n, FALSE); 417 luaL_Buffer b; 418 luaL_buffinit(L, &b); 419 luaV_addlstring(&b, s, strlen(s), 0); 420 luaL_pushresult(&b); 421 } 422 423 static char_u * 424 luaV_toline(lua_State *L, int pos) 425 { 426 size_t l; 427 const char *s = lua_tolstring(L, pos, &l); 428 429 luaL_Buffer b; 430 luaL_buffinit(L, &b); 431 luaV_addlstring(&b, s, l, 1); 432 luaL_pushresult(&b); 433 return (char_u *) lua_tostring(L, -1); 434 } 435 436 /* pops a string s from the top of the stack and calls mf(t) for pieces t of 437 * s separated by newlines */ 438 static void 439 luaV_msgfunc(lua_State *L, msgfunc_T mf) 440 { 441 luaL_Buffer b; 442 size_t l; 443 const char *p, *s = lua_tolstring(L, -1, &l); 444 luaL_buffinit(L, &b); 445 luaV_addlstring(&b, s, l, 0); 446 luaL_pushresult(&b); 447 /* break string */ 448 p = s = lua_tolstring(L, -1, &l); 449 while (l--) 450 { 451 if (*p++ == '\0') /* break? */ 452 { 453 mf((char_u *) s); 454 s = p; 455 } 456 } 457 mf((char_u *) s); 458 lua_pop(L, 2); /* original and modified strings */ 459 } 460 461 462 /* ======= Buffer type ======= */ 463 464 static luaV_Buffer * 465 luaV_newbuffer(lua_State *L, buf_T *buf) 466 { 467 luaV_Buffer *b = (luaV_Buffer *) lua_newuserdata(L, sizeof(luaV_Buffer)); 468 *b = buf; 469 lua_pushlightuserdata(L, (void *) buf); 470 lua_pushvalue(L, -2); 471 lua_rawset(L, LUA_ENVIRONINDEX); /* env[buf] = udata */ 472 /* to avoid GC, store as key in env */ 473 lua_pushvalue(L, -1); 474 lua_pushboolean(L, 1); 475 lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = true */ 476 /* set metatable */ 477 luaV_getfield(L, LUAVIM_BUFFER); 478 lua_setmetatable(L, -2); 479 return b; 480 } 481 482 static luaV_Buffer * 483 luaV_pushbuffer (lua_State *L, buf_T *buf) 484 { 485 luaV_Buffer *b = NULL; 486 if (buf == NULL) 487 lua_pushnil(L); 488 else { 489 lua_pushlightuserdata(L, (void *) buf); 490 lua_rawget(L, LUA_ENVIRONINDEX); 491 if (lua_isnil(L, -1)) /* not interned? */ 492 { 493 lua_pop(L, 1); 494 b = luaV_newbuffer(L, buf); 495 } 496 else 497 b = (luaV_Buffer *) lua_touserdata(L, -1); 498 } 499 return b; 500 } 501 502 /* Buffer metamethods */ 503 504 static int 505 luaV_buffer_tostring(lua_State *L) 506 { 507 lua_pushfstring(L, "%s: %p", LUAVIM_BUFFER, lua_touserdata(L, 1)); 508 return 1; 509 } 510 511 static int 512 luaV_buffer_len(lua_State *L) 513 { 514 luaV_Buffer *b = lua_touserdata(L, 1); 515 lua_pushinteger(L, (*b)->b_ml.ml_line_count); 516 return 1; 517 } 518 519 static int 520 luaV_buffer_call(lua_State *L) 521 { 522 luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1); 523 lua_settop(L, 1); 524 set_curbuf(*b, DOBUF_SPLIT); 525 return 1; 526 } 527 528 static int 529 luaV_buffer_index(lua_State *L) 530 { 531 luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1); 532 linenr_T n = (linenr_T) lua_tointeger(L, 2); 533 if (n > 0 && n <= (*b)->b_ml.ml_line_count) 534 luaV_pushline(L, *b, n); 535 else if (lua_isstring(L, 2)) 536 { 537 const char *s = lua_tostring(L, 2); 538 if (strncmp(s, "name", 4) == 0) 539 lua_pushstring(L, (char *) (*b)->b_sfname); 540 else if (strncmp(s, "fname", 5) == 0) 541 lua_pushstring(L, (char *) (*b)->b_ffname); 542 else if (strncmp(s, "number", 6) == 0) 543 lua_pushinteger(L, (*b)->b_fnum); 544 /* methods */ 545 else if (strncmp(s, "insert", 6) == 0 546 || strncmp(s, "next", 4) == 0 547 || strncmp(s, "previous", 8) == 0 548 || strncmp(s, "isvalid", 7) == 0) 549 { 550 lua_getmetatable(L, 1); 551 lua_getfield(L, -1, s); 552 } 553 else 554 lua_pushnil(L); 555 } 556 else 557 lua_pushnil(L); 558 return 1; 559 } 560 561 static int 562 luaV_buffer_newindex(lua_State *L) 563 { 564 luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1); 565 linenr_T n = (linenr_T) luaL_checkinteger(L, 2); 566 #ifdef HAVE_SANDBOX 567 luaV_checksandbox(L); 568 #endif 569 if (n < 1 || n > (*b)->b_ml.ml_line_count) 570 luaL_error(L, "invalid line number"); 571 if (lua_isnil(L, 3)) /* delete line */ 572 { 573 buf_T *buf = curbuf; 574 curbuf = *b; 575 if (u_savedel(n, 1L) == FAIL) 576 { 577 curbuf = buf; 578 luaL_error(L, "cannot save undo information"); 579 } 580 else if (ml_delete(n, FALSE) == FAIL) 581 { 582 curbuf = buf; 583 luaL_error(L, "cannot delete line"); 584 } 585 else { 586 deleted_lines_mark(n, 1L); 587 if (*b == curwin->w_buffer) /* fix cursor in current window? */ 588 { 589 if (curwin->w_cursor.lnum >= n) 590 { 591 if (curwin->w_cursor.lnum > n) 592 { 593 curwin->w_cursor.lnum -= 1; 594 check_cursor_col(); 595 } 596 else check_cursor(); 597 changed_cline_bef_curs(); 598 } 599 invalidate_botline(); 600 } 601 } 602 curbuf = buf; 603 } 604 else if (lua_isstring(L, 3)) /* update line */ 605 { 606 buf_T *buf = curbuf; 607 curbuf = *b; 608 if (u_savesub(n) == FAIL) 609 { 610 curbuf = buf; 611 luaL_error(L, "cannot save undo information"); 612 } 613 else if (ml_replace(n, luaV_toline(L, 3), TRUE) == FAIL) 614 { 615 curbuf = buf; 616 luaL_error(L, "cannot replace line"); 617 } 618 else changed_bytes(n, 0); 619 curbuf = buf; 620 if (*b == curwin->w_buffer) 621 check_cursor_col(); 622 } 623 else 624 luaL_error(L, "wrong argument to change line"); 625 return 0; 626 } 627 628 static int 629 luaV_buffer_insert(lua_State *L) 630 { 631 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); 632 linenr_T last = (*b)->b_ml.ml_line_count; 633 linenr_T n = (linenr_T) luaL_optinteger(L, 3, last); 634 buf_T *buf; 635 luaL_checktype(L, 2, LUA_TSTRING); 636 #ifdef HAVE_SANDBOX 637 luaV_checksandbox(L); 638 #endif 639 /* fix insertion line */ 640 if (n < 0) n = 0; 641 if (n > last) n = last; 642 /* insert */ 643 buf = curbuf; 644 curbuf = *b; 645 if (u_save(n, n + 1) == FAIL) 646 { 647 curbuf = buf; 648 luaL_error(L, "cannot save undo information"); 649 } 650 else if (ml_append(n, luaV_toline(L, 2), 0, FALSE) == FAIL) 651 { 652 curbuf = buf; 653 luaL_error(L, "cannot insert line"); 654 } 655 else 656 appended_lines_mark(n, 1L); 657 curbuf = buf; 658 update_screen(VALID); 659 return 0; 660 } 661 662 static int 663 luaV_buffer_next(lua_State *L) 664 { 665 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); 666 luaV_pushbuffer(L, (*b)->b_next); 667 return 1; 668 } 669 670 static int 671 luaV_buffer_previous(lua_State *L) 672 { 673 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); 674 luaV_pushbuffer(L, (*b)->b_prev); 675 return 1; 676 } 677 678 static int 679 luaV_buffer_isvalid(lua_State *L) 680 { 681 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); 682 lua_pushlightuserdata(L, (void *) (*b)); 683 lua_rawget(L, LUA_ENVIRONINDEX); 684 lua_pushboolean(L, !lua_isnil(L, -1)); 685 return 1; 686 } 687 688 static const luaL_Reg luaV_Buffer_mt[] = { 689 {"__tostring", luaV_buffer_tostring}, 690 {"__len", luaV_buffer_len}, 691 {"__call", luaV_buffer_call}, 692 {"__index", luaV_buffer_index}, 693 {"__newindex", luaV_buffer_newindex}, 694 {"insert", luaV_buffer_insert}, 695 {"next", luaV_buffer_next}, 696 {"previous", luaV_buffer_previous}, 697 {"isvalid", luaV_buffer_isvalid}, 698 {NULL, NULL} 699 }; 700 701 702 /* ======= Window type ======= */ 703 704 static luaV_Window * 705 luaV_newwindow(lua_State *L, win_T *win) 706 { 707 luaV_Window *w = (luaV_Window *) lua_newuserdata(L, sizeof(luaV_Window)); 708 *w = win; 709 lua_pushlightuserdata(L, (void *) win); 710 lua_pushvalue(L, -2); 711 lua_rawset(L, LUA_ENVIRONINDEX); /* env[win] = udata */ 712 /* to avoid GC, store as key in env */ 713 lua_pushvalue(L, -1); 714 lua_pushboolean(L, 1); 715 lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = true */ 716 /* set metatable */ 717 luaV_getfield(L, LUAVIM_WINDOW); 718 lua_setmetatable(L, -2); 719 return w; 720 } 721 722 static luaV_Window * 723 luaV_pushwindow(lua_State *L, win_T *win) 724 { 725 luaV_Window *w = NULL; 726 if (win == NULL) 727 lua_pushnil(L); 728 else { 729 lua_pushlightuserdata(L, (void *) win); 730 lua_rawget(L, LUA_ENVIRONINDEX); 731 if (lua_isnil(L, -1)) /* not interned? */ 732 { 733 lua_pop(L, 1); 734 w = luaV_newwindow(L, win); 735 } 736 else w = (luaV_Window *) lua_touserdata(L, -1); 737 } 738 return w; 739 } 740 741 /* Window metamethods */ 742 743 static int 744 luaV_window_tostring(lua_State *L) 745 { 746 lua_pushfstring(L, "%s: %p", LUAVIM_WINDOW, lua_touserdata(L, 1)); 747 return 1; 748 } 749 750 static int 751 luaV_window_call(lua_State *L) 752 { 753 luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1); 754 lua_settop(L, 1); 755 win_goto(*w); 756 return 1; 757 } 758 759 static int 760 luaV_window_index(lua_State *L) 761 { 762 luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1); 763 const char *s = luaL_checkstring(L, 2); 764 if (strncmp(s, "buffer", 6) == 0) 765 luaV_pushbuffer(L, (*w)->w_buffer); 766 else if (strncmp(s, "line", 4) == 0) 767 lua_pushinteger(L, (*w)->w_cursor.lnum); 768 else if (strncmp(s, "col", 3) == 0) 769 lua_pushinteger(L, (*w)->w_cursor.col + 1); 770 #ifdef FEAT_VERTSPLIT 771 else if (strncmp(s, "width", 5) == 0) 772 lua_pushinteger(L, W_WIDTH((*w))); 773 #endif 774 else if (strncmp(s, "height", 6) == 0) 775 lua_pushinteger(L, (*w)->w_height); 776 /* methods */ 777 else if (strncmp(s, "next", 4) == 0 778 || strncmp(s, "previous", 8) == 0 779 || strncmp(s, "isvalid", 7) == 0) 780 { 781 lua_getmetatable(L, 1); 782 lua_getfield(L, -1, s); 783 } 784 else 785 lua_pushnil(L); 786 return 1; 787 } 788 789 static int 790 luaV_window_newindex (lua_State *L) 791 { 792 luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1); 793 const char *s = luaL_checkstring(L, 2); 794 int v = luaL_checkinteger(L, 3); 795 if (strncmp(s, "line", 4) == 0) 796 { 797 #ifdef HAVE_SANDBOX 798 luaV_checksandbox(L); 799 #endif 800 if (v < 1 || v > (*w)->w_buffer->b_ml.ml_line_count) 801 luaL_error(L, "line out of range"); 802 (*w)->w_cursor.lnum = v; 803 update_screen(VALID); 804 } 805 else if (strncmp(s, "col", 3) == 0) 806 { 807 #ifdef HAVE_SANDBOX 808 luaV_checksandbox(L); 809 #endif 810 (*w)->w_cursor.col = v - 1; 811 update_screen(VALID); 812 } 813 #ifdef FEAT_VERTSPLIT 814 else if (strncmp(s, "width", 5) == 0) 815 { 816 win_T *win = curwin; 817 #ifdef FEAT_GUI 818 need_mouse_correct = TRUE; 819 #endif 820 curwin = *w; 821 win_setwidth(v); 822 curwin = win; 823 } 824 #endif 825 else if (strncmp(s, "height", 6) == 0) 826 { 827 win_T *win = curwin; 828 #ifdef FEAT_GUI 829 need_mouse_correct = TRUE; 830 #endif 831 curwin = *w; 832 win_setheight(v); 833 curwin = win; 834 } 835 else 836 luaL_error(L, "invalid window property: `%s'", s); 837 return 0; 838 } 839 840 static int 841 luaV_window_next(lua_State *L) 842 { 843 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); 844 luaV_pushwindow(L, (*w)->w_next); 845 return 1; 846 } 847 848 static int 849 luaV_window_previous(lua_State *L) 850 { 851 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); 852 luaV_pushwindow(L, (*w)->w_prev); 853 return 1; 854 } 855 856 static int 857 luaV_window_isvalid(lua_State *L) 858 { 859 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); 860 lua_pushlightuserdata(L, (void *) (*w)); 861 lua_rawget(L, LUA_ENVIRONINDEX); 862 lua_pushboolean(L, !lua_isnil(L, -1)); 863 return 1; 864 } 865 866 static const luaL_Reg luaV_Window_mt[] = { 867 {"__tostring", luaV_window_tostring}, 868 {"__call", luaV_window_call}, 869 {"__index", luaV_window_index}, 870 {"__newindex", luaV_window_newindex}, 871 {"next", luaV_window_next}, 872 {"previous", luaV_window_previous}, 873 {"isvalid", luaV_window_isvalid}, 874 {NULL, NULL} 875 }; 876 877 878 /* ======= Vim module ======= */ 879 880 static int 881 luaV_print(lua_State *L) 882 { 883 int i, n = lua_gettop(L); /* nargs */ 884 const char *s; 885 size_t l; 886 luaL_Buffer b; 887 luaL_buffinit(L, &b); 888 lua_getglobal(L, "tostring"); 889 for (i = 1; i <= n; i++) 890 { 891 lua_pushvalue(L, -1); /* tostring */ 892 lua_pushvalue(L, i); /* arg */ 893 lua_call(L, 1, 1); 894 s = lua_tolstring(L, -1, &l); 895 if (s == NULL) 896 return luaL_error(L, "cannot convert to string"); 897 if (i > 1) luaL_addchar(&b, ' '); /* use space instead of tab */ 898 luaV_addlstring(&b, s, l, 0); 899 lua_pop(L, 1); 900 } 901 luaL_pushresult(&b); 902 luaV_msg(L); 903 return 0; 904 } 905 906 static int 907 luaV_command(lua_State *L) 908 { 909 do_cmdline_cmd((char_u *) luaL_checkstring(L, 1)); 910 update_screen(VALID); 911 return 0; 912 } 913 914 static int 915 luaV_eval(lua_State *L) 916 { 917 typval_T *tv = eval_expr((char_u *) luaL_checkstring(L, 1), NULL); 918 if (tv == NULL) luaL_error(L, "invalid expression"); 919 luaV_pushtypval(L, tv); 920 return 1; 921 } 922 923 static int 924 luaV_beep(lua_State *L UNUSED) 925 { 926 vim_beep(); 927 return 0; 928 } 929 930 static int 931 luaV_line(lua_State *L) 932 { 933 luaV_pushline(L, curbuf, curwin->w_cursor.lnum); 934 return 1; 935 } 936 937 static int 938 luaV_buffer(lua_State *L) 939 { 940 buf_T *buf; 941 if (lua_isstring(L, 1)) /* get by number or name? */ 942 { 943 if (lua_isnumber(L, 1)) /* by number? */ 944 { 945 int n = lua_tointeger(L, 1); 946 for (buf = firstbuf; buf != NULL; buf = buf->b_next) 947 if (buf->b_fnum == n) break; 948 } 949 else { /* by name */ 950 size_t l; 951 const char *s = lua_tolstring(L, 1, &l); 952 for (buf = firstbuf; buf != NULL; buf = buf->b_next) 953 { 954 if (buf->b_ffname == NULL || buf->b_sfname == NULL) 955 { 956 if (l == 0) break; 957 } 958 else if (strncmp(s, (char *)buf->b_ffname, l) == 0 959 || strncmp(s, (char *)buf->b_sfname, l) == 0) 960 break; 961 } 962 } 963 if (buf == NULL) /* not found? */ 964 lua_pushnil(L); 965 else 966 luaV_pushbuffer(L, buf); 967 } 968 else { 969 buf = (lua_toboolean(L, 1)) ? firstbuf : curbuf; /* first buffer? */ 970 luaV_pushbuffer(L, buf); 971 } 972 return 1; 973 } 974 975 static int 976 luaV_window(lua_State *L) 977 { 978 win_T *win; 979 if (lua_isnumber(L, 1)) /* get by number? */ 980 { 981 int n = lua_tointeger(L, 1); 982 for (win = firstwin; win != NULL; win = win->w_next, n--) 983 if (n == 1) break; 984 if (win == NULL) /* not found? */ 985 lua_pushnil(L); 986 else 987 luaV_pushwindow(L, win); 988 } 989 else { 990 win = (lua_toboolean(L, 1)) ? firstwin : curwin; /* first window? */ 991 luaV_pushwindow(L, win); 992 } 993 return 1; 994 } 995 996 static int 997 luaV_open(lua_State *L) 998 { 999 luaV_Buffer *b; 1000 char_u *s = NULL; 1001 #ifdef HAVE_SANDBOX 1002 luaV_checksandbox(L); 1003 #endif 1004 if (lua_isstring(L, 1)) s = (char_u *) lua_tostring(L, 1); 1005 b = luaV_pushbuffer(L, buflist_new(s, NULL, 1L, BLN_LISTED)); 1006 return 1; 1007 } 1008 1009 static int 1010 luaV_isbuffer(lua_State *L) 1011 { 1012 lua_pushboolean(L, luaV_toudata(L, 1, LUAVIM_BUFFER) != NULL); 1013 return 1; 1014 } 1015 1016 static int 1017 luaV_iswindow(lua_State *L) 1018 { 1019 lua_pushboolean(L, luaV_toudata(L, 1, LUAVIM_WINDOW) != NULL); 1020 return 1; 1021 } 1022 1023 /* for freeing buffer and window objects; lightuserdata as arg */ 1024 static int 1025 luaV_free(lua_State *L) 1026 { 1027 lua_pushvalue(L, 1); /* lightudata */ 1028 lua_rawget(L, LUA_ENVIRONINDEX); 1029 if (!lua_isnil(L, -1)) 1030 { 1031 lua_pushnil(L); 1032 lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = nil */ 1033 lua_pushnil(L); 1034 lua_rawset(L, LUA_ENVIRONINDEX); /* env[lightudata] = nil */ 1035 } 1036 return 0; 1037 } 1038 1039 static const luaL_Reg luaV_module[] = { 1040 {"command", luaV_command}, 1041 {"eval", luaV_eval}, 1042 {"beep", luaV_beep}, 1043 {"line", luaV_line}, 1044 {"buffer", luaV_buffer}, 1045 {"window", luaV_window}, 1046 {"open", luaV_open}, 1047 {"isbuffer", luaV_isbuffer}, 1048 {"iswindow", luaV_iswindow}, 1049 {NULL, NULL} 1050 }; 1051 1052 static int 1053 luaopen_vim(lua_State *L) 1054 { 1055 /* set environment */ 1056 lua_newtable(L); 1057 lua_newtable(L); 1058 lua_pushliteral(L, "v"); 1059 lua_setfield(L, -2, "__mode"); 1060 lua_setmetatable(L, -2); 1061 lua_replace(L, LUA_ENVIRONINDEX); 1062 /* print */ 1063 lua_pushcfunction(L, luaV_print); 1064 lua_setglobal(L, "print"); 1065 /* free */ 1066 lua_pushlightuserdata(L, (void *) LUAVIM_FREE); 1067 lua_pushcfunction(L, luaV_free); 1068 lua_rawset(L, LUA_REGISTRYINDEX); 1069 /* register */ 1070 luaV_newmetatable(L, LUAVIM_BUFFER); 1071 luaL_register(L, NULL, luaV_Buffer_mt); 1072 luaV_newmetatable(L, LUAVIM_WINDOW); 1073 luaL_register(L, NULL, luaV_Window_mt); 1074 luaL_register(L, LUAVIM_NAME, luaV_module); 1075 return 0; 1076 } 1077 1078 static lua_State * 1079 luaV_newstate(void) 1080 { 1081 lua_State *L = luaL_newstate(); 1082 const luaL_Reg luaV_core_libs[] = { 1083 {"", luaopen_base}, 1084 {LUA_TABLIBNAME, luaopen_table}, 1085 {LUA_STRLIBNAME, luaopen_string}, 1086 {LUA_MATHLIBNAME, luaopen_math}, 1087 {LUA_OSLIBNAME, luaopen_os}, /* restricted */ 1088 {LUA_LOADLIBNAME, luaopen_package}, 1089 {LUA_DBLIBNAME, luaopen_debug}, 1090 {NULL, NULL} 1091 }; 1092 const char *os_funcs[] = { 1093 "date", "clock", "time", "difftime", "getenv", NULL 1094 }; 1095 const luaL_Reg *reg = luaV_core_libs; 1096 const char **s = os_funcs; 1097 /* core libs */ 1098 for ( ; reg->func; reg++) 1099 { 1100 lua_pushcfunction(L, reg->func); 1101 lua_pushstring(L, reg->name); 1102 lua_call(L, 1, 0); 1103 } 1104 /* restricted os lib */ 1105 lua_getglobal(L, LUA_OSLIBNAME); 1106 lua_newtable(L); 1107 for ( ; *s; s++) 1108 { 1109 lua_getfield(L, -2, *s); 1110 lua_setfield(L, -2, *s); 1111 } 1112 lua_setglobal(L, LUA_OSLIBNAME); 1113 lua_pop(L, 1); /* os table */ 1114 /* vim */ 1115 lua_pushcfunction(L, luaopen_vim); 1116 lua_call(L, 0, 0); 1117 return L; 1118 } 1119 1120 static void 1121 luaV_setrange(lua_State *L, int line1, int line2) 1122 { 1123 lua_getglobal(L, LUAVIM_NAME); 1124 lua_pushinteger(L, line1); 1125 lua_setfield(L, -2, "firstline"); 1126 lua_pushinteger(L, line2); 1127 lua_setfield(L, -2, "lastline"); 1128 lua_pop(L, 1); /* vim table */ 1129 } 1130 1131 1132 /* ======= Interface ======= */ 1133 1134 static lua_State *L = NULL; 1135 1136 static int 1137 lua_init(void) 1138 { 1139 if (L == NULL) 1140 { 1141 #ifdef DYNAMIC_LUA 1142 if (!lua_enabled(TRUE)) 1143 { 1144 EMSG(_("Lua library cannot be loaded.")); 1145 return FAIL; 1146 } 1147 #endif 1148 L = luaV_newstate(); 1149 } 1150 return OK; 1151 } 1152 1153 void 1154 lua_end(void) 1155 { 1156 if (L != NULL) 1157 { 1158 lua_close(L); 1159 L = NULL; 1160 #ifdef DYNAMIC_LUA 1161 end_dynamic_lua(); 1162 #endif 1163 } 1164 } 1165 1166 /* ex commands */ 1167 void 1168 ex_lua(exarg_T *eap) 1169 { 1170 char *script; 1171 if (lua_init() == FAIL) return; 1172 script = (char *) script_get(eap, eap->arg); 1173 if (!eap->skip) 1174 { 1175 char *s = (script) ? script : (char *) eap->arg; 1176 luaV_setrange(L, eap->line1, eap->line2); 1177 if (luaL_loadbuffer(L, s, strlen(s), LUAVIM_CHUNKNAME) 1178 || lua_pcall(L, 0, 0, 0)) 1179 luaV_emsg(L); 1180 } 1181 if (script != NULL) vim_free(script); 1182 } 1183 1184 void 1185 ex_luado(exarg_T *eap) 1186 { 1187 linenr_T l; 1188 const char *s = (const char *) eap->arg; 1189 luaL_Buffer b; 1190 size_t len; 1191 if (lua_init() == FAIL) return; 1192 if (u_save(eap->line1 - 1, eap->line2 + 1) == FAIL) 1193 { 1194 EMSG(_("cannot save undo information")); 1195 return; 1196 } 1197 luaV_setrange(L, eap->line1, eap->line2); 1198 luaL_buffinit(L, &b); 1199 luaL_addlstring(&b, "return function(line) ", 22); /* header */ 1200 luaL_addlstring(&b, s, strlen(s)); 1201 luaL_addlstring(&b, " end", 4); /* footer */ 1202 luaL_pushresult(&b); 1203 s = lua_tolstring(L, -1, &len); 1204 if (luaL_loadbuffer(L, s, len, LUAVIM_CHUNKNAME)) 1205 { 1206 luaV_emsg(L); 1207 lua_pop(L, 1); /* function body */ 1208 return; 1209 } 1210 lua_call(L, 0, 1); 1211 lua_replace(L, -2); /* function -> body */ 1212 for (l = eap->line1; l <= eap->line2; l++) 1213 { 1214 lua_pushvalue(L, -1); /* function */ 1215 luaV_pushline(L, curbuf, l); /* current line as arg */ 1216 if (lua_pcall(L, 1, 1, 0)) 1217 { 1218 luaV_emsg(L); 1219 break; 1220 } 1221 if (lua_isstring(L, -1)) /* update line? */ 1222 { 1223 #ifdef HAVE_SANDBOX 1224 luaV_checksandbox(L); 1225 #endif 1226 ml_replace(l, luaV_toline(L, -1), TRUE); 1227 changed_bytes(l, 0); 1228 lua_pop(L, 1); /* result from luaV_toline */ 1229 } 1230 lua_pop(L, 1); /* line */ 1231 } 1232 lua_pop(L, 1); /* function */ 1233 check_cursor(); 1234 update_screen(NOT_VALID); 1235 } 1236 1237 void 1238 ex_luafile(exarg_T *eap) 1239 { 1240 if (lua_init() == FAIL) 1241 return; 1242 if (!eap->skip) 1243 { 1244 luaV_setrange(L, eap->line1, eap->line2); 1245 if (luaL_loadfile(L, (char *) eap->arg) || lua_pcall(L, 0, 0, 0)) 1246 luaV_emsg(L); 1247 } 1248 } 1249 1250 /* buffer */ 1251 void 1252 lua_buffer_free(buf_T *buf) 1253 { 1254 if (lua_init() == FAIL) return; 1255 luaV_getfield(L, LUAVIM_FREE); 1256 lua_pushlightuserdata(L, (void *) buf); 1257 lua_call(L, 1, 0); 1258 } 1259 1260 /* window */ 1261 void 1262 lua_window_free(win_T *win) 1263 { 1264 if (lua_init() == FAIL) return; 1265 luaV_getfield(L, LUAVIM_FREE); 1266 lua_pushlightuserdata(L, (void *) win); 1267 lua_call(L, 1, 0); 1268 } 1269 1270 #endif 1271