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 else if (strncmp(s, "width", 5) == 0) 1182 lua_pushinteger(L, w->w_width); 1183 else if (strncmp(s, "height", 6) == 0) 1184 lua_pushinteger(L, w->w_height); 1185 /* methods */ 1186 else if (strncmp(s, "next", 4) == 0 1187 || strncmp(s, "previous", 8) == 0 1188 || strncmp(s, "isvalid", 7) == 0) 1189 { 1190 lua_getmetatable(L, 1); 1191 lua_getfield(L, -1, s); 1192 } 1193 else 1194 lua_pushnil(L); 1195 return 1; 1196 } 1197 1198 static int 1199 luaV_window_newindex (lua_State *L) 1200 { 1201 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1); 1202 const char *s = luaL_checkstring(L, 2); 1203 int v = luaL_checkinteger(L, 3); 1204 if (strncmp(s, "line", 4) == 0) 1205 { 1206 #ifdef HAVE_SANDBOX 1207 luaV_checksandbox(L); 1208 #endif 1209 if (v < 1 || v > w->w_buffer->b_ml.ml_line_count) 1210 luaL_error(L, "line out of range"); 1211 w->w_cursor.lnum = v; 1212 update_screen(VALID); 1213 } 1214 else if (strncmp(s, "col", 3) == 0) 1215 { 1216 #ifdef HAVE_SANDBOX 1217 luaV_checksandbox(L); 1218 #endif 1219 w->w_cursor.col = v - 1; 1220 update_screen(VALID); 1221 } 1222 else if (strncmp(s, "width", 5) == 0) 1223 { 1224 win_T *win = curwin; 1225 #ifdef FEAT_GUI 1226 need_mouse_correct = TRUE; 1227 #endif 1228 curwin = w; 1229 win_setwidth(v); 1230 curwin = win; 1231 } 1232 else if (strncmp(s, "height", 6) == 0) 1233 { 1234 win_T *win = curwin; 1235 #ifdef FEAT_GUI 1236 need_mouse_correct = TRUE; 1237 #endif 1238 curwin = w; 1239 win_setheight(v); 1240 curwin = win; 1241 } 1242 else 1243 luaL_error(L, "invalid window property: `%s'", s); 1244 return 0; 1245 } 1246 1247 static int 1248 luaV_window_next(lua_State *L) 1249 { 1250 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); 1251 win_T *win = (win_T *) luaV_checkcache(L, (void *) *w); 1252 luaV_pushwindow(L, win->w_next); 1253 return 1; 1254 } 1255 1256 static int 1257 luaV_window_previous(lua_State *L) 1258 { 1259 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); 1260 win_T *win = (win_T *) luaV_checkcache(L, (void *) *w); 1261 luaV_pushwindow(L, win->w_prev); 1262 return 1; 1263 } 1264 1265 static int 1266 luaV_window_isvalid(lua_State *L) 1267 { 1268 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); 1269 luaV_getudata(L, *w); 1270 lua_pushboolean(L, !lua_isnil(L, -1)); 1271 return 1; 1272 } 1273 1274 static const luaL_Reg luaV_Window_mt[] = { 1275 {"__tostring", luaV_window_tostring}, 1276 {"__call", luaV_window_call}, 1277 {"__index", luaV_window_index}, 1278 {"__newindex", luaV_window_newindex}, 1279 {"next", luaV_window_next}, 1280 {"previous", luaV_window_previous}, 1281 {"isvalid", luaV_window_isvalid}, 1282 {NULL, NULL} 1283 }; 1284 1285 1286 /* ======= Vim module ======= */ 1287 1288 static int 1289 luaV_print(lua_State *L) 1290 { 1291 int i, n = lua_gettop(L); /* nargs */ 1292 const char *s; 1293 size_t l; 1294 luaL_Buffer b; 1295 luaL_buffinit(L, &b); 1296 lua_getglobal(L, "tostring"); 1297 for (i = 1; i <= n; i++) 1298 { 1299 lua_pushvalue(L, -1); /* tostring */ 1300 lua_pushvalue(L, i); /* arg */ 1301 lua_call(L, 1, 1); 1302 s = lua_tolstring(L, -1, &l); 1303 if (s == NULL) 1304 return luaL_error(L, "cannot convert to string"); 1305 if (i > 1) luaL_addchar(&b, ' '); /* use space instead of tab */ 1306 luaV_addlstring(&b, s, l, 0); 1307 lua_pop(L, 1); 1308 } 1309 luaL_pushresult(&b); 1310 luaV_msg(L); 1311 return 0; 1312 } 1313 1314 static int 1315 luaV_debug(lua_State *L) 1316 { 1317 lua_settop(L, 0); 1318 lua_getglobal(L, "vim"); 1319 lua_getfield(L, -1, "eval"); 1320 lua_remove(L, -2); /* vim.eval at position 1 */ 1321 for (;;) 1322 { 1323 const char *input; 1324 size_t l; 1325 lua_pushvalue(L, 1); /* vim.eval */ 1326 lua_pushliteral(L, "input('lua_debug> ')"); 1327 lua_call(L, 1, 1); /* return string */ 1328 input = lua_tolstring(L, -1, &l); 1329 if (l == 0 || strcmp(input, "cont") == 0) 1330 return 0; 1331 msg_putchar('\n'); /* avoid outputting on input line */ 1332 if (luaL_loadbuffer(L, input, l, "=(debug command)") 1333 || lua_pcall(L, 0, 0, 0)) 1334 luaV_emsg(L); 1335 lua_settop(L, 1); /* remove eventual returns, but keep vim.eval */ 1336 } 1337 } 1338 1339 static int 1340 luaV_command(lua_State *L) 1341 { 1342 do_cmdline_cmd((char_u *) luaL_checkstring(L, 1)); 1343 update_screen(VALID); 1344 return 0; 1345 } 1346 1347 static int 1348 luaV_eval(lua_State *L) 1349 { 1350 typval_T *tv = eval_expr((char_u *) luaL_checkstring(L, 1), NULL); 1351 if (tv == NULL) luaL_error(L, "invalid expression"); 1352 luaV_pushtypval(L, tv); 1353 free_tv(tv); 1354 return 1; 1355 } 1356 1357 static int 1358 luaV_beep(lua_State *L UNUSED) 1359 { 1360 vim_beep(BO_LANG); 1361 return 0; 1362 } 1363 1364 static int 1365 luaV_line(lua_State *L) 1366 { 1367 luaV_pushline(L, curbuf, curwin->w_cursor.lnum); 1368 return 1; 1369 } 1370 1371 static int 1372 luaV_list(lua_State *L) 1373 { 1374 list_T *l = list_alloc(); 1375 if (l == NULL) 1376 lua_pushnil(L); 1377 else 1378 luaV_newlist(L, l); 1379 return 1; 1380 } 1381 1382 static int 1383 luaV_dict(lua_State *L) 1384 { 1385 dict_T *d = dict_alloc(); 1386 if (d == NULL) 1387 lua_pushnil(L); 1388 else 1389 luaV_newdict(L, d); 1390 return 1; 1391 } 1392 1393 static int 1394 luaV_buffer(lua_State *L) 1395 { 1396 buf_T *buf; 1397 if (lua_isstring(L, 1)) /* get by number or name? */ 1398 { 1399 if (lua_isnumber(L, 1)) /* by number? */ 1400 { 1401 int n = lua_tointeger(L, 1); 1402 FOR_ALL_BUFFERS(buf) 1403 if (buf->b_fnum == n) break; 1404 } 1405 else { /* by name */ 1406 size_t l; 1407 const char *s = lua_tolstring(L, 1, &l); 1408 FOR_ALL_BUFFERS(buf) 1409 { 1410 if (buf->b_ffname == NULL || buf->b_sfname == NULL) 1411 { 1412 if (l == 0) break; 1413 } 1414 else if (strncmp(s, (char *)buf->b_ffname, l) == 0 1415 || strncmp(s, (char *)buf->b_sfname, l) == 0) 1416 break; 1417 } 1418 } 1419 } 1420 else 1421 buf = (lua_toboolean(L, 1)) ? firstbuf : curbuf; /* first buffer? */ 1422 luaV_pushbuffer(L, buf); 1423 return 1; 1424 } 1425 1426 static int 1427 luaV_window(lua_State *L) 1428 { 1429 win_T *win; 1430 if (lua_isnumber(L, 1)) /* get by number? */ 1431 { 1432 int n = lua_tointeger(L, 1); 1433 for (win = firstwin; win != NULL; win = win->w_next, n--) 1434 if (n == 1) break; 1435 } 1436 else 1437 win = (lua_toboolean(L, 1)) ? firstwin : curwin; /* first window? */ 1438 luaV_pushwindow(L, win); 1439 return 1; 1440 } 1441 1442 static int 1443 luaV_open(lua_State *L) 1444 { 1445 char_u *s = NULL; 1446 #ifdef HAVE_SANDBOX 1447 luaV_checksandbox(L); 1448 #endif 1449 if (lua_isstring(L, 1)) s = (char_u *) lua_tostring(L, 1); 1450 luaV_pushbuffer(L, buflist_new(s, NULL, 1L, BLN_LISTED)); 1451 return 1; 1452 } 1453 1454 static int 1455 luaV_type(lua_State *L) 1456 { 1457 luaL_checkany(L, 1); 1458 if (lua_type(L, 1) == LUA_TUSERDATA) /* check vim udata? */ 1459 { 1460 lua_settop(L, 1); 1461 if (lua_getmetatable(L, 1)) 1462 { 1463 luaV_getfield(L, LUAVIM_LIST); 1464 if (lua_rawequal(L, -1, 2)) 1465 { 1466 lua_pushstring(L, "list"); 1467 return 1; 1468 } 1469 luaV_getfield(L, LUAVIM_DICT); 1470 if (lua_rawequal(L, -1, 2)) 1471 { 1472 lua_pushstring(L, "dict"); 1473 return 1; 1474 } 1475 luaV_getfield(L, LUAVIM_BUFFER); 1476 if (lua_rawequal(L, -1, 2)) 1477 { 1478 lua_pushstring(L, "buffer"); 1479 return 1; 1480 } 1481 luaV_getfield(L, LUAVIM_WINDOW); 1482 if (lua_rawequal(L, -1, 2)) 1483 { 1484 lua_pushstring(L, "window"); 1485 return 1; 1486 } 1487 } 1488 } 1489 lua_pushstring(L, luaL_typename(L, 1)); /* fallback */ 1490 return 1; 1491 } 1492 1493 static const luaL_Reg luaV_module[] = { 1494 {"command", luaV_command}, 1495 {"eval", luaV_eval}, 1496 {"beep", luaV_beep}, 1497 {"line", luaV_line}, 1498 {"list", luaV_list}, 1499 {"dict", luaV_dict}, 1500 {"buffer", luaV_buffer}, 1501 {"window", luaV_window}, 1502 {"open", luaV_open}, 1503 {"type", luaV_type}, 1504 {NULL, NULL} 1505 }; 1506 1507 /* for freeing list, dict, buffer and window objects; lightuserdata as arg */ 1508 static int 1509 luaV_free(lua_State *L) 1510 { 1511 lua_pushnil(L); 1512 luaV_setudata(L, lua_touserdata(L, 1)); 1513 return 0; 1514 } 1515 1516 static int 1517 luaV_luaeval (lua_State *L) 1518 { 1519 luaL_Buffer b; 1520 size_t l; 1521 const char *str = lua_tolstring(L, 1, &l); 1522 typval_T *arg = (typval_T *) lua_touserdata(L, 2); 1523 typval_T *rettv = (typval_T *) lua_touserdata(L, 3); 1524 luaL_buffinit(L, &b); 1525 luaL_addlstring(&b, LUAVIM_EVALHEADER, sizeof(LUAVIM_EVALHEADER) - 1); 1526 luaL_addlstring(&b, str, l); 1527 luaL_pushresult(&b); 1528 str = lua_tolstring(L, -1, &l); 1529 if (luaL_loadbuffer(L, str, l, LUAVIM_EVALNAME)) /* compile error? */ 1530 { 1531 luaV_emsg(L); 1532 return 0; 1533 } 1534 luaV_pushtypval(L, arg); 1535 if (lua_pcall(L, 1, 1, 0)) /* running error? */ 1536 { 1537 luaV_emsg(L); 1538 return 0; 1539 } 1540 luaV_totypval(L, -1, rettv); 1541 return 0; 1542 } 1543 1544 static int 1545 luaV_setref (lua_State *L) 1546 { 1547 int copyID = lua_tointeger(L, 1); 1548 int abort = FALSE; 1549 typval_T tv; 1550 1551 luaV_getfield(L, LUAVIM_LIST); 1552 luaV_getfield(L, LUAVIM_DICT); 1553 lua_pushnil(L); 1554 /* traverse cache table */ 1555 while (!abort && lua_next(L, lua_upvalueindex(1)) != 0) 1556 { 1557 lua_getmetatable(L, -1); 1558 if (lua_rawequal(L, -1, 2)) /* list? */ 1559 { 1560 tv.v_type = VAR_LIST; 1561 tv.vval.v_list = (list_T *) lua_touserdata(L, 4); /* key */ 1562 abort = set_ref_in_item(&tv, copyID, NULL, NULL); 1563 } 1564 else if (lua_rawequal(L, -1, 3)) /* dict? */ 1565 { 1566 tv.v_type = VAR_DICT; 1567 tv.vval.v_dict = (dict_T *) lua_touserdata(L, 4); /* key */ 1568 abort = set_ref_in_item(&tv, copyID, NULL, NULL); 1569 } 1570 lua_pop(L, 2); /* metatable and value */ 1571 } 1572 lua_pushinteger(L, abort); 1573 return 1; 1574 } 1575 1576 static int 1577 luaopen_vim(lua_State *L) 1578 { 1579 /* set cache table */ 1580 lua_newtable(L); 1581 lua_newtable(L); 1582 lua_pushstring(L, "v"); 1583 lua_setfield(L, -2, "__mode"); 1584 lua_setmetatable(L, -2); /* cache is weak-valued */ 1585 /* print */ 1586 lua_pushcfunction(L, luaV_print); 1587 lua_setglobal(L, "print"); 1588 /* debug.debug */ 1589 lua_getglobal(L, "debug"); 1590 lua_pushcfunction(L, luaV_debug); 1591 lua_setfield(L, -2, "debug"); 1592 lua_pop(L, 1); 1593 /* free */ 1594 lua_pushlightuserdata(L, (void *) LUAVIM_FREE); 1595 lua_pushvalue(L, 1); /* cache table */ 1596 lua_pushcclosure(L, luaV_free, 1); 1597 lua_rawset(L, LUA_REGISTRYINDEX); 1598 /* luaeval */ 1599 lua_pushlightuserdata(L, (void *) LUAVIM_LUAEVAL); 1600 lua_pushvalue(L, 1); /* cache table */ 1601 lua_pushcclosure(L, luaV_luaeval, 1); 1602 lua_rawset(L, LUA_REGISTRYINDEX); 1603 /* setref */ 1604 lua_pushlightuserdata(L, (void *) LUAVIM_SETREF); 1605 lua_pushvalue(L, 1); /* cache table */ 1606 lua_pushcclosure(L, luaV_setref, 1); 1607 lua_rawset(L, LUA_REGISTRYINDEX); 1608 /* register */ 1609 luaV_newmetatable(L, LUAVIM_LIST); 1610 lua_pushvalue(L, 1); 1611 luaV_openlib(L, luaV_List_mt, 1); 1612 luaV_newmetatable(L, LUAVIM_DICT); 1613 lua_pushvalue(L, 1); 1614 luaV_openlib(L, luaV_Dict_mt, 1); 1615 luaV_newmetatable(L, LUAVIM_BUFFER); 1616 lua_pushvalue(L, 1); /* cache table */ 1617 luaV_openlib(L, luaV_Buffer_mt, 1); 1618 luaV_newmetatable(L, LUAVIM_WINDOW); 1619 lua_pushvalue(L, 1); /* cache table */ 1620 luaV_openlib(L, luaV_Window_mt, 1); 1621 lua_newtable(L); /* vim table */ 1622 lua_pushvalue(L, 1); /* cache table */ 1623 luaV_openlib(L, luaV_module, 1); 1624 lua_setglobal(L, LUAVIM_NAME); 1625 return 0; 1626 } 1627 1628 static lua_State * 1629 luaV_newstate(void) 1630 { 1631 lua_State *L = luaL_newstate(); 1632 luaL_openlibs(L); /* core libs */ 1633 lua_pushcfunction(L, luaopen_vim); /* vim */ 1634 lua_call(L, 0, 0); 1635 return L; 1636 } 1637 1638 static void 1639 luaV_setrange(lua_State *L, int line1, int line2) 1640 { 1641 lua_getglobal(L, LUAVIM_NAME); 1642 lua_pushinteger(L, line1); 1643 lua_setfield(L, -2, "firstline"); 1644 lua_pushinteger(L, line2); 1645 lua_setfield(L, -2, "lastline"); 1646 lua_pop(L, 1); /* vim table */ 1647 } 1648 1649 1650 /* ======= Interface ======= */ 1651 1652 static lua_State *L = NULL; 1653 1654 static int 1655 lua_isopen(void) 1656 { 1657 return L != NULL; 1658 } 1659 1660 static int 1661 lua_init(void) 1662 { 1663 if (!lua_isopen()) 1664 { 1665 #ifdef DYNAMIC_LUA 1666 if (!lua_enabled(TRUE)) 1667 { 1668 EMSG(_("Lua library cannot be loaded.")); 1669 return FAIL; 1670 } 1671 #endif 1672 L = luaV_newstate(); 1673 } 1674 return OK; 1675 } 1676 1677 void 1678 lua_end(void) 1679 { 1680 if (lua_isopen()) 1681 { 1682 lua_close(L); 1683 L = NULL; 1684 #ifdef DYNAMIC_LUA 1685 end_dynamic_lua(); 1686 #endif 1687 } 1688 } 1689 1690 /* ex commands */ 1691 void 1692 ex_lua(exarg_T *eap) 1693 { 1694 char *script; 1695 if (lua_init() == FAIL) return; 1696 script = (char *) script_get(eap, eap->arg); 1697 if (!eap->skip) 1698 { 1699 char *s = (script) ? script : (char *) eap->arg; 1700 luaV_setrange(L, eap->line1, eap->line2); 1701 if (luaL_loadbuffer(L, s, strlen(s), LUAVIM_CHUNKNAME) 1702 || lua_pcall(L, 0, 0, 0)) 1703 luaV_emsg(L); 1704 } 1705 if (script != NULL) vim_free(script); 1706 } 1707 1708 void 1709 ex_luado(exarg_T *eap) 1710 { 1711 linenr_T l; 1712 const char *s = (const char *) eap->arg; 1713 luaL_Buffer b; 1714 size_t len; 1715 buf_T *was_curbuf = curbuf; 1716 1717 if (lua_init() == FAIL) return; 1718 if (u_save(eap->line1 - 1, eap->line2 + 1) == FAIL) 1719 { 1720 EMSG(_("cannot save undo information")); 1721 return; 1722 } 1723 luaV_setrange(L, eap->line1, eap->line2); 1724 luaL_buffinit(L, &b); 1725 luaL_addlstring(&b, "return function(line, linenr) ", 30); /* header */ 1726 luaL_addlstring(&b, s, strlen(s)); 1727 luaL_addlstring(&b, " end", 4); /* footer */ 1728 luaL_pushresult(&b); 1729 s = lua_tolstring(L, -1, &len); 1730 if (luaL_loadbuffer(L, s, len, LUAVIM_CHUNKNAME)) 1731 { 1732 luaV_emsg(L); 1733 lua_pop(L, 1); /* function body */ 1734 return; 1735 } 1736 lua_call(L, 0, 1); 1737 lua_replace(L, -2); /* function -> body */ 1738 for (l = eap->line1; l <= eap->line2; l++) 1739 { 1740 /* Check the line number, the command my have deleted lines. */ 1741 if (l > curbuf->b_ml.ml_line_count) 1742 break; 1743 1744 lua_pushvalue(L, -1); /* function */ 1745 luaV_pushline(L, curbuf, l); /* current line as arg */ 1746 lua_pushinteger(L, l); /* current line number as arg */ 1747 if (lua_pcall(L, 2, 1, 0)) 1748 { 1749 luaV_emsg(L); 1750 break; 1751 } 1752 /* Catch the command switching to another buffer. */ 1753 if (curbuf != was_curbuf) 1754 break; 1755 if (lua_isstring(L, -1)) /* update line? */ 1756 { 1757 #ifdef HAVE_SANDBOX 1758 luaV_checksandbox(L); 1759 #endif 1760 ml_replace(l, luaV_toline(L, -1), TRUE); 1761 changed_bytes(l, 0); 1762 lua_pop(L, 1); /* result from luaV_toline */ 1763 } 1764 lua_pop(L, 1); /* line */ 1765 } 1766 lua_pop(L, 1); /* function */ 1767 check_cursor(); 1768 update_screen(NOT_VALID); 1769 } 1770 1771 void 1772 ex_luafile(exarg_T *eap) 1773 { 1774 if (lua_init() == FAIL) 1775 return; 1776 if (!eap->skip) 1777 { 1778 luaV_setrange(L, eap->line1, eap->line2); 1779 if (luaL_loadfile(L, (char *) eap->arg) || lua_pcall(L, 0, 0, 0)) 1780 luaV_emsg(L); 1781 } 1782 } 1783 1784 #define luaV_freetype(typ,tname) \ 1785 void \ 1786 lua_##tname##_free(typ *o) \ 1787 { \ 1788 if (!lua_isopen()) return; \ 1789 luaV_getfield(L, LUAVIM_FREE); \ 1790 lua_pushlightuserdata(L, (void *) o); \ 1791 lua_call(L, 1, 0); \ 1792 } 1793 1794 luaV_freetype(buf_T, buffer) 1795 luaV_freetype(win_T, window) 1796 1797 void 1798 do_luaeval (char_u *str, typval_T *arg, typval_T *rettv) 1799 { 1800 lua_init(); 1801 luaV_getfield(L, LUAVIM_LUAEVAL); 1802 lua_pushstring(L, (char *) str); 1803 lua_pushlightuserdata(L, (void *) arg); 1804 lua_pushlightuserdata(L, (void *) rettv); 1805 lua_call(L, 3, 0); 1806 } 1807 1808 int 1809 set_ref_in_lua (int copyID) 1810 { 1811 int aborted = 0; 1812 1813 if (lua_isopen()) 1814 { 1815 luaV_getfield(L, LUAVIM_SETREF); 1816 /* call the function with 1 arg, getting 1 result back */ 1817 lua_pushinteger(L, copyID); 1818 lua_call(L, 1, 1); 1819 /* get the result */ 1820 aborted = lua_tointeger(L, -1); 1821 /* pop result off the stack */ 1822 lua_pop(L, 1); 1823 } 1824 return aborted; 1825 } 1826 1827 #endif 1828