1 /* vi:set ts=8 sts=4 sw=4 noet: 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 #define LUAVIM_EVALNAME "luaeval" 25 #define LUAVIM_EVALHEADER "local _A=select(1,...) return " 26 27 typedef buf_T *luaV_Buffer; 28 typedef win_T *luaV_Window; 29 typedef dict_T *luaV_Dict; 30 typedef list_T *luaV_List; 31 typedef void (*msgfunc_T)(char_u *); 32 33 static const char LUAVIM_DICT[] = "dict"; 34 static const char LUAVIM_LIST[] = "list"; 35 static const char LUAVIM_BUFFER[] = "buffer"; 36 static const char LUAVIM_WINDOW[] = "window"; 37 static const char LUAVIM_FREE[] = "luaV_free"; 38 static const char LUAVIM_LUAEVAL[] = "luaV_luaeval"; 39 static const char LUAVIM_SETREF[] = "luaV_setref"; 40 41 /* most functions are closures with a cache table as first upvalue; 42 * get/setudata manage references to vim userdata in cache table through 43 * object pointers (light userdata) */ 44 #define luaV_getudata(L, v) \ 45 lua_pushlightuserdata((L), (void *) (v)); \ 46 lua_rawget((L), lua_upvalueindex(1)) 47 #define luaV_setudata(L, v) \ 48 lua_pushlightuserdata((L), (void *) (v)); \ 49 lua_pushvalue((L), -2); \ 50 lua_rawset((L), lua_upvalueindex(1)) 51 #define luaV_getfield(L, s) \ 52 lua_pushlightuserdata((L), (void *)(s)); \ 53 lua_rawget((L), LUA_REGISTRYINDEX) 54 #define luaV_checksandbox(L) \ 55 if (sandbox) luaL_error((L), "not allowed in sandbox") 56 #define luaV_msg(L) luaV_msgfunc((L), (msgfunc_T) msg) 57 #define luaV_emsg(L) luaV_msgfunc((L), (msgfunc_T) emsg) 58 59 static luaV_List *luaV_pushlist (lua_State *L, list_T *lis); 60 static luaV_Dict *luaV_pushdict (lua_State *L, dict_T *dic); 61 62 #if LUA_VERSION_NUM <= 501 63 #define luaV_openlib(L, l, n) luaL_openlib(L, NULL, l, n) 64 #define luaL_typeerror luaL_typerror 65 #else 66 #define luaV_openlib luaL_setfuncs 67 #endif 68 69 #ifdef DYNAMIC_LUA 70 71 #ifndef WIN3264 72 # include <dlfcn.h> 73 # define HANDLE void* 74 # define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL) 75 # define symbol_from_dll dlsym 76 # define close_dll dlclose 77 #else 78 # define load_dll vimLoadLib 79 # define symbol_from_dll GetProcAddress 80 # define close_dll FreeLibrary 81 #endif 82 83 /* lauxlib */ 84 #if LUA_VERSION_NUM <= 501 85 #define luaL_register dll_luaL_register 86 #define luaL_prepbuffer dll_luaL_prepbuffer 87 #define luaL_openlib dll_luaL_openlib 88 #define luaL_typerror dll_luaL_typerror 89 #define luaL_loadfile dll_luaL_loadfile 90 #define luaL_loadbuffer dll_luaL_loadbuffer 91 #else 92 #define luaL_prepbuffsize dll_luaL_prepbuffsize 93 #define luaL_setfuncs dll_luaL_setfuncs 94 #define luaL_loadfilex dll_luaL_loadfilex 95 #define luaL_loadbufferx dll_luaL_loadbufferx 96 #define luaL_argerror dll_luaL_argerror 97 #endif 98 #define luaL_checkany dll_luaL_checkany 99 #define luaL_checklstring dll_luaL_checklstring 100 #define luaL_checkinteger dll_luaL_checkinteger 101 #define luaL_optinteger dll_luaL_optinteger 102 #define luaL_checktype dll_luaL_checktype 103 #define luaL_error dll_luaL_error 104 #define luaL_newstate dll_luaL_newstate 105 #define luaL_buffinit dll_luaL_buffinit 106 #define luaL_addlstring dll_luaL_addlstring 107 #define luaL_pushresult dll_luaL_pushresult 108 /* lua */ 109 #if LUA_VERSION_NUM <= 501 110 #define lua_tonumber dll_lua_tonumber 111 #define lua_tointeger dll_lua_tointeger 112 #define lua_call dll_lua_call 113 #define lua_pcall dll_lua_pcall 114 #else 115 #define lua_tonumberx dll_lua_tonumberx 116 #define lua_tointegerx dll_lua_tointegerx 117 #define lua_callk dll_lua_callk 118 #define lua_pcallk dll_lua_pcallk 119 #define lua_getglobal dll_lua_getglobal 120 #define lua_setglobal dll_lua_setglobal 121 #endif 122 #if LUA_VERSION_NUM <= 502 123 #define lua_replace dll_lua_replace 124 #define lua_remove dll_lua_remove 125 #endif 126 #if LUA_VERSION_NUM >= 503 127 #define lua_rotate dll_lua_rotate 128 #define lua_copy dll_lua_copy 129 #endif 130 #define lua_typename dll_lua_typename 131 #define lua_close dll_lua_close 132 #define lua_gettop dll_lua_gettop 133 #define lua_settop dll_lua_settop 134 #define lua_pushvalue dll_lua_pushvalue 135 #define lua_isnumber dll_lua_isnumber 136 #define lua_isstring dll_lua_isstring 137 #define lua_type dll_lua_type 138 #define lua_rawequal dll_lua_rawequal 139 #define lua_toboolean dll_lua_toboolean 140 #define lua_tolstring dll_lua_tolstring 141 #define lua_touserdata dll_lua_touserdata 142 #define lua_pushnil dll_lua_pushnil 143 #define lua_pushnumber dll_lua_pushnumber 144 #define lua_pushinteger dll_lua_pushinteger 145 #define lua_pushlstring dll_lua_pushlstring 146 #define lua_pushstring dll_lua_pushstring 147 #define lua_pushfstring dll_lua_pushfstring 148 #define lua_pushcclosure dll_lua_pushcclosure 149 #define lua_pushboolean dll_lua_pushboolean 150 #define lua_pushlightuserdata dll_lua_pushlightuserdata 151 #define lua_getfield dll_lua_getfield 152 #define lua_rawget dll_lua_rawget 153 #define lua_rawgeti dll_lua_rawgeti 154 #define lua_createtable dll_lua_createtable 155 #define lua_newuserdata dll_lua_newuserdata 156 #define lua_getmetatable dll_lua_getmetatable 157 #define lua_setfield dll_lua_setfield 158 #define lua_rawset dll_lua_rawset 159 #define lua_rawseti dll_lua_rawseti 160 #define lua_setmetatable dll_lua_setmetatable 161 #define lua_next dll_lua_next 162 /* libs */ 163 #define luaopen_base dll_luaopen_base 164 #define luaopen_table dll_luaopen_table 165 #define luaopen_string dll_luaopen_string 166 #define luaopen_math dll_luaopen_math 167 #define luaopen_io dll_luaopen_io 168 #define luaopen_os dll_luaopen_os 169 #define luaopen_package dll_luaopen_package 170 #define luaopen_debug dll_luaopen_debug 171 #define luaL_openlibs dll_luaL_openlibs 172 173 /* lauxlib */ 174 #if LUA_VERSION_NUM <= 501 175 void (*dll_luaL_register) (lua_State *L, const char *libname, const luaL_Reg *l); 176 char *(*dll_luaL_prepbuffer) (luaL_Buffer *B); 177 void (*dll_luaL_openlib) (lua_State *L, const char *libname, const luaL_Reg *l, int nup); 178 int (*dll_luaL_typerror) (lua_State *L, int narg, const char *tname); 179 int (*dll_luaL_loadfile) (lua_State *L, const char *filename); 180 int (*dll_luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, const char *name); 181 #else 182 char *(*dll_luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); 183 void (*dll_luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); 184 int (*dll_luaL_loadfilex) (lua_State *L, const char *filename, const char *mode); 185 int (*dll_luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode); 186 int (*dll_luaL_argerror) (lua_State *L, int numarg, const char *extramsg); 187 #endif 188 void (*dll_luaL_checkany) (lua_State *L, int narg); 189 const char *(*dll_luaL_checklstring) (lua_State *L, int numArg, size_t *l); 190 lua_Integer (*dll_luaL_checkinteger) (lua_State *L, int numArg); 191 lua_Integer (*dll_luaL_optinteger) (lua_State *L, int nArg, lua_Integer def); 192 void (*dll_luaL_checktype) (lua_State *L, int narg, int t); 193 int (*dll_luaL_error) (lua_State *L, const char *fmt, ...); 194 lua_State *(*dll_luaL_newstate) (void); 195 void (*dll_luaL_buffinit) (lua_State *L, luaL_Buffer *B); 196 void (*dll_luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); 197 void (*dll_luaL_pushresult) (luaL_Buffer *B); 198 /* lua */ 199 #if LUA_VERSION_NUM <= 501 200 lua_Number (*dll_lua_tonumber) (lua_State *L, int idx); 201 lua_Integer (*dll_lua_tointeger) (lua_State *L, int idx); 202 void (*dll_lua_call) (lua_State *L, int nargs, int nresults); 203 int (*dll_lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); 204 #else 205 lua_Number (*dll_lua_tonumberx) (lua_State *L, int idx, int *isnum); 206 lua_Integer (*dll_lua_tointegerx) (lua_State *L, int idx, int *isnum); 207 void (*dll_lua_callk) (lua_State *L, int nargs, int nresults, int ctx, 208 lua_CFunction k); 209 int (*dll_lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, 210 int ctx, lua_CFunction k); 211 void (*dll_lua_getglobal) (lua_State *L, const char *var); 212 void (*dll_lua_setglobal) (lua_State *L, const char *var); 213 #endif 214 #if LUA_VERSION_NUM <= 502 215 void (*dll_lua_replace) (lua_State *L, int idx); 216 void (*dll_lua_remove) (lua_State *L, int idx); 217 #endif 218 #if LUA_VERSION_NUM >= 503 219 void (*dll_lua_rotate) (lua_State *L, int idx, int n); 220 void (*dll_lua_copy) (lua_State *L, int fromidx, int toidx); 221 #endif 222 const char *(*dll_lua_typename) (lua_State *L, int tp); 223 void (*dll_lua_close) (lua_State *L); 224 int (*dll_lua_gettop) (lua_State *L); 225 void (*dll_lua_settop) (lua_State *L, int idx); 226 void (*dll_lua_pushvalue) (lua_State *L, int idx); 227 int (*dll_lua_isnumber) (lua_State *L, int idx); 228 int (*dll_lua_isstring) (lua_State *L, int idx); 229 int (*dll_lua_type) (lua_State *L, int idx); 230 int (*dll_lua_rawequal) (lua_State *L, int idx1, int idx2); 231 int (*dll_lua_toboolean) (lua_State *L, int idx); 232 const char *(*dll_lua_tolstring) (lua_State *L, int idx, size_t *len); 233 void *(*dll_lua_touserdata) (lua_State *L, int idx); 234 void (*dll_lua_pushnil) (lua_State *L); 235 void (*dll_lua_pushnumber) (lua_State *L, lua_Number n); 236 void (*dll_lua_pushinteger) (lua_State *L, lua_Integer n); 237 void (*dll_lua_pushlstring) (lua_State *L, const char *s, size_t l); 238 void (*dll_lua_pushstring) (lua_State *L, const char *s); 239 const char *(*dll_lua_pushfstring) (lua_State *L, const char *fmt, ...); 240 void (*dll_lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); 241 void (*dll_lua_pushboolean) (lua_State *L, int b); 242 void (*dll_lua_pushlightuserdata) (lua_State *L, void *p); 243 void (*dll_lua_getfield) (lua_State *L, int idx, const char *k); 244 void (*dll_lua_rawget) (lua_State *L, int idx); 245 void (*dll_lua_rawgeti) (lua_State *L, int idx, int n); 246 void (*dll_lua_createtable) (lua_State *L, int narr, int nrec); 247 void *(*dll_lua_newuserdata) (lua_State *L, size_t sz); 248 int (*dll_lua_getmetatable) (lua_State *L, int objindex); 249 void (*dll_lua_setfield) (lua_State *L, int idx, const char *k); 250 void (*dll_lua_rawset) (lua_State *L, int idx); 251 void (*dll_lua_rawseti) (lua_State *L, int idx, int n); 252 int (*dll_lua_setmetatable) (lua_State *L, int objindex); 253 int (*dll_lua_next) (lua_State *L, int idx); 254 /* libs */ 255 int (*dll_luaopen_base) (lua_State *L); 256 int (*dll_luaopen_table) (lua_State *L); 257 int (*dll_luaopen_string) (lua_State *L); 258 int (*dll_luaopen_math) (lua_State *L); 259 int (*dll_luaopen_io) (lua_State *L); 260 int (*dll_luaopen_os) (lua_State *L); 261 int (*dll_luaopen_package) (lua_State *L); 262 int (*dll_luaopen_debug) (lua_State *L); 263 void (*dll_luaL_openlibs) (lua_State *L); 264 265 typedef void **luaV_function; 266 typedef struct { 267 const char *name; 268 luaV_function func; 269 } luaV_Reg; 270 271 static const luaV_Reg luaV_dll[] = { 272 /* lauxlib */ 273 #if LUA_VERSION_NUM <= 501 274 {"luaL_register", (luaV_function) &dll_luaL_register}, 275 {"luaL_prepbuffer", (luaV_function) &dll_luaL_prepbuffer}, 276 {"luaL_openlib", (luaV_function) &dll_luaL_openlib}, 277 {"luaL_typerror", (luaV_function) &dll_luaL_typerror}, 278 {"luaL_loadfile", (luaV_function) &dll_luaL_loadfile}, 279 {"luaL_loadbuffer", (luaV_function) &dll_luaL_loadbuffer}, 280 #else 281 {"luaL_prepbuffsize", (luaV_function) &dll_luaL_prepbuffsize}, 282 {"luaL_setfuncs", (luaV_function) &dll_luaL_setfuncs}, 283 {"luaL_loadfilex", (luaV_function) &dll_luaL_loadfilex}, 284 {"luaL_loadbufferx", (luaV_function) &dll_luaL_loadbufferx}, 285 {"luaL_argerror", (luaV_function) &dll_luaL_argerror}, 286 #endif 287 {"luaL_checkany", (luaV_function) &dll_luaL_checkany}, 288 {"luaL_checklstring", (luaV_function) &dll_luaL_checklstring}, 289 {"luaL_checkinteger", (luaV_function) &dll_luaL_checkinteger}, 290 {"luaL_optinteger", (luaV_function) &dll_luaL_optinteger}, 291 {"luaL_checktype", (luaV_function) &dll_luaL_checktype}, 292 {"luaL_error", (luaV_function) &dll_luaL_error}, 293 {"luaL_newstate", (luaV_function) &dll_luaL_newstate}, 294 {"luaL_buffinit", (luaV_function) &dll_luaL_buffinit}, 295 {"luaL_addlstring", (luaV_function) &dll_luaL_addlstring}, 296 {"luaL_pushresult", (luaV_function) &dll_luaL_pushresult}, 297 /* lua */ 298 #if LUA_VERSION_NUM <= 501 299 {"lua_tonumber", (luaV_function) &dll_lua_tonumber}, 300 {"lua_tointeger", (luaV_function) &dll_lua_tointeger}, 301 {"lua_call", (luaV_function) &dll_lua_call}, 302 {"lua_pcall", (luaV_function) &dll_lua_pcall}, 303 #else 304 {"lua_tonumberx", (luaV_function) &dll_lua_tonumberx}, 305 {"lua_tointegerx", (luaV_function) &dll_lua_tointegerx}, 306 {"lua_callk", (luaV_function) &dll_lua_callk}, 307 {"lua_pcallk", (luaV_function) &dll_lua_pcallk}, 308 {"lua_getglobal", (luaV_function) &dll_lua_getglobal}, 309 {"lua_setglobal", (luaV_function) &dll_lua_setglobal}, 310 #endif 311 #if LUA_VERSION_NUM <= 502 312 {"lua_replace", (luaV_function) &dll_lua_replace}, 313 {"lua_remove", (luaV_function) &dll_lua_remove}, 314 #endif 315 #if LUA_VERSION_NUM >= 503 316 {"lua_rotate", (luaV_function) &dll_lua_rotate}, 317 {"lua_copy", (luaV_function) &dll_lua_copy}, 318 #endif 319 {"lua_typename", (luaV_function) &dll_lua_typename}, 320 {"lua_close", (luaV_function) &dll_lua_close}, 321 {"lua_gettop", (luaV_function) &dll_lua_gettop}, 322 {"lua_settop", (luaV_function) &dll_lua_settop}, 323 {"lua_pushvalue", (luaV_function) &dll_lua_pushvalue}, 324 {"lua_isnumber", (luaV_function) &dll_lua_isnumber}, 325 {"lua_isstring", (luaV_function) &dll_lua_isstring}, 326 {"lua_type", (luaV_function) &dll_lua_type}, 327 {"lua_rawequal", (luaV_function) &dll_lua_rawequal}, 328 {"lua_toboolean", (luaV_function) &dll_lua_toboolean}, 329 {"lua_tolstring", (luaV_function) &dll_lua_tolstring}, 330 {"lua_touserdata", (luaV_function) &dll_lua_touserdata}, 331 {"lua_pushnil", (luaV_function) &dll_lua_pushnil}, 332 {"lua_pushnumber", (luaV_function) &dll_lua_pushnumber}, 333 {"lua_pushinteger", (luaV_function) &dll_lua_pushinteger}, 334 {"lua_pushlstring", (luaV_function) &dll_lua_pushlstring}, 335 {"lua_pushstring", (luaV_function) &dll_lua_pushstring}, 336 {"lua_pushfstring", (luaV_function) &dll_lua_pushfstring}, 337 {"lua_pushcclosure", (luaV_function) &dll_lua_pushcclosure}, 338 {"lua_pushboolean", (luaV_function) &dll_lua_pushboolean}, 339 {"lua_pushlightuserdata", (luaV_function) &dll_lua_pushlightuserdata}, 340 {"lua_getfield", (luaV_function) &dll_lua_getfield}, 341 {"lua_rawget", (luaV_function) &dll_lua_rawget}, 342 {"lua_rawgeti", (luaV_function) &dll_lua_rawgeti}, 343 {"lua_createtable", (luaV_function) &dll_lua_createtable}, 344 {"lua_newuserdata", (luaV_function) &dll_lua_newuserdata}, 345 {"lua_getmetatable", (luaV_function) &dll_lua_getmetatable}, 346 {"lua_setfield", (luaV_function) &dll_lua_setfield}, 347 {"lua_rawset", (luaV_function) &dll_lua_rawset}, 348 {"lua_rawseti", (luaV_function) &dll_lua_rawseti}, 349 {"lua_setmetatable", (luaV_function) &dll_lua_setmetatable}, 350 {"lua_next", (luaV_function) &dll_lua_next}, 351 /* libs */ 352 {"luaopen_base", (luaV_function) &dll_luaopen_base}, 353 {"luaopen_table", (luaV_function) &dll_luaopen_table}, 354 {"luaopen_string", (luaV_function) &dll_luaopen_string}, 355 {"luaopen_math", (luaV_function) &dll_luaopen_math}, 356 {"luaopen_io", (luaV_function) &dll_luaopen_io}, 357 {"luaopen_os", (luaV_function) &dll_luaopen_os}, 358 {"luaopen_package", (luaV_function) &dll_luaopen_package}, 359 {"luaopen_debug", (luaV_function) &dll_luaopen_debug}, 360 {"luaL_openlibs", (luaV_function) &dll_luaL_openlibs}, 361 {NULL, NULL} 362 }; 363 364 static HANDLE hinstLua = NULL; 365 366 static void 367 end_dynamic_lua(void) 368 { 369 if (hinstLua) 370 { 371 close_dll(hinstLua); 372 hinstLua = 0; 373 } 374 } 375 376 static int 377 lua_link_init(char *libname, int verbose) 378 { 379 const luaV_Reg *reg; 380 if (hinstLua) return OK; 381 hinstLua = load_dll(libname); 382 if (!hinstLua) 383 { 384 if (verbose) 385 EMSG2(_(e_loadlib), libname); 386 return FAIL; 387 } 388 for (reg = luaV_dll; reg->func; reg++) 389 { 390 if ((*reg->func = symbol_from_dll(hinstLua, reg->name)) == NULL) 391 { 392 close_dll(hinstLua); 393 hinstLua = 0; 394 if (verbose) 395 EMSG2(_(e_loadfunc), reg->name); 396 return FAIL; 397 } 398 } 399 return OK; 400 } 401 #endif /* DYNAMIC_LUA */ 402 403 #if defined(DYNAMIC_LUA) || defined(PROTO) 404 int 405 lua_enabled(int verbose) 406 { 407 return lua_link_init((char *)p_luadll, verbose) == OK; 408 } 409 #endif 410 411 #if LUA_VERSION_NUM > 501 412 static int 413 luaL_typeerror (lua_State *L, int narg, const char *tname) 414 { 415 const char *msg = lua_pushfstring(L, "%s expected, got %s", 416 tname, luaL_typename(L, narg)); 417 return luaL_argerror(L, narg, msg); 418 } 419 #endif 420 421 422 /* ======= Internal ======= */ 423 424 static void 425 luaV_newmetatable(lua_State *L, const char *tname) 426 { 427 lua_newtable(L); 428 lua_pushlightuserdata(L, (void *) tname); 429 lua_pushvalue(L, -2); 430 lua_rawset(L, LUA_REGISTRYINDEX); 431 } 432 433 static void * 434 luaV_toudata(lua_State *L, int ud, const char *tname) 435 { 436 void *p = lua_touserdata(L, ud); 437 438 if (p != NULL) /* value is userdata? */ 439 { 440 if (lua_getmetatable(L, ud)) /* does it have a metatable? */ 441 { 442 luaV_getfield(L, tname); /* get metatable */ 443 if (lua_rawequal(L, -1, -2)) /* MTs match? */ 444 { 445 lua_pop(L, 2); /* MTs */ 446 return p; 447 } 448 } 449 } 450 return NULL; 451 } 452 453 static void * 454 luaV_checkcache(lua_State *L, void *p) 455 { 456 luaV_getudata(L, p); 457 if (lua_isnil(L, -1)) luaL_error(L, "invalid object"); 458 lua_pop(L, 1); 459 return p; 460 } 461 462 #define luaV_unbox(L,luatyp,ud) (*((luatyp *) lua_touserdata((L),(ud)))) 463 464 #define luaV_checkvalid(L,luatyp,ud) \ 465 luaV_checkcache((L), (void *) luaV_unbox((L),luatyp,(ud))) 466 467 static void * 468 luaV_checkudata(lua_State *L, int ud, const char *tname) 469 { 470 void *p = luaV_toudata(L, ud, tname); 471 if (p == NULL) luaL_typeerror(L, ud, tname); 472 return p; 473 } 474 475 static void 476 luaV_pushtypval(lua_State *L, typval_T *tv) 477 { 478 if (tv == NULL) 479 { 480 lua_pushnil(L); 481 return; 482 } 483 switch (tv->v_type) 484 { 485 case VAR_STRING: 486 lua_pushstring(L, tv->vval.v_string == NULL 487 ? "" : (char *)tv->vval.v_string); 488 break; 489 case VAR_NUMBER: 490 lua_pushinteger(L, (int) tv->vval.v_number); 491 break; 492 #ifdef FEAT_FLOAT 493 case VAR_FLOAT: 494 lua_pushnumber(L, (lua_Number) tv->vval.v_float); 495 break; 496 #endif 497 case VAR_LIST: 498 luaV_pushlist(L, tv->vval.v_list); 499 break; 500 case VAR_DICT: 501 luaV_pushdict(L, tv->vval.v_dict); 502 break; 503 case VAR_SPECIAL: 504 if (tv->vval.v_number <= VVAL_TRUE) 505 lua_pushinteger(L, (int) tv->vval.v_number); 506 else 507 lua_pushnil(L); 508 break; 509 default: 510 lua_pushnil(L); 511 } 512 } 513 514 /* converts lua value at 'pos' to typval 'tv' */ 515 static void 516 luaV_totypval (lua_State *L, int pos, typval_T *tv) 517 { 518 switch(lua_type(L, pos)) { 519 case LUA_TBOOLEAN: 520 tv->v_type = VAR_SPECIAL; 521 tv->vval.v_number = (varnumber_T) lua_toboolean(L, pos); 522 break; 523 case LUA_TSTRING: 524 tv->v_type = VAR_STRING; 525 tv->vval.v_string = vim_strsave((char_u *) lua_tostring(L, pos)); 526 break; 527 case LUA_TNUMBER: 528 #ifdef FEAT_FLOAT 529 tv->v_type = VAR_FLOAT; 530 tv->vval.v_float = (float_T) lua_tonumber(L, pos); 531 #else 532 tv->v_type = VAR_NUMBER; 533 tv->vval.v_number = (varnumber_T) lua_tointeger(L, pos); 534 #endif 535 break; 536 case LUA_TUSERDATA: { 537 void *p = lua_touserdata(L, pos); 538 if (lua_getmetatable(L, pos)) /* has metatable? */ 539 { 540 /* check list */ 541 luaV_getfield(L, LUAVIM_LIST); 542 if (lua_rawequal(L, -1, -2)) 543 { 544 tv->v_type = VAR_LIST; 545 tv->vval.v_list = *((luaV_List *) p); 546 ++tv->vval.v_list->lv_refcount; 547 lua_pop(L, 2); /* MTs */ 548 return; 549 } 550 /* check dict */ 551 luaV_getfield(L, LUAVIM_DICT); 552 if (lua_rawequal(L, -1, -3)) 553 { 554 tv->v_type = VAR_DICT; 555 tv->vval.v_dict = *((luaV_Dict *) p); 556 ++tv->vval.v_dict->dv_refcount; 557 lua_pop(L, 3); /* MTs */ 558 return; 559 } 560 lua_pop(L, 3); /* MTs */ 561 } 562 break; 563 } 564 default: 565 tv->v_type = VAR_NUMBER; 566 tv->vval.v_number = 0; 567 } 568 } 569 570 /* similar to luaL_addlstring, but replaces \0 with \n if toline and 571 * \n with \0 otherwise */ 572 static void 573 luaV_addlstring(luaL_Buffer *b, const char *s, size_t l, int toline) 574 { 575 while (l--) 576 { 577 if (*s == '\0' && toline) 578 luaL_addchar(b, '\n'); 579 else if (*s == '\n' && !toline) 580 luaL_addchar(b, '\0'); 581 else 582 luaL_addchar(b, *s); 583 s++; 584 } 585 } 586 587 static void 588 luaV_pushline(lua_State *L, buf_T *buf, linenr_T n) 589 { 590 const char *s = (const char *) ml_get_buf(buf, n, FALSE); 591 luaL_Buffer b; 592 luaL_buffinit(L, &b); 593 luaV_addlstring(&b, s, strlen(s), 0); 594 luaL_pushresult(&b); 595 } 596 597 static char_u * 598 luaV_toline(lua_State *L, int pos) 599 { 600 size_t l; 601 const char *s = lua_tolstring(L, pos, &l); 602 603 luaL_Buffer b; 604 luaL_buffinit(L, &b); 605 luaV_addlstring(&b, s, l, 1); 606 luaL_pushresult(&b); 607 return (char_u *) lua_tostring(L, -1); 608 } 609 610 /* pops a string s from the top of the stack and calls mf(t) for pieces t of 611 * s separated by newlines */ 612 static void 613 luaV_msgfunc(lua_State *L, msgfunc_T mf) 614 { 615 luaL_Buffer b; 616 size_t l; 617 const char *p, *s = lua_tolstring(L, -1, &l); 618 luaL_buffinit(L, &b); 619 luaV_addlstring(&b, s, l, 0); 620 luaL_pushresult(&b); 621 /* break string */ 622 p = s = lua_tolstring(L, -1, &l); 623 while (l--) 624 { 625 if (*p++ == '\0') /* break? */ 626 { 627 mf((char_u *) s); 628 s = p; 629 } 630 } 631 mf((char_u *) s); 632 lua_pop(L, 2); /* original and modified strings */ 633 } 634 635 #define luaV_newtype(typ,tname,luatyp,luatname) \ 636 static luatyp * \ 637 luaV_new##tname (lua_State *L, typ *obj) \ 638 { \ 639 luatyp *o = (luatyp *) lua_newuserdata(L, sizeof(luatyp)); \ 640 *o = obj; \ 641 luaV_setudata(L, obj); /* cache[obj] = udata */ \ 642 luaV_getfield(L, luatname); \ 643 lua_setmetatable(L, -2); \ 644 return o; \ 645 } 646 647 #define luaV_pushtype(typ,tname,luatyp) \ 648 static luatyp * \ 649 luaV_push##tname (lua_State *L, typ *obj) \ 650 { \ 651 luatyp *o = NULL; \ 652 if (obj == NULL) \ 653 lua_pushnil(L); \ 654 else { \ 655 luaV_getudata(L, obj); \ 656 if (lua_isnil(L, -1)) /* not interned? */ \ 657 { \ 658 lua_pop(L, 1); \ 659 o = luaV_new##tname(L, obj); \ 660 } \ 661 else \ 662 o = (luatyp *) lua_touserdata(L, -1); \ 663 } \ 664 return o; \ 665 } 666 667 #define luaV_type_tostring(tname,luatname) \ 668 static int \ 669 luaV_##tname##_tostring (lua_State *L) \ 670 { \ 671 lua_pushfstring(L, "%s: %p", luatname, lua_touserdata(L, 1)); \ 672 return 1; \ 673 } 674 675 /* ======= List type ======= */ 676 677 static luaV_List * 678 luaV_newlist (lua_State *L, list_T *lis) 679 { 680 luaV_List *l = (luaV_List *) lua_newuserdata(L, sizeof(luaV_List)); 681 *l = lis; 682 lis->lv_refcount++; /* reference in Lua */ 683 luaV_setudata(L, lis); /* cache[lis] = udata */ 684 luaV_getfield(L, LUAVIM_LIST); 685 lua_setmetatable(L, -2); 686 return l; 687 } 688 689 luaV_pushtype(list_T, list, luaV_List) 690 luaV_type_tostring(list, LUAVIM_LIST) 691 692 static int 693 luaV_list_len (lua_State *L) 694 { 695 list_T *l = luaV_unbox(L, luaV_List, 1); 696 lua_pushinteger(L, (l == NULL) ? 0 : (int) l->lv_len); 697 return 1; 698 } 699 700 static int 701 luaV_list_iter (lua_State *L) 702 { 703 listitem_T *li = (listitem_T *) lua_touserdata(L, lua_upvalueindex(2)); 704 if (li == NULL) return 0; 705 luaV_pushtypval(L, &li->li_tv); 706 lua_pushlightuserdata(L, (void *) li->li_next); 707 lua_replace(L, lua_upvalueindex(2)); 708 return 1; 709 } 710 711 static int 712 luaV_list_call (lua_State *L) 713 { 714 list_T *l = luaV_unbox(L, luaV_List, 1); 715 lua_pushvalue(L, lua_upvalueindex(1)); /* pass cache table along */ 716 lua_pushlightuserdata(L, (void *) l->lv_first); 717 lua_pushcclosure(L, luaV_list_iter, 2); 718 return 1; 719 } 720 721 static int 722 luaV_list_index (lua_State *L) 723 { 724 list_T *l = luaV_unbox(L, luaV_List, 1); 725 if (lua_isnumber(L, 2)) /* list item? */ 726 { 727 listitem_T *li = list_find(l, (long) luaL_checkinteger(L, 2)); 728 if (li == NULL) 729 lua_pushnil(L); 730 else 731 luaV_pushtypval(L, &li->li_tv); 732 } 733 else if (lua_isstring(L, 2)) /* method? */ 734 { 735 const char *s = lua_tostring(L, 2); 736 if (strncmp(s, "add", 3) == 0 737 || strncmp(s, "insert", 6) == 0) 738 { 739 lua_getmetatable(L, 1); 740 lua_getfield(L, -1, s); 741 } 742 else 743 lua_pushnil(L); 744 } 745 else 746 lua_pushnil(L); 747 return 1; 748 } 749 750 static int 751 luaV_list_newindex (lua_State *L) 752 { 753 list_T *l = luaV_unbox(L, luaV_List, 1); 754 long n = (long) luaL_checkinteger(L, 2); 755 listitem_T *li; 756 if (l->lv_lock) 757 luaL_error(L, "list is locked"); 758 li = list_find(l, n); 759 if (li == NULL) return 0; 760 if (lua_isnil(L, 3)) /* remove? */ 761 { 762 vimlist_remove(l, li, li); 763 clear_tv(&li->li_tv); 764 vim_free(li); 765 } 766 else 767 { 768 typval_T v; 769 luaV_totypval(L, 3, &v); 770 clear_tv(&li->li_tv); 771 copy_tv(&v, &li->li_tv); 772 clear_tv(&v); 773 } 774 return 0; 775 } 776 777 static int 778 luaV_list_add (lua_State *L) 779 { 780 luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST); 781 list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis); 782 typval_T v; 783 if (l->lv_lock) 784 luaL_error(L, "list is locked"); 785 lua_settop(L, 2); 786 luaV_totypval(L, 2, &v); 787 if (list_append_tv(l, &v) == FAIL) 788 { 789 clear_tv(&v); 790 luaL_error(L, "Failed to add item to list"); 791 } 792 clear_tv(&v); 793 lua_settop(L, 1); 794 return 1; 795 } 796 797 static int 798 luaV_list_insert (lua_State *L) 799 { 800 luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST); 801 list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis); 802 long pos = (long) luaL_optinteger(L, 3, 0); 803 listitem_T *li = NULL; 804 typval_T v; 805 if (l->lv_lock) 806 luaL_error(L, "list is locked"); 807 if (pos < l->lv_len) 808 { 809 li = list_find(l, pos); 810 if (li == NULL) 811 luaL_error(L, "invalid position"); 812 } 813 lua_settop(L, 2); 814 luaV_totypval(L, 2, &v); 815 if (list_insert_tv(l, &v, li) == FAIL) 816 { 817 clear_tv(&v); 818 luaL_error(L, "Failed to add item to list"); 819 } 820 clear_tv(&v); 821 lua_settop(L, 1); 822 return 1; 823 } 824 825 static const luaL_Reg luaV_List_mt[] = { 826 {"__tostring", luaV_list_tostring}, 827 {"__len", luaV_list_len}, 828 {"__call", luaV_list_call}, 829 {"__index", luaV_list_index}, 830 {"__newindex", luaV_list_newindex}, 831 {"add", luaV_list_add}, 832 {"insert", luaV_list_insert}, 833 {NULL, NULL} 834 }; 835 836 837 /* ======= Dict type ======= */ 838 839 static luaV_Dict * 840 luaV_newdict (lua_State *L, dict_T *dic) 841 { 842 luaV_Dict *d = (luaV_Dict *) lua_newuserdata(L, sizeof(luaV_Dict)); 843 *d = dic; 844 dic->dv_refcount++; /* reference in Lua */ 845 luaV_setudata(L, dic); /* cache[dic] = udata */ 846 luaV_getfield(L, LUAVIM_DICT); 847 lua_setmetatable(L, -2); 848 return d; 849 } 850 851 luaV_pushtype(dict_T, dict, luaV_Dict) 852 luaV_type_tostring(dict, LUAVIM_DICT) 853 854 static int 855 luaV_dict_len (lua_State *L) 856 { 857 dict_T *d = luaV_unbox(L, luaV_Dict, 1); 858 lua_pushinteger(L, (d == NULL) ? 0 : (int) d->dv_hashtab.ht_used); 859 return 1; 860 } 861 862 static int 863 luaV_dict_iter (lua_State *L UNUSED) 864 { 865 #ifdef FEAT_EVAL 866 hashitem_T *hi = (hashitem_T *) lua_touserdata(L, lua_upvalueindex(2)); 867 int n = lua_tointeger(L, lua_upvalueindex(3)); 868 dictitem_T *di; 869 if (n <= 0) return 0; 870 while (HASHITEM_EMPTY(hi)) hi++; 871 di = dict_lookup(hi); 872 lua_pushstring(L, (char *) hi->hi_key); 873 luaV_pushtypval(L, &di->di_tv); 874 lua_pushlightuserdata(L, (void *) (hi + 1)); 875 lua_replace(L, lua_upvalueindex(2)); 876 lua_pushinteger(L, n - 1); 877 lua_replace(L, lua_upvalueindex(3)); 878 return 2; 879 #else 880 return 0; 881 #endif 882 } 883 884 static int 885 luaV_dict_call (lua_State *L) 886 { 887 dict_T *d = luaV_unbox(L, luaV_Dict, 1); 888 hashtab_T *ht = &d->dv_hashtab; 889 lua_pushvalue(L, lua_upvalueindex(1)); /* pass cache table along */ 890 lua_pushlightuserdata(L, (void *) ht->ht_array); 891 lua_pushinteger(L, ht->ht_used); /* # remaining items */ 892 lua_pushcclosure(L, luaV_dict_iter, 3); 893 return 1; 894 } 895 896 static int 897 luaV_dict_index (lua_State *L) 898 { 899 dict_T *d = luaV_unbox(L, luaV_Dict, 1); 900 char_u *key = (char_u *) luaL_checkstring(L, 2); 901 dictitem_T *di = dict_find(d, key, -1); 902 if (di == NULL) 903 lua_pushnil(L); 904 else 905 luaV_pushtypval(L, &di->di_tv); 906 return 1; 907 } 908 909 static int 910 luaV_dict_newindex (lua_State *L) 911 { 912 dict_T *d = luaV_unbox(L, luaV_Dict, 1); 913 char_u *key = (char_u *) luaL_checkstring(L, 2); 914 dictitem_T *di; 915 if (d->dv_lock) 916 luaL_error(L, "dict is locked"); 917 di = dict_find(d, key, -1); 918 if (di == NULL) /* non-existing key? */ 919 { 920 if (lua_isnil(L, 3)) return 0; 921 di = dictitem_alloc(key); 922 if (di == NULL) return 0; 923 if (dict_add(d, di) == FAIL) 924 { 925 vim_free(di); 926 return 0; 927 } 928 } 929 else 930 clear_tv(&di->di_tv); 931 if (lua_isnil(L, 3)) /* remove? */ 932 { 933 hashitem_T *hi = hash_find(&d->dv_hashtab, di->di_key); 934 hash_remove(&d->dv_hashtab, hi); 935 dictitem_free(di); 936 } 937 else { 938 typval_T v; 939 luaV_totypval(L, 3, &v); 940 copy_tv(&v, &di->di_tv); 941 clear_tv(&v); 942 } 943 return 0; 944 } 945 946 static const luaL_Reg luaV_Dict_mt[] = { 947 {"__tostring", luaV_dict_tostring}, 948 {"__len", luaV_dict_len}, 949 {"__call", luaV_dict_call}, 950 {"__index", luaV_dict_index}, 951 {"__newindex", luaV_dict_newindex}, 952 {NULL, NULL} 953 }; 954 955 956 /* ======= Buffer type ======= */ 957 958 luaV_newtype(buf_T, buffer, luaV_Buffer, LUAVIM_BUFFER) 959 luaV_pushtype(buf_T, buffer, luaV_Buffer) 960 luaV_type_tostring(buffer, LUAVIM_BUFFER) 961 962 static int 963 luaV_buffer_len(lua_State *L) 964 { 965 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1); 966 lua_pushinteger(L, b->b_ml.ml_line_count); 967 return 1; 968 } 969 970 static int 971 luaV_buffer_call(lua_State *L) 972 { 973 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1); 974 lua_settop(L, 1); 975 set_curbuf(b, DOBUF_SPLIT); 976 return 1; 977 } 978 979 static int 980 luaV_buffer_index(lua_State *L) 981 { 982 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1); 983 linenr_T n = (linenr_T) lua_tointeger(L, 2); 984 if (n > 0 && n <= b->b_ml.ml_line_count) 985 luaV_pushline(L, b, n); 986 else if (lua_isstring(L, 2)) 987 { 988 const char *s = lua_tostring(L, 2); 989 if (strncmp(s, "name", 4) == 0) 990 lua_pushstring(L, (char *) b->b_sfname); 991 else if (strncmp(s, "fname", 5) == 0) 992 lua_pushstring(L, (char *) b->b_ffname); 993 else if (strncmp(s, "number", 6) == 0) 994 lua_pushinteger(L, b->b_fnum); 995 /* methods */ 996 else if (strncmp(s, "insert", 6) == 0 997 || strncmp(s, "next", 4) == 0 998 || strncmp(s, "previous", 8) == 0 999 || strncmp(s, "isvalid", 7) == 0) 1000 { 1001 lua_getmetatable(L, 1); 1002 lua_getfield(L, -1, s); 1003 } 1004 else 1005 lua_pushnil(L); 1006 } 1007 else 1008 lua_pushnil(L); 1009 return 1; 1010 } 1011 1012 static int 1013 luaV_buffer_newindex(lua_State *L) 1014 { 1015 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1); 1016 linenr_T n = (linenr_T) luaL_checkinteger(L, 2); 1017 #ifdef HAVE_SANDBOX 1018 luaV_checksandbox(L); 1019 #endif 1020 if (n < 1 || n > b->b_ml.ml_line_count) 1021 luaL_error(L, "invalid line number"); 1022 if (lua_isnil(L, 3)) /* delete line */ 1023 { 1024 buf_T *buf = curbuf; 1025 curbuf = b; 1026 if (u_savedel(n, 1L) == FAIL) 1027 { 1028 curbuf = buf; 1029 luaL_error(L, "cannot save undo information"); 1030 } 1031 else if (ml_delete(n, FALSE) == FAIL) 1032 { 1033 curbuf = buf; 1034 luaL_error(L, "cannot delete line"); 1035 } 1036 else { 1037 deleted_lines_mark(n, 1L); 1038 if (b == curwin->w_buffer) /* fix cursor in current window? */ 1039 { 1040 if (curwin->w_cursor.lnum >= n) 1041 { 1042 if (curwin->w_cursor.lnum > n) 1043 { 1044 curwin->w_cursor.lnum -= 1; 1045 check_cursor_col(); 1046 } 1047 else check_cursor(); 1048 changed_cline_bef_curs(); 1049 } 1050 invalidate_botline(); 1051 } 1052 } 1053 curbuf = buf; 1054 } 1055 else if (lua_isstring(L, 3)) /* update line */ 1056 { 1057 buf_T *buf = curbuf; 1058 curbuf = b; 1059 if (u_savesub(n) == FAIL) 1060 { 1061 curbuf = buf; 1062 luaL_error(L, "cannot save undo information"); 1063 } 1064 else if (ml_replace(n, luaV_toline(L, 3), TRUE) == FAIL) 1065 { 1066 curbuf = buf; 1067 luaL_error(L, "cannot replace line"); 1068 } 1069 else changed_bytes(n, 0); 1070 curbuf = buf; 1071 if (b == curwin->w_buffer) 1072 check_cursor_col(); 1073 } 1074 else 1075 luaL_error(L, "wrong argument to change line"); 1076 return 0; 1077 } 1078 1079 static int 1080 luaV_buffer_insert(lua_State *L) 1081 { 1082 luaV_Buffer *lb = luaV_checkudata(L, 1, LUAVIM_BUFFER); 1083 buf_T *b = (buf_T *) luaV_checkcache(L, (void *) *lb); 1084 linenr_T last = b->b_ml.ml_line_count; 1085 linenr_T n = (linenr_T) luaL_optinteger(L, 3, last); 1086 buf_T *buf; 1087 luaL_checktype(L, 2, LUA_TSTRING); 1088 #ifdef HAVE_SANDBOX 1089 luaV_checksandbox(L); 1090 #endif 1091 /* fix insertion line */ 1092 if (n < 0) n = 0; 1093 if (n > last) n = last; 1094 /* insert */ 1095 buf = curbuf; 1096 curbuf = b; 1097 if (u_save(n, n + 1) == FAIL) 1098 { 1099 curbuf = buf; 1100 luaL_error(L, "cannot save undo information"); 1101 } 1102 else if (ml_append(n, luaV_toline(L, 2), 0, FALSE) == FAIL) 1103 { 1104 curbuf = buf; 1105 luaL_error(L, "cannot insert line"); 1106 } 1107 else 1108 appended_lines_mark(n, 1L); 1109 curbuf = buf; 1110 update_screen(VALID); 1111 return 0; 1112 } 1113 1114 static int 1115 luaV_buffer_next(lua_State *L) 1116 { 1117 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); 1118 buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b); 1119 luaV_pushbuffer(L, buf->b_next); 1120 return 1; 1121 } 1122 1123 static int 1124 luaV_buffer_previous(lua_State *L) 1125 { 1126 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); 1127 buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b); 1128 luaV_pushbuffer(L, buf->b_prev); 1129 return 1; 1130 } 1131 1132 static int 1133 luaV_buffer_isvalid(lua_State *L) 1134 { 1135 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); 1136 luaV_getudata(L, *b); 1137 lua_pushboolean(L, !lua_isnil(L, -1)); 1138 return 1; 1139 } 1140 1141 static const luaL_Reg luaV_Buffer_mt[] = { 1142 {"__tostring", luaV_buffer_tostring}, 1143 {"__len", luaV_buffer_len}, 1144 {"__call", luaV_buffer_call}, 1145 {"__index", luaV_buffer_index}, 1146 {"__newindex", luaV_buffer_newindex}, 1147 {"insert", luaV_buffer_insert}, 1148 {"next", luaV_buffer_next}, 1149 {"previous", luaV_buffer_previous}, 1150 {"isvalid", luaV_buffer_isvalid}, 1151 {NULL, NULL} 1152 }; 1153 1154 1155 /* ======= Window type ======= */ 1156 1157 luaV_newtype(win_T, window, luaV_Window, LUAVIM_WINDOW) 1158 luaV_pushtype(win_T, window, luaV_Window) 1159 luaV_type_tostring(window, LUAVIM_WINDOW) 1160 1161 static int 1162 luaV_window_call(lua_State *L) 1163 { 1164 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1); 1165 lua_settop(L, 1); 1166 win_goto(w); 1167 return 1; 1168 } 1169 1170 static int 1171 luaV_window_index(lua_State *L) 1172 { 1173 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1); 1174 const char *s = luaL_checkstring(L, 2); 1175 if (strncmp(s, "buffer", 6) == 0) 1176 luaV_pushbuffer(L, w->w_buffer); 1177 else if (strncmp(s, "line", 4) == 0) 1178 lua_pushinteger(L, w->w_cursor.lnum); 1179 else if (strncmp(s, "col", 3) == 0) 1180 lua_pushinteger(L, w->w_cursor.col + 1); 1181 #ifdef FEAT_WINDOWS 1182 else if (strncmp(s, "width", 5) == 0) 1183 lua_pushinteger(L, W_WIDTH(w)); 1184 #endif 1185 else if (strncmp(s, "height", 6) == 0) 1186 lua_pushinteger(L, w->w_height); 1187 /* methods */ 1188 else if (strncmp(s, "next", 4) == 0 1189 || strncmp(s, "previous", 8) == 0 1190 || strncmp(s, "isvalid", 7) == 0) 1191 { 1192 lua_getmetatable(L, 1); 1193 lua_getfield(L, -1, s); 1194 } 1195 else 1196 lua_pushnil(L); 1197 return 1; 1198 } 1199 1200 static int 1201 luaV_window_newindex (lua_State *L) 1202 { 1203 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1); 1204 const char *s = luaL_checkstring(L, 2); 1205 int v = luaL_checkinteger(L, 3); 1206 if (strncmp(s, "line", 4) == 0) 1207 { 1208 #ifdef HAVE_SANDBOX 1209 luaV_checksandbox(L); 1210 #endif 1211 if (v < 1 || v > w->w_buffer->b_ml.ml_line_count) 1212 luaL_error(L, "line out of range"); 1213 w->w_cursor.lnum = v; 1214 update_screen(VALID); 1215 } 1216 else if (strncmp(s, "col", 3) == 0) 1217 { 1218 #ifdef HAVE_SANDBOX 1219 luaV_checksandbox(L); 1220 #endif 1221 w->w_cursor.col = v - 1; 1222 update_screen(VALID); 1223 } 1224 #ifdef FEAT_WINDOWS 1225 else if (strncmp(s, "width", 5) == 0) 1226 { 1227 win_T *win = curwin; 1228 #ifdef FEAT_GUI 1229 need_mouse_correct = TRUE; 1230 #endif 1231 curwin = w; 1232 win_setwidth(v); 1233 curwin = win; 1234 } 1235 #endif 1236 else if (strncmp(s, "height", 6) == 0) 1237 { 1238 win_T *win = curwin; 1239 #ifdef FEAT_GUI 1240 need_mouse_correct = TRUE; 1241 #endif 1242 curwin = w; 1243 win_setheight(v); 1244 curwin = win; 1245 } 1246 else 1247 luaL_error(L, "invalid window property: `%s'", s); 1248 return 0; 1249 } 1250 1251 static int 1252 luaV_window_next(lua_State *L) 1253 { 1254 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); 1255 win_T *win = (win_T *) luaV_checkcache(L, (void *) *w); 1256 luaV_pushwindow(L, win->w_next); 1257 return 1; 1258 } 1259 1260 static int 1261 luaV_window_previous(lua_State *L) 1262 { 1263 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); 1264 win_T *win = (win_T *) luaV_checkcache(L, (void *) *w); 1265 luaV_pushwindow(L, win->w_prev); 1266 return 1; 1267 } 1268 1269 static int 1270 luaV_window_isvalid(lua_State *L) 1271 { 1272 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); 1273 luaV_getudata(L, *w); 1274 lua_pushboolean(L, !lua_isnil(L, -1)); 1275 return 1; 1276 } 1277 1278 static const luaL_Reg luaV_Window_mt[] = { 1279 {"__tostring", luaV_window_tostring}, 1280 {"__call", luaV_window_call}, 1281 {"__index", luaV_window_index}, 1282 {"__newindex", luaV_window_newindex}, 1283 {"next", luaV_window_next}, 1284 {"previous", luaV_window_previous}, 1285 {"isvalid", luaV_window_isvalid}, 1286 {NULL, NULL} 1287 }; 1288 1289 1290 /* ======= Vim module ======= */ 1291 1292 static int 1293 luaV_print(lua_State *L) 1294 { 1295 int i, n = lua_gettop(L); /* nargs */ 1296 const char *s; 1297 size_t l; 1298 luaL_Buffer b; 1299 luaL_buffinit(L, &b); 1300 lua_getglobal(L, "tostring"); 1301 for (i = 1; i <= n; i++) 1302 { 1303 lua_pushvalue(L, -1); /* tostring */ 1304 lua_pushvalue(L, i); /* arg */ 1305 lua_call(L, 1, 1); 1306 s = lua_tolstring(L, -1, &l); 1307 if (s == NULL) 1308 return luaL_error(L, "cannot convert to string"); 1309 if (i > 1) luaL_addchar(&b, ' '); /* use space instead of tab */ 1310 luaV_addlstring(&b, s, l, 0); 1311 lua_pop(L, 1); 1312 } 1313 luaL_pushresult(&b); 1314 luaV_msg(L); 1315 return 0; 1316 } 1317 1318 static int 1319 luaV_debug(lua_State *L) 1320 { 1321 lua_settop(L, 0); 1322 lua_getglobal(L, "vim"); 1323 lua_getfield(L, -1, "eval"); 1324 lua_remove(L, -2); /* vim.eval at position 1 */ 1325 for (;;) 1326 { 1327 const char *input; 1328 size_t l; 1329 lua_pushvalue(L, 1); /* vim.eval */ 1330 lua_pushliteral(L, "input('lua_debug> ')"); 1331 lua_call(L, 1, 1); /* return string */ 1332 input = lua_tolstring(L, -1, &l); 1333 if (l == 0 || strcmp(input, "cont") == 0) 1334 return 0; 1335 msg_putchar('\n'); /* avoid outputting on input line */ 1336 if (luaL_loadbuffer(L, input, l, "=(debug command)") 1337 || lua_pcall(L, 0, 0, 0)) 1338 luaV_emsg(L); 1339 lua_settop(L, 1); /* remove eventual returns, but keep vim.eval */ 1340 } 1341 } 1342 1343 static int 1344 luaV_command(lua_State *L) 1345 { 1346 do_cmdline_cmd((char_u *) luaL_checkstring(L, 1)); 1347 update_screen(VALID); 1348 return 0; 1349 } 1350 1351 static int 1352 luaV_eval(lua_State *L) 1353 { 1354 typval_T *tv = eval_expr((char_u *) luaL_checkstring(L, 1), NULL); 1355 if (tv == NULL) luaL_error(L, "invalid expression"); 1356 luaV_pushtypval(L, tv); 1357 free_tv(tv); 1358 return 1; 1359 } 1360 1361 static int 1362 luaV_beep(lua_State *L UNUSED) 1363 { 1364 vim_beep(BO_LANG); 1365 return 0; 1366 } 1367 1368 static int 1369 luaV_line(lua_State *L) 1370 { 1371 luaV_pushline(L, curbuf, curwin->w_cursor.lnum); 1372 return 1; 1373 } 1374 1375 static int 1376 luaV_list(lua_State *L) 1377 { 1378 list_T *l = list_alloc(); 1379 if (l == NULL) 1380 lua_pushnil(L); 1381 else 1382 luaV_newlist(L, l); 1383 return 1; 1384 } 1385 1386 static int 1387 luaV_dict(lua_State *L) 1388 { 1389 dict_T *d = dict_alloc(); 1390 if (d == NULL) 1391 lua_pushnil(L); 1392 else 1393 luaV_newdict(L, d); 1394 return 1; 1395 } 1396 1397 static int 1398 luaV_buffer(lua_State *L) 1399 { 1400 buf_T *buf; 1401 if (lua_isstring(L, 1)) /* get by number or name? */ 1402 { 1403 if (lua_isnumber(L, 1)) /* by number? */ 1404 { 1405 int n = lua_tointeger(L, 1); 1406 FOR_ALL_BUFFERS(buf) 1407 if (buf->b_fnum == n) break; 1408 } 1409 else { /* by name */ 1410 size_t l; 1411 const char *s = lua_tolstring(L, 1, &l); 1412 FOR_ALL_BUFFERS(buf) 1413 { 1414 if (buf->b_ffname == NULL || buf->b_sfname == NULL) 1415 { 1416 if (l == 0) break; 1417 } 1418 else if (strncmp(s, (char *)buf->b_ffname, l) == 0 1419 || strncmp(s, (char *)buf->b_sfname, l) == 0) 1420 break; 1421 } 1422 } 1423 } 1424 else 1425 buf = (lua_toboolean(L, 1)) ? firstbuf : curbuf; /* first buffer? */ 1426 luaV_pushbuffer(L, buf); 1427 return 1; 1428 } 1429 1430 static int 1431 luaV_window(lua_State *L) 1432 { 1433 win_T *win; 1434 if (lua_isnumber(L, 1)) /* get by number? */ 1435 { 1436 int n = lua_tointeger(L, 1); 1437 for (win = firstwin; win != NULL; win = win->w_next, n--) 1438 if (n == 1) break; 1439 } 1440 else 1441 win = (lua_toboolean(L, 1)) ? firstwin : curwin; /* first window? */ 1442 luaV_pushwindow(L, win); 1443 return 1; 1444 } 1445 1446 static int 1447 luaV_open(lua_State *L) 1448 { 1449 char_u *s = NULL; 1450 #ifdef HAVE_SANDBOX 1451 luaV_checksandbox(L); 1452 #endif 1453 if (lua_isstring(L, 1)) s = (char_u *) lua_tostring(L, 1); 1454 luaV_pushbuffer(L, buflist_new(s, NULL, 1L, BLN_LISTED)); 1455 return 1; 1456 } 1457 1458 static int 1459 luaV_type(lua_State *L) 1460 { 1461 luaL_checkany(L, 1); 1462 if (lua_type(L, 1) == LUA_TUSERDATA) /* check vim udata? */ 1463 { 1464 lua_settop(L, 1); 1465 if (lua_getmetatable(L, 1)) 1466 { 1467 luaV_getfield(L, LUAVIM_LIST); 1468 if (lua_rawequal(L, -1, 2)) 1469 { 1470 lua_pushstring(L, "list"); 1471 return 1; 1472 } 1473 luaV_getfield(L, LUAVIM_DICT); 1474 if (lua_rawequal(L, -1, 2)) 1475 { 1476 lua_pushstring(L, "dict"); 1477 return 1; 1478 } 1479 luaV_getfield(L, LUAVIM_BUFFER); 1480 if (lua_rawequal(L, -1, 2)) 1481 { 1482 lua_pushstring(L, "buffer"); 1483 return 1; 1484 } 1485 luaV_getfield(L, LUAVIM_WINDOW); 1486 if (lua_rawequal(L, -1, 2)) 1487 { 1488 lua_pushstring(L, "window"); 1489 return 1; 1490 } 1491 } 1492 } 1493 lua_pushstring(L, luaL_typename(L, 1)); /* fallback */ 1494 return 1; 1495 } 1496 1497 static const luaL_Reg luaV_module[] = { 1498 {"command", luaV_command}, 1499 {"eval", luaV_eval}, 1500 {"beep", luaV_beep}, 1501 {"line", luaV_line}, 1502 {"list", luaV_list}, 1503 {"dict", luaV_dict}, 1504 {"buffer", luaV_buffer}, 1505 {"window", luaV_window}, 1506 {"open", luaV_open}, 1507 {"type", luaV_type}, 1508 {NULL, NULL} 1509 }; 1510 1511 /* for freeing list, dict, buffer and window objects; lightuserdata as arg */ 1512 static int 1513 luaV_free(lua_State *L) 1514 { 1515 lua_pushnil(L); 1516 luaV_setudata(L, lua_touserdata(L, 1)); 1517 return 0; 1518 } 1519 1520 static int 1521 luaV_luaeval (lua_State *L) 1522 { 1523 luaL_Buffer b; 1524 size_t l; 1525 const char *str = lua_tolstring(L, 1, &l); 1526 typval_T *arg = (typval_T *) lua_touserdata(L, 2); 1527 typval_T *rettv = (typval_T *) lua_touserdata(L, 3); 1528 luaL_buffinit(L, &b); 1529 luaL_addlstring(&b, LUAVIM_EVALHEADER, sizeof(LUAVIM_EVALHEADER) - 1); 1530 luaL_addlstring(&b, str, l); 1531 luaL_pushresult(&b); 1532 str = lua_tolstring(L, -1, &l); 1533 if (luaL_loadbuffer(L, str, l, LUAVIM_EVALNAME)) /* compile error? */ 1534 { 1535 luaV_emsg(L); 1536 return 0; 1537 } 1538 luaV_pushtypval(L, arg); 1539 if (lua_pcall(L, 1, 1, 0)) /* running error? */ 1540 { 1541 luaV_emsg(L); 1542 return 0; 1543 } 1544 luaV_totypval(L, -1, rettv); 1545 return 0; 1546 } 1547 1548 static int 1549 luaV_setref (lua_State *L) 1550 { 1551 int copyID = lua_tointeger(L, 1); 1552 int abort = FALSE; 1553 typval_T tv; 1554 1555 luaV_getfield(L, LUAVIM_LIST); 1556 luaV_getfield(L, LUAVIM_DICT); 1557 lua_pushnil(L); 1558 /* traverse cache table */ 1559 while (!abort && lua_next(L, lua_upvalueindex(1)) != 0) 1560 { 1561 lua_getmetatable(L, -1); 1562 if (lua_rawequal(L, -1, 2)) /* list? */ 1563 { 1564 tv.v_type = VAR_LIST; 1565 tv.vval.v_list = (list_T *) lua_touserdata(L, 4); /* key */ 1566 abort = set_ref_in_item(&tv, copyID, NULL, NULL); 1567 } 1568 else if (lua_rawequal(L, -1, 3)) /* dict? */ 1569 { 1570 tv.v_type = VAR_DICT; 1571 tv.vval.v_dict = (dict_T *) lua_touserdata(L, 4); /* key */ 1572 abort = set_ref_in_item(&tv, copyID, NULL, NULL); 1573 } 1574 lua_pop(L, 2); /* metatable and value */ 1575 } 1576 lua_pushinteger(L, abort); 1577 return 1; 1578 } 1579 1580 static int 1581 luaopen_vim(lua_State *L) 1582 { 1583 /* set cache table */ 1584 lua_newtable(L); 1585 lua_newtable(L); 1586 lua_pushstring(L, "v"); 1587 lua_setfield(L, -2, "__mode"); 1588 lua_setmetatable(L, -2); /* cache is weak-valued */ 1589 /* print */ 1590 lua_pushcfunction(L, luaV_print); 1591 lua_setglobal(L, "print"); 1592 /* debug.debug */ 1593 lua_getglobal(L, "debug"); 1594 lua_pushcfunction(L, luaV_debug); 1595 lua_setfield(L, -2, "debug"); 1596 lua_pop(L, 1); 1597 /* free */ 1598 lua_pushlightuserdata(L, (void *) LUAVIM_FREE); 1599 lua_pushvalue(L, 1); /* cache table */ 1600 lua_pushcclosure(L, luaV_free, 1); 1601 lua_rawset(L, LUA_REGISTRYINDEX); 1602 /* luaeval */ 1603 lua_pushlightuserdata(L, (void *) LUAVIM_LUAEVAL); 1604 lua_pushvalue(L, 1); /* cache table */ 1605 lua_pushcclosure(L, luaV_luaeval, 1); 1606 lua_rawset(L, LUA_REGISTRYINDEX); 1607 /* setref */ 1608 lua_pushlightuserdata(L, (void *) LUAVIM_SETREF); 1609 lua_pushvalue(L, 1); /* cache table */ 1610 lua_pushcclosure(L, luaV_setref, 1); 1611 lua_rawset(L, LUA_REGISTRYINDEX); 1612 /* register */ 1613 luaV_newmetatable(L, LUAVIM_LIST); 1614 lua_pushvalue(L, 1); 1615 luaV_openlib(L, luaV_List_mt, 1); 1616 luaV_newmetatable(L, LUAVIM_DICT); 1617 lua_pushvalue(L, 1); 1618 luaV_openlib(L, luaV_Dict_mt, 1); 1619 luaV_newmetatable(L, LUAVIM_BUFFER); 1620 lua_pushvalue(L, 1); /* cache table */ 1621 luaV_openlib(L, luaV_Buffer_mt, 1); 1622 luaV_newmetatable(L, LUAVIM_WINDOW); 1623 lua_pushvalue(L, 1); /* cache table */ 1624 luaV_openlib(L, luaV_Window_mt, 1); 1625 lua_newtable(L); /* vim table */ 1626 lua_pushvalue(L, 1); /* cache table */ 1627 luaV_openlib(L, luaV_module, 1); 1628 lua_setglobal(L, LUAVIM_NAME); 1629 return 0; 1630 } 1631 1632 static lua_State * 1633 luaV_newstate(void) 1634 { 1635 lua_State *L = luaL_newstate(); 1636 luaL_openlibs(L); /* core libs */ 1637 lua_pushcfunction(L, luaopen_vim); /* vim */ 1638 lua_call(L, 0, 0); 1639 return L; 1640 } 1641 1642 static void 1643 luaV_setrange(lua_State *L, int line1, int line2) 1644 { 1645 lua_getglobal(L, LUAVIM_NAME); 1646 lua_pushinteger(L, line1); 1647 lua_setfield(L, -2, "firstline"); 1648 lua_pushinteger(L, line2); 1649 lua_setfield(L, -2, "lastline"); 1650 lua_pop(L, 1); /* vim table */ 1651 } 1652 1653 1654 /* ======= Interface ======= */ 1655 1656 static lua_State *L = NULL; 1657 1658 static int 1659 lua_isopen(void) 1660 { 1661 return L != NULL; 1662 } 1663 1664 static int 1665 lua_init(void) 1666 { 1667 if (!lua_isopen()) 1668 { 1669 #ifdef DYNAMIC_LUA 1670 if (!lua_enabled(TRUE)) 1671 { 1672 EMSG(_("Lua library cannot be loaded.")); 1673 return FAIL; 1674 } 1675 #endif 1676 L = luaV_newstate(); 1677 } 1678 return OK; 1679 } 1680 1681 void 1682 lua_end(void) 1683 { 1684 if (lua_isopen()) 1685 { 1686 lua_close(L); 1687 L = NULL; 1688 #ifdef DYNAMIC_LUA 1689 end_dynamic_lua(); 1690 #endif 1691 } 1692 } 1693 1694 /* ex commands */ 1695 void 1696 ex_lua(exarg_T *eap) 1697 { 1698 char *script; 1699 if (lua_init() == FAIL) return; 1700 script = (char *) script_get(eap, eap->arg); 1701 if (!eap->skip) 1702 { 1703 char *s = (script) ? script : (char *) eap->arg; 1704 luaV_setrange(L, eap->line1, eap->line2); 1705 if (luaL_loadbuffer(L, s, strlen(s), LUAVIM_CHUNKNAME) 1706 || lua_pcall(L, 0, 0, 0)) 1707 luaV_emsg(L); 1708 } 1709 if (script != NULL) vim_free(script); 1710 } 1711 1712 void 1713 ex_luado(exarg_T *eap) 1714 { 1715 linenr_T l; 1716 const char *s = (const char *) eap->arg; 1717 luaL_Buffer b; 1718 size_t len; 1719 if (lua_init() == FAIL) return; 1720 if (u_save(eap->line1 - 1, eap->line2 + 1) == FAIL) 1721 { 1722 EMSG(_("cannot save undo information")); 1723 return; 1724 } 1725 luaV_setrange(L, eap->line1, eap->line2); 1726 luaL_buffinit(L, &b); 1727 luaL_addlstring(&b, "return function(line, linenr) ", 30); /* header */ 1728 luaL_addlstring(&b, s, strlen(s)); 1729 luaL_addlstring(&b, " end", 4); /* footer */ 1730 luaL_pushresult(&b); 1731 s = lua_tolstring(L, -1, &len); 1732 if (luaL_loadbuffer(L, s, len, LUAVIM_CHUNKNAME)) 1733 { 1734 luaV_emsg(L); 1735 lua_pop(L, 1); /* function body */ 1736 return; 1737 } 1738 lua_call(L, 0, 1); 1739 lua_replace(L, -2); /* function -> body */ 1740 for (l = eap->line1; l <= eap->line2; l++) 1741 { 1742 lua_pushvalue(L, -1); /* function */ 1743 luaV_pushline(L, curbuf, l); /* current line as arg */ 1744 lua_pushinteger(L, l); /* current line number as arg */ 1745 if (lua_pcall(L, 2, 1, 0)) 1746 { 1747 luaV_emsg(L); 1748 break; 1749 } 1750 if (lua_isstring(L, -1)) /* update line? */ 1751 { 1752 #ifdef HAVE_SANDBOX 1753 luaV_checksandbox(L); 1754 #endif 1755 ml_replace(l, luaV_toline(L, -1), TRUE); 1756 changed_bytes(l, 0); 1757 lua_pop(L, 1); /* result from luaV_toline */ 1758 } 1759 lua_pop(L, 1); /* line */ 1760 } 1761 lua_pop(L, 1); /* function */ 1762 check_cursor(); 1763 update_screen(NOT_VALID); 1764 } 1765 1766 void 1767 ex_luafile(exarg_T *eap) 1768 { 1769 if (lua_init() == FAIL) 1770 return; 1771 if (!eap->skip) 1772 { 1773 luaV_setrange(L, eap->line1, eap->line2); 1774 if (luaL_loadfile(L, (char *) eap->arg) || lua_pcall(L, 0, 0, 0)) 1775 luaV_emsg(L); 1776 } 1777 } 1778 1779 #define luaV_freetype(typ,tname) \ 1780 void \ 1781 lua_##tname##_free(typ *o) \ 1782 { \ 1783 if (!lua_isopen()) return; \ 1784 luaV_getfield(L, LUAVIM_FREE); \ 1785 lua_pushlightuserdata(L, (void *) o); \ 1786 lua_call(L, 1, 0); \ 1787 } 1788 1789 luaV_freetype(buf_T, buffer) 1790 luaV_freetype(win_T, window) 1791 1792 void 1793 do_luaeval (char_u *str, typval_T *arg, typval_T *rettv) 1794 { 1795 lua_init(); 1796 luaV_getfield(L, LUAVIM_LUAEVAL); 1797 lua_pushstring(L, (char *) str); 1798 lua_pushlightuserdata(L, (void *) arg); 1799 lua_pushlightuserdata(L, (void *) rettv); 1800 lua_call(L, 3, 0); 1801 } 1802 1803 int 1804 set_ref_in_lua (int copyID) 1805 { 1806 int aborted = 0; 1807 1808 if (lua_isopen()) 1809 { 1810 luaV_getfield(L, LUAVIM_SETREF); 1811 /* call the function with 1 arg, getting 1 result back */ 1812 lua_pushinteger(L, copyID); 1813 lua_call(L, 1, 1); 1814 /* get the result */ 1815 aborted = lua_tointeger(L, -1); 1816 /* pop result off the stack */ 1817 lua_pop(L, 1); 1818 } 1819 return aborted; 1820 } 1821 1822 #endif 1823