diff --git a/7.3.490 b/7.3.490 new file mode 100644 index 0000000..6c49a48 --- /dev/null +++ b/7.3.490 @@ -0,0 +1,2517 @@ +To: vim_dev@googlegroups.com +Subject: Patch 7.3.490 +Fcc: outbox +From: Bram Moolenaar +Mime-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +------------ + +Patch 7.3.490 +Problem: Member confusion in Lua interface. +Solution: Fix it. Add luaeval(). (Taro Muraoka, Luis Carvalho) +Files: runtime/doc/if_lua.txt, src/eval.c, src/if_lua.c, + src/proto/if_lua.pro + + +*** ../vim-7.3.489/runtime/doc/if_lua.txt 2010-08-15 21:57:14.000000000 +0200 +--- runtime/doc/if_lua.txt 2012-04-05 16:41:35.000000000 +0200 +*************** +*** 1,4 **** +! *if_lua.txt* For Vim version 7.3. Last change: 2010 Jul 22 + + + VIM REFERENCE MANUAL by Luis Carvalho +--- 1,4 ---- +! *if_lua.txt* For Vim version 7.3. Last change: 2012 Jan 16 + + + VIM REFERENCE MANUAL by Luis Carvalho +*************** +*** 8,15 **** + + 1. Commands |lua-commands| + 2. The vim module |lua-vim| +! 3. Buffer userdata |lua-buffer| +! 4. Window userdata |lua-window| + + {Vi does not have any of these commands} + +--- 8,18 ---- + + 1. Commands |lua-commands| + 2. The vim module |lua-vim| +! 3. List userdata |lua-list| +! 4. Dict userdata |lua-dict| +! 5. Buffer userdata |lua-buffer| +! 6. Window userdata |lua-window| +! 7. The luaeval function |lua-luaeval| + + {Vi does not have any of these commands} + +*************** +*** 88,98 **** + All these commands execute a Lua chunk from either the command line (:lua and + :luado) or a file (:luafile) with the given line [range]. Similarly to the Lua + interpreter, each chunk has its own scope and so only global variables are +! shared between command calls. Lua default libraries "table", "string", "math", +! and "package" are available, "io" and "debug" are not, and "os" is restricted +! to functions "date", "clock", "time", "difftime", and "getenv". In addition, +! Lua "print" function has its output redirected to the Vim message area, with +! arguments separated by a white space instead of a tab. + + Lua uses the "vim" module (see |lua-vim|) to issue commands to Vim + and manage buffers (|lua-buffer|) and windows (|lua-window|). However, +--- 91,99 ---- + All these commands execute a Lua chunk from either the command line (:lua and + :luado) or a file (:luafile) with the given line [range]. Similarly to the Lua + interpreter, each chunk has its own scope and so only global variables are +! shared between command calls. All Lua default libraries are available. In +! addition, Lua "print" function has its output redirected to the Vim message +! area, with arguments separated by a white space instead of a tab. + + Lua uses the "vim" module (see |lua-vim|) to issue commands to Vim + and manage buffers (|lua-buffer|) and windows (|lua-window|). However, +*************** +*** 108,116 **** + module also includes routines for buffer, window, and current line queries, + Vim evaluation and command execution, and others. + +! vim.isbuffer(value) Returns 'true' (boolean, not string) if +! "value" is a buffer userdata and 'false' +! otherwise (see |lua-buffer|). + + vim.buffer([arg]) If "arg" is a number, returns buffer with + number "arg" in the buffer list or, if "arg" +--- 109,117 ---- + module also includes routines for buffer, window, and current line queries, + Vim evaluation and command execution, and others. + +! vim.list() Returns an empty list (see |List|). +! +! vim.dict() Returns an empty dictionary (see |Dictionary|). + + vim.buffer([arg]) If "arg" is a number, returns buffer with + number "arg" in the buffer list or, if "arg" +*************** +*** 121,136 **** + 'true' returns the first buffer in the buffer + list or else the current buffer. + +- vim.iswindow(value) Returns 'true' (boolean, not string) if +- "value" is a window userdata and +- 'false' otherwise (see |lua-window|). +- + vim.window([arg]) If "arg" is a number, returns window with + number "arg" or 'nil' (nil value, not string) + if not found. Otherwise, if "toboolean(arg)" + is 'true' returns the first window or else the + current window. + + vim.command({cmd}) Executes the vim (ex-mode) command {cmd}. + Examples: > + :lua vim.command"set tw=60" +--- 122,142 ---- + 'true' returns the first buffer in the buffer + list or else the current buffer. + + vim.window([arg]) If "arg" is a number, returns window with + number "arg" or 'nil' (nil value, not string) + if not found. Otherwise, if "toboolean(arg)" + is 'true' returns the first window or else the + current window. + ++ vim.type({arg}) Returns the type of {arg}. It is equivalent to ++ Lua's "type" function, but returns "list", ++ "dict", "buffer", or "window" if {arg} is a ++ list, dictionary, buffer, or window, ++ respectively. Examples: > ++ :lua l = vim.list() ++ :lua print(type(l), vim.type(l)) ++ :" userdata list ++ < + vim.command({cmd}) Executes the vim (ex-mode) command {cmd}. + Examples: > + :lua vim.command"set tw=60" +*************** +*** 141,147 **** + Vim strings and numbers are directly converted + to Lua strings and numbers respectively. Vim + lists and dictionaries are converted to Lua +! tables (lists become integer-keyed tables). + Examples: > + :lua tw = vim.eval"&tw" + :lua print(vim.eval"{'a': 'one'}".a) +--- 147,153 ---- + Vim strings and numbers are directly converted + to Lua strings and numbers respectively. Vim + lists and dictionaries are converted to Lua +! userdata (see |lua-list| and |lua-dict|). + Examples: > + :lua tw = vim.eval"&tw" + :lua print(vim.eval"{'a': 'one'}".a) +*************** +*** 157,163 **** + + + ============================================================================== +! 3. Buffer userdata *lua-buffer* + + Buffer userdata represent vim buffers. A buffer userdata "b" has the following + properties and methods: +--- 163,234 ---- + + + ============================================================================== +! 3. List userdata *lua-list* +! +! List userdata represent vim lists, and the interface tries to follow closely +! Vim's syntax for lists. Since lists are objects, changes in list references in +! Lua are reflected in Vim and vice-versa. A list "l" has the following +! properties and methods: +! +! Properties +! ---------- +! o "#l" is the number of items in list "l", equivalent to "len(l)" +! in Vim. +! o "l[k]" returns the k-th item in "l"; "l" is zero-indexed, as in Vim. +! To modify the k-th item, simply do "l[k] = newitem"; in +! particular, "l[k] = nil" removes the k-th item from "l". +! o "l()" returns an iterator for "l". +! +! Methods +! ------- +! o "l:add(item)" appends "item" to the end of "l". +! o "l:insert(item[, pos])" inserts "item" at (optional) +! position "pos" in the list. The default value for "pos" is 0. +! +! Examples: +! > +! :let l = [1, 'item'] +! :lua l = vim.eval('l') -- same 'l' +! :lua l:add(vim.list()) +! :lua l[0] = math.pi +! :echo l[0] " 3.141593 +! :lua l[0] = nil -- remove first item +! :lua l:insert(true, 1) +! :lua print(l, #l, l[0], l[1], l[-1]) +! :lua for item in l() do print(item) end +! < +! +! ============================================================================== +! 4. Dict userdata *lua-dict* +! +! Similarly to list userdata, dict userdata represent vim dictionaries; since +! dictionaries are also objects, references are kept between Lua and Vim. A dict +! "d" has the following properties: +! +! Properties +! ---------- +! o "#d" is the number of items in dict "d", equivalent to "len(d)" +! in Vim. +! o "d.key" or "d['key']" returns the value at entry "key" in "d". +! To modify the entry at this key, simply do "d.key = newvalue"; in +! particular, "d.key = nil" removes the entry from "d". +! o "d()" returns an iterator for "d" and is equivalent to "items(d)" in +! Vim. +! +! Examples: +! > +! :let d = {'n':10} +! :lua d = vim.eval('d') -- same 'd' +! :lua print(d, d.n, #d) +! :let d.self = d +! :lua for k, v in d() do print(d, k, v) end +! :lua d.x = math.pi +! :lua d.self = nil -- remove entry +! :echo d +! < +! +! ============================================================================== +! 5. Buffer userdata *lua-buffer* + + Buffer userdata represent vim buffers. A buffer userdata "b" has the following + properties and methods: +*************** +*** 209,215 **** + < + + ============================================================================== +! 4. Window userdata *lua-window* + + Window objects represent vim windows. A window userdata "w" has the following + properties and methods: +--- 280,286 ---- + < + + ============================================================================== +! 6. Window userdata *lua-window* + + Window objects represent vim windows. A window userdata "w" has the following + properties and methods: +*************** +*** 241,244 **** + < + + ============================================================================== +! vim:tw=78:ts=8:ft=help:norl: +--- 312,340 ---- + < + + ============================================================================== +! 7. The luaeval function *lua-luaeval* +! +! The (dual) equivalent of "vim.eval" for passing Lua values to Vim is +! "luaeval". "luaeval" takes an expression string and an optional argument and +! returns the result of the expression. It is semantically equivalent in Lua to: +! > +! local chunkheader = "local _A = select(1, ...) return " +! function luaeval (expstr, arg) +! local chunk = assert(loadstring(chunkheader .. expstr, "luaeval")) +! return chunk(arg) -- return typval +! end +! < +! Note that "_A" receives the argument to "luaeval". Examples: > +! +! :echo luaeval('math.pi') +! :lua a = vim.list():add('newlist') +! :let a = luaeval('a') +! :echo a[0] " 'newlist' +! :function Rand(x,y) " random uniform between x and y +! : return luaeval('(_A.y-_A.x)*math.random()+_A.x', {'x':a:x,'y':a:y}) +! : endfunction +! :echo Rand(1,10) +! +! +! ============================================================================== +! vim:tw=78:ts=8:noet:ft=help:norl: +*** ../vim-7.3.489/src/eval.c 2012-03-28 16:49:25.000000000 +0200 +--- src/eval.c 2012-04-05 16:41:35.000000000 +0200 +*************** +*** 622,627 **** +--- 622,630 ---- + static void f_log __ARGS((typval_T *argvars, typval_T *rettv)); + static void f_log10 __ARGS((typval_T *argvars, typval_T *rettv)); + #endif ++ #ifdef FEAT_LUA ++ static void f_luaeval __ARGS((typval_T *argvars, typval_T *rettv)); ++ #endif + static void f_map __ARGS((typval_T *argvars, typval_T *rettv)); + static void f_maparg __ARGS((typval_T *argvars, typval_T *rettv)); + static void f_mapcheck __ARGS((typval_T *argvars, typval_T *rettv)); +*************** +*** 6777,6782 **** +--- 6780,6789 ---- + /* v: vars */ + set_ref_in_ht(&vimvarht, copyID); + ++ #ifdef FEAT_LUA ++ set_ref_in_lua(copyID); ++ #endif ++ + /* + * 2. Free lists and dictionaries that are not referenced. + */ +*************** +*** 7946,7951 **** +--- 7953,7961 ---- + {"log", 1, 1, f_log}, + {"log10", 1, 1, f_log10}, + #endif ++ #ifdef FEAT_LUA ++ {"luaeval", 1, 2, f_luaeval}, ++ #endif + {"map", 2, 2, f_map}, + {"maparg", 1, 4, f_maparg}, + {"mapcheck", 1, 3, f_mapcheck}, +*************** +*** 13626,13631 **** +--- 13636,13658 ---- + } + #endif + ++ #ifdef FEAT_LUA ++ /* ++ * "luaeval()" function ++ */ ++ static void ++ f_luaeval(argvars, rettv) ++ typval_T *argvars; ++ typval_T *rettv; ++ { ++ char_u *str; ++ char_u buf[NUMBUFLEN]; ++ ++ str = get_tv_string_buf(&argvars[0], buf); ++ do_luaeval(str, argvars + 1, rettv); ++ } ++ #endif ++ + /* + * "map()" function + */ +*** ../vim-7.3.489/src/if_lua.c 2011-12-08 16:00:12.000000000 +0100 +--- src/if_lua.c 2012-04-05 16:41:35.000000000 +0200 +*************** +*** 1,4 **** +! /* vi:set ts=8 sts=4 sw=4: + * + * VIM - Vi IMproved by Bram Moolenaar + * +--- 1,4 ---- +! /* vi:set ts=8 sts=4 sw=4 noet: + * + * VIM - Vi IMproved by Bram Moolenaar + * +*************** +*** 21,35 **** +--- 21,53 ---- + + #define LUAVIM_CHUNKNAME "vim chunk" + #define LUAVIM_NAME "vim" ++ #define LUAVIM_EVALNAME "luaeval" ++ #define LUAVIM_EVALHEADER "local _A=select(1,...) return " + + typedef buf_T *luaV_Buffer; + typedef win_T *luaV_Window; ++ typedef dict_T *luaV_Dict; ++ typedef list_T *luaV_List; + typedef void (*msgfunc_T)(char_u *); + ++ static const char LUAVIM_DICT[] = "dict"; ++ static const char LUAVIM_LIST[] = "list"; + static const char LUAVIM_BUFFER[] = "buffer"; + static const char LUAVIM_WINDOW[] = "window"; + static const char LUAVIM_FREE[] = "luaV_free"; ++ static const char LUAVIM_LUAEVAL[] = "luaV_luaeval"; ++ static const char LUAVIM_SETREF[] = "luaV_setref"; + ++ /* most functions are closures with a cache table as first upvalue; ++ * get/setudata manage references to vim userdata in cache table through ++ * object pointers (light userdata) */ ++ #define luaV_getudata(L, v) \ ++ lua_pushlightuserdata((L), (void *) (v)); \ ++ lua_rawget((L), lua_upvalueindex(1)) ++ #define luaV_setudata(L, v) \ ++ lua_pushlightuserdata((L), (void *) (v)); \ ++ lua_pushvalue((L), -2); \ ++ lua_rawset((L), lua_upvalueindex(1)) + #define luaV_getfield(L, s) \ + lua_pushlightuserdata((L), (void *)(s)); \ + lua_rawget((L), LUA_REGISTRYINDEX) +*************** +*** 38,43 **** +--- 56,70 ---- + #define luaV_msg(L) luaV_msgfunc((L), (msgfunc_T) msg) + #define luaV_emsg(L) luaV_msgfunc((L), (msgfunc_T) emsg) + ++ static luaV_List *luaV_pushlist (lua_State *L, list_T *lis); ++ static luaV_Dict *luaV_pushdict (lua_State *L, dict_T *dic); ++ ++ #if LUA_VERSION_NUM <= 501 ++ #define luaV_openlib(L, l, n) luaL_openlib(L, NULL, l, n) ++ #define luaL_typeerror luaL_typerror ++ #else ++ #define luaV_openlib luaL_setfuncs ++ #endif + + #ifdef DYNAMIC_LUA + +*************** +*** 54,85 **** + #endif + + /* lauxlib */ + #define luaL_register dll_luaL_register + #define luaL_typerror dll_luaL_typerror + #define luaL_checklstring dll_luaL_checklstring + #define luaL_checkinteger dll_luaL_checkinteger + #define luaL_optinteger dll_luaL_optinteger + #define luaL_checktype dll_luaL_checktype + #define luaL_error dll_luaL_error +- #define luaL_loadfile dll_luaL_loadfile +- #define luaL_loadbuffer dll_luaL_loadbuffer + #define luaL_newstate dll_luaL_newstate + #define luaL_buffinit dll_luaL_buffinit +- #define luaL_prepbuffer dll_luaL_prepbuffer + #define luaL_addlstring dll_luaL_addlstring + #define luaL_pushresult dll_luaL_pushresult + /* lua */ + #define lua_close dll_lua_close + #define lua_gettop dll_lua_gettop + #define lua_settop dll_lua_settop + #define lua_pushvalue dll_lua_pushvalue + #define lua_replace dll_lua_replace + #define lua_isnumber dll_lua_isnumber + #define lua_isstring dll_lua_isstring + #define lua_type dll_lua_type + #define lua_rawequal dll_lua_rawequal +- #define lua_tonumber dll_lua_tonumber +- #define lua_tointeger dll_lua_tointeger + #define lua_toboolean dll_lua_toboolean + #define lua_tolstring dll_lua_tolstring + #define lua_touserdata dll_lua_touserdata +--- 81,134 ---- + #endif + + /* lauxlib */ ++ #if LUA_VERSION_NUM <= 501 + #define luaL_register dll_luaL_register ++ #define luaL_prepbuffer dll_luaL_prepbuffer ++ #define luaL_openlib dll_luaL_openlib + #define luaL_typerror dll_luaL_typerror ++ #define luaL_loadfile dll_luaL_loadfile ++ #define luaL_loadbuffer dll_luaL_loadbuffer ++ #else ++ #define luaL_prepbuffsize dll_luaL_prepbuffsize ++ #define luaL_setfuncs dll_luaL_setfuncs ++ #define luaL_loadfilex dll_luaL_loadfilex ++ #define luaL_loadbufferx dll_luaL_loadbufferx ++ #define luaL_argerror dll_luaL_argerror ++ #endif + #define luaL_checklstring dll_luaL_checklstring + #define luaL_checkinteger dll_luaL_checkinteger + #define luaL_optinteger dll_luaL_optinteger + #define luaL_checktype dll_luaL_checktype + #define luaL_error dll_luaL_error + #define luaL_newstate dll_luaL_newstate + #define luaL_buffinit dll_luaL_buffinit + #define luaL_addlstring dll_luaL_addlstring + #define luaL_pushresult dll_luaL_pushresult + /* lua */ ++ #if LUA_VERSION_NUM <= 501 ++ #define lua_tonumber dll_lua_tonumber ++ #define lua_tointeger dll_lua_tointeger ++ #define lua_call dll_lua_call ++ #define lua_pcall dll_lua_pcall ++ #else ++ #define lua_tonumberx dll_lua_tonumberx ++ #define lua_tointegerx dll_lua_tointegerx ++ #define lua_callk dll_lua_callk ++ #define lua_pcallk dll_lua_pcallk ++ #define lua_getglobal dll_lua_getglobal ++ #define lua_setglobal dll_lua_setglobal ++ #define lua_typename dll_lua_typename ++ #endif + #define lua_close dll_lua_close + #define lua_gettop dll_lua_gettop + #define lua_settop dll_lua_settop + #define lua_pushvalue dll_lua_pushvalue + #define lua_replace dll_lua_replace ++ #define lua_remove dll_lua_remove + #define lua_isnumber dll_lua_isnumber + #define lua_isstring dll_lua_isstring + #define lua_type dll_lua_type + #define lua_rawequal dll_lua_rawequal + #define lua_toboolean dll_lua_toboolean + #define lua_tolstring dll_lua_tolstring + #define lua_touserdata dll_lua_touserdata +*************** +*** 94,109 **** + #define lua_pushlightuserdata dll_lua_pushlightuserdata + #define lua_getfield dll_lua_getfield + #define lua_rawget dll_lua_rawget + #define lua_createtable dll_lua_createtable + #define lua_newuserdata dll_lua_newuserdata + #define lua_getmetatable dll_lua_getmetatable + #define lua_setfield dll_lua_setfield + #define lua_rawset dll_lua_rawset + #define lua_rawseti dll_lua_rawseti +- #define lua_remove dll_lua_remove + #define lua_setmetatable dll_lua_setmetatable +- #define lua_call dll_lua_call +- #define lua_pcall dll_lua_pcall + /* libs */ + #define luaopen_base dll_luaopen_base + #define luaopen_table dll_luaopen_table +--- 143,156 ---- + #define lua_pushlightuserdata dll_lua_pushlightuserdata + #define lua_getfield dll_lua_getfield + #define lua_rawget dll_lua_rawget ++ #define lua_rawgeti dll_lua_rawgeti + #define lua_createtable dll_lua_createtable + #define lua_newuserdata dll_lua_newuserdata + #define lua_getmetatable dll_lua_getmetatable + #define lua_setfield dll_lua_setfield + #define lua_rawset dll_lua_rawset + #define lua_rawseti dll_lua_rawseti + #define lua_setmetatable dll_lua_setmetatable + /* libs */ + #define luaopen_base dll_luaopen_base + #define luaopen_table dll_luaopen_table +*************** +*** 116,147 **** + #define luaL_openlibs dll_luaL_openlibs + + /* lauxlib */ + void (*dll_luaL_register) (lua_State *L, const char *libname, const luaL_Reg *l); + int (*dll_luaL_typerror) (lua_State *L, int narg, const char *tname); + const char *(*dll_luaL_checklstring) (lua_State *L, int numArg, size_t *l); + lua_Integer (*dll_luaL_checkinteger) (lua_State *L, int numArg); + lua_Integer (*dll_luaL_optinteger) (lua_State *L, int nArg, lua_Integer def); + void (*dll_luaL_checktype) (lua_State *L, int narg, int t); + int (*dll_luaL_error) (lua_State *L, const char *fmt, ...); +- int (*dll_luaL_loadfile) (lua_State *L, const char *filename); +- int (*dll_luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, const char *name); + lua_State *(*dll_luaL_newstate) (void); + void (*dll_luaL_buffinit) (lua_State *L, luaL_Buffer *B); +- char *(*dll_luaL_prepbuffer) (luaL_Buffer *B); + void (*dll_luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); + void (*dll_luaL_pushresult) (luaL_Buffer *B); + /* lua */ + void (*dll_lua_close) (lua_State *L); + int (*dll_lua_gettop) (lua_State *L); + void (*dll_lua_settop) (lua_State *L, int idx); + void (*dll_lua_pushvalue) (lua_State *L, int idx); + void (*dll_lua_replace) (lua_State *L, int idx); + int (*dll_lua_isnumber) (lua_State *L, int idx); + int (*dll_lua_isstring) (lua_State *L, int idx); + int (*dll_lua_type) (lua_State *L, int idx); + int (*dll_lua_rawequal) (lua_State *L, int idx1, int idx2); +- lua_Number (*dll_lua_tonumber) (lua_State *L, int idx); +- lua_Integer (*dll_lua_tointeger) (lua_State *L, int idx); + int (*dll_lua_toboolean) (lua_State *L, int idx); + const char *(*dll_lua_tolstring) (lua_State *L, int idx, size_t *len); + void *(*dll_lua_touserdata) (lua_State *L, int idx); +--- 163,218 ---- + #define luaL_openlibs dll_luaL_openlibs + + /* lauxlib */ ++ #if LUA_VERSION_NUM <= 501 + void (*dll_luaL_register) (lua_State *L, const char *libname, const luaL_Reg *l); ++ char *(*dll_luaL_prepbuffer) (luaL_Buffer *B); ++ void (*dll_luaL_openlib) (lua_State *L, const char *libname, const luaL_Reg *l, int nup); + int (*dll_luaL_typerror) (lua_State *L, int narg, const char *tname); ++ int (*dll_luaL_loadfile) (lua_State *L, const char *filename); ++ int (*dll_luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, const char *name); ++ #else ++ char *(*dll_luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); ++ void (*dll_luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); ++ int (*dll_luaL_loadfilex) (lua_State *L, const char *filename, const char *mode); ++ int (*dll_luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode); ++ int (*dll_luaL_argerror) (lua_State *L, int numarg, const char *extramsg); ++ #endif + const char *(*dll_luaL_checklstring) (lua_State *L, int numArg, size_t *l); + lua_Integer (*dll_luaL_checkinteger) (lua_State *L, int numArg); + lua_Integer (*dll_luaL_optinteger) (lua_State *L, int nArg, lua_Integer def); + void (*dll_luaL_checktype) (lua_State *L, int narg, int t); + int (*dll_luaL_error) (lua_State *L, const char *fmt, ...); + lua_State *(*dll_luaL_newstate) (void); + void (*dll_luaL_buffinit) (lua_State *L, luaL_Buffer *B); + void (*dll_luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); + void (*dll_luaL_pushresult) (luaL_Buffer *B); + /* lua */ ++ #if LUA_VERSION_NUM <= 501 ++ lua_Number (*dll_lua_tonumber) (lua_State *L, int idx); ++ lua_Integer (*dll_lua_tointeger) (lua_State *L, int idx); ++ void (*dll_lua_call) (lua_State *L, int nargs, int nresults); ++ int (*dll_lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); ++ #else ++ lua_Number (*dll_lua_tonumberx) (lua_State *L, int idx, int *isnum); ++ lua_Integer (*dll_lua_tointegerx) (lua_State *L, int idx, int *isnum); ++ void (*dll_lua_callk) (lua_State *L, int nargs, int nresults, int ctx, ++ lua_CFunction k); ++ int (*dll_lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, ++ int ctx, lua_CFunction k); ++ void (*dll_lua_getglobal) (lua_State *L, const char *var); ++ void (*dll_lua_setglobal) (lua_State *L, const char *var); ++ const char *(*dll_lua_typename) (lua_State *L, int tp); ++ #endif + void (*dll_lua_close) (lua_State *L); + int (*dll_lua_gettop) (lua_State *L); + void (*dll_lua_settop) (lua_State *L, int idx); + void (*dll_lua_pushvalue) (lua_State *L, int idx); + void (*dll_lua_replace) (lua_State *L, int idx); ++ void (*dll_lua_remove) (lua_State *L, int idx); + int (*dll_lua_isnumber) (lua_State *L, int idx); + int (*dll_lua_isstring) (lua_State *L, int idx); + int (*dll_lua_type) (lua_State *L, int idx); + int (*dll_lua_rawequal) (lua_State *L, int idx1, int idx2); + int (*dll_lua_toboolean) (lua_State *L, int idx); + const char *(*dll_lua_tolstring) (lua_State *L, int idx, size_t *len); + void *(*dll_lua_touserdata) (lua_State *L, int idx); +*************** +*** 156,171 **** + void (*dll_lua_pushlightuserdata) (lua_State *L, void *p); + void (*dll_lua_getfield) (lua_State *L, int idx, const char *k); + void (*dll_lua_rawget) (lua_State *L, int idx); + void (*dll_lua_createtable) (lua_State *L, int narr, int nrec); + void *(*dll_lua_newuserdata) (lua_State *L, size_t sz); + int (*dll_lua_getmetatable) (lua_State *L, int objindex); + void (*dll_lua_setfield) (lua_State *L, int idx, const char *k); + void (*dll_lua_rawset) (lua_State *L, int idx); + void (*dll_lua_rawseti) (lua_State *L, int idx, int n); +- void (*dll_lua_remove) (lua_State *L, int idx); + int (*dll_lua_setmetatable) (lua_State *L, int objindex); +- void (*dll_lua_call) (lua_State *L, int nargs, int nresults); +- int (*dll_lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); + /* libs */ + int (*dll_luaopen_base) (lua_State *L); + int (*dll_luaopen_table) (lua_State *L); +--- 227,240 ---- + void (*dll_lua_pushlightuserdata) (lua_State *L, void *p); + void (*dll_lua_getfield) (lua_State *L, int idx, const char *k); + void (*dll_lua_rawget) (lua_State *L, int idx); ++ void (*dll_lua_rawgeti) (lua_State *L, int idx, int n); + void (*dll_lua_createtable) (lua_State *L, int narr, int nrec); + void *(*dll_lua_newuserdata) (lua_State *L, size_t sz); + int (*dll_lua_getmetatable) (lua_State *L, int objindex); + void (*dll_lua_setfield) (lua_State *L, int idx, const char *k); + void (*dll_lua_rawset) (lua_State *L, int idx); + void (*dll_lua_rawseti) (lua_State *L, int idx, int n); + int (*dll_lua_setmetatable) (lua_State *L, int objindex); + /* libs */ + int (*dll_luaopen_base) (lua_State *L); + int (*dll_luaopen_table) (lua_State *L); +*************** +*** 185,216 **** + + static const luaV_Reg luaV_dll[] = { + /* lauxlib */ + {"luaL_register", (luaV_function) &dll_luaL_register}, + {"luaL_typerror", (luaV_function) &dll_luaL_typerror}, + {"luaL_checklstring", (luaV_function) &dll_luaL_checklstring}, + {"luaL_checkinteger", (luaV_function) &dll_luaL_checkinteger}, + {"luaL_optinteger", (luaV_function) &dll_luaL_optinteger}, + {"luaL_checktype", (luaV_function) &dll_luaL_checktype}, + {"luaL_error", (luaV_function) &dll_luaL_error}, +- {"luaL_loadfile", (luaV_function) &dll_luaL_loadfile}, +- {"luaL_loadbuffer", (luaV_function) &dll_luaL_loadbuffer}, + {"luaL_newstate", (luaV_function) &dll_luaL_newstate}, + {"luaL_buffinit", (luaV_function) &dll_luaL_buffinit}, +- {"luaL_prepbuffer", (luaV_function) &dll_luaL_prepbuffer}, + {"luaL_addlstring", (luaV_function) &dll_luaL_addlstring}, + {"luaL_pushresult", (luaV_function) &dll_luaL_pushresult}, + /* lua */ + {"lua_close", (luaV_function) &dll_lua_close}, + {"lua_gettop", (luaV_function) &dll_lua_gettop}, + {"lua_settop", (luaV_function) &dll_lua_settop}, + {"lua_pushvalue", (luaV_function) &dll_lua_pushvalue}, + {"lua_replace", (luaV_function) &dll_lua_replace}, + {"lua_isnumber", (luaV_function) &dll_lua_isnumber}, + {"lua_isstring", (luaV_function) &dll_lua_isstring}, + {"lua_type", (luaV_function) &dll_lua_type}, + {"lua_rawequal", (luaV_function) &dll_lua_rawequal}, +- {"lua_tonumber", (luaV_function) &dll_lua_tonumber}, +- {"lua_tointeger", (luaV_function) &dll_lua_tointeger}, + {"lua_toboolean", (luaV_function) &dll_lua_toboolean}, + {"lua_tolstring", (luaV_function) &dll_lua_tolstring}, + {"lua_touserdata", (luaV_function) &dll_lua_touserdata}, +--- 254,307 ---- + + static const luaV_Reg luaV_dll[] = { + /* lauxlib */ ++ #if LUA_VERSION_NUM <= 501 + {"luaL_register", (luaV_function) &dll_luaL_register}, ++ {"luaL_prepbuffer", (luaV_function) &dll_luaL_prepbuffer}, ++ {"luaL_openlib", (luaV_function) &dll_luaL_openlib}, + {"luaL_typerror", (luaV_function) &dll_luaL_typerror}, ++ {"luaL_loadfile", (luaV_function) &dll_luaL_loadfile}, ++ {"luaL_loadbuffer", (luaV_function) &dll_luaL_loadbuffer}, ++ #else ++ {"luaL_prepbuffsize", (luaV_function) &dll_luaL_prepbuffsize}, ++ {"luaL_setfuncs", (luaV_function) &dll_luaL_setfuncs}, ++ {"luaL_loadfilex", (luaV_function) &dll_luaL_loadfilex}, ++ {"luaL_loadbufferx", (luaV_function) &dll_luaL_loadbufferx}, ++ {"luaL_argerror", (luaV_function) &dll_luaL_argerror}, ++ #endif + {"luaL_checklstring", (luaV_function) &dll_luaL_checklstring}, + {"luaL_checkinteger", (luaV_function) &dll_luaL_checkinteger}, + {"luaL_optinteger", (luaV_function) &dll_luaL_optinteger}, + {"luaL_checktype", (luaV_function) &dll_luaL_checktype}, + {"luaL_error", (luaV_function) &dll_luaL_error}, + {"luaL_newstate", (luaV_function) &dll_luaL_newstate}, + {"luaL_buffinit", (luaV_function) &dll_luaL_buffinit}, + {"luaL_addlstring", (luaV_function) &dll_luaL_addlstring}, + {"luaL_pushresult", (luaV_function) &dll_luaL_pushresult}, + /* lua */ ++ #if LUA_VERSION_NUM <= 501 ++ {"lua_tonumber", (luaV_function) &dll_lua_tonumber}, ++ {"lua_tointeger", (luaV_function) &dll_lua_tointeger}, ++ {"lua_call", (luaV_function) &dll_lua_call}, ++ {"lua_pcall", (luaV_function) &dll_lua_pcall}, ++ #else ++ {"lua_tonumberx", (luaV_function) &dll_lua_tonumberx}, ++ {"lua_tointegerx", (luaV_function) &dll_lua_tointegerx}, ++ {"lua_callk", (luaV_function) &dll_lua_callk}, ++ {"lua_pcallk", (luaV_function) &dll_lua_pcallk}, ++ {"lua_getglobal", (luaV_function) &dll_lua_getglobal}, ++ {"lua_setglobal", (luaV_function) &dll_lua_setglobal}, ++ {"lua_typename", (luaV_function) &dll_lua_typename}, ++ #endif + {"lua_close", (luaV_function) &dll_lua_close}, + {"lua_gettop", (luaV_function) &dll_lua_gettop}, + {"lua_settop", (luaV_function) &dll_lua_settop}, + {"lua_pushvalue", (luaV_function) &dll_lua_pushvalue}, + {"lua_replace", (luaV_function) &dll_lua_replace}, ++ {"lua_remove", (luaV_function) &dll_lua_remove}, + {"lua_isnumber", (luaV_function) &dll_lua_isnumber}, + {"lua_isstring", (luaV_function) &dll_lua_isstring}, + {"lua_type", (luaV_function) &dll_lua_type}, + {"lua_rawequal", (luaV_function) &dll_lua_rawequal}, + {"lua_toboolean", (luaV_function) &dll_lua_toboolean}, + {"lua_tolstring", (luaV_function) &dll_lua_tolstring}, + {"lua_touserdata", (luaV_function) &dll_lua_touserdata}, +*************** +*** 225,240 **** + {"lua_pushlightuserdata", (luaV_function) &dll_lua_pushlightuserdata}, + {"lua_getfield", (luaV_function) &dll_lua_getfield}, + {"lua_rawget", (luaV_function) &dll_lua_rawget}, + {"lua_createtable", (luaV_function) &dll_lua_createtable}, + {"lua_newuserdata", (luaV_function) &dll_lua_newuserdata}, + {"lua_getmetatable", (luaV_function) &dll_lua_getmetatable}, + {"lua_setfield", (luaV_function) &dll_lua_setfield}, + {"lua_rawset", (luaV_function) &dll_lua_rawset}, + {"lua_rawseti", (luaV_function) &dll_lua_rawseti}, +- {"lua_remove", (luaV_function) &dll_lua_remove}, + {"lua_setmetatable", (luaV_function) &dll_lua_setmetatable}, +- {"lua_call", (luaV_function) &dll_lua_call}, +- {"lua_pcall", (luaV_function) &dll_lua_pcall}, + /* libs */ + {"luaopen_base", (luaV_function) &dll_luaopen_base}, + {"luaopen_table", (luaV_function) &dll_luaopen_table}, +--- 316,329 ---- + {"lua_pushlightuserdata", (luaV_function) &dll_lua_pushlightuserdata}, + {"lua_getfield", (luaV_function) &dll_lua_getfield}, + {"lua_rawget", (luaV_function) &dll_lua_rawget}, ++ {"lua_rawgeti", (luaV_function) &dll_lua_rawgeti}, + {"lua_createtable", (luaV_function) &dll_lua_createtable}, + {"lua_newuserdata", (luaV_function) &dll_lua_newuserdata}, + {"lua_getmetatable", (luaV_function) &dll_lua_getmetatable}, + {"lua_setfield", (luaV_function) &dll_lua_setfield}, + {"lua_rawset", (luaV_function) &dll_lua_rawset}, + {"lua_rawseti", (luaV_function) &dll_lua_rawseti}, + {"lua_setmetatable", (luaV_function) &dll_lua_setmetatable}, + /* libs */ + {"luaopen_base", (luaV_function) &dll_luaopen_base}, + {"luaopen_table", (luaV_function) &dll_luaopen_table}, +*************** +*** 294,299 **** +--- 383,398 ---- + + #endif /* DYNAMIC_LUA */ + ++ #if LUA_VERSION_NUM > 501 ++ static int ++ luaL_typeerror (lua_State *L, int narg, const char *tname) ++ { ++ const char *msg = lua_pushfstring(L, "%s expected, got %s", ++ tname, luaL_typename(L, narg)); ++ return luaL_argerror(L, narg, msg); ++ } ++ #endif ++ + + /* ======= Internal ======= */ + +*************** +*** 327,343 **** + } + + static void * + luaV_checkudata(lua_State *L, int ud, const char *tname) + { + void *p = luaV_toudata(L, ud, tname); +! if (p == NULL) luaL_typerror(L, ud, tname); + return p; + } + + static void + luaV_pushtypval(lua_State *L, typval_T *tv) + { +! if (tv == NULL) luaL_error(L, "null type"); + switch (tv->v_type) + { + case VAR_STRING: +--- 426,460 ---- + } + + static void * ++ luaV_checkcache(lua_State *L, void *p) ++ { ++ luaV_getudata(L, p); ++ if (lua_isnil(L, -1)) luaL_error(L, "invalid object"); ++ lua_pop(L, 1); ++ return p; ++ } ++ ++ #define luaV_unbox(L,luatyp,ud) (*((luatyp *) lua_touserdata((L),(ud)))) ++ ++ #define luaV_checkvalid(L,luatyp,ud) \ ++ luaV_checkcache((L), (void *) luaV_unbox((L),luatyp,(ud))) ++ ++ static void * + luaV_checkudata(lua_State *L, int ud, const char *tname) + { + void *p = luaV_toudata(L, ud, tname); +! if (p == NULL) luaL_typeerror(L, ud, tname); + return p; + } + + static void + luaV_pushtypval(lua_State *L, typval_T *tv) + { +! if (tv == NULL) +! { +! lua_pushnil(L); +! return; +! } + switch (tv->v_type) + { + case VAR_STRING: +*************** +*** 351,418 **** + lua_pushnumber(L, (lua_Number) tv->vval.v_float); + break; + #endif +! case VAR_LIST: { +! list_T *l = tv->vval.v_list; + +! if (l != NULL) + { +! /* check cache */ +! lua_pushlightuserdata(L, (void *) l); +! lua_rawget(L, LUA_ENVIRONINDEX); +! if (lua_isnil(L, -1)) /* not interned? */ + { +! listitem_T *li; +! int n = 0; +! lua_pop(L, 1); /* nil */ +! lua_newtable(L); +! lua_pushlightuserdata(L, (void *) l); +! lua_pushvalue(L, -2); +! lua_rawset(L, LUA_ENVIRONINDEX); +! for (li = l->lv_first; li != NULL; li = li->li_next) +! { +! luaV_pushtypval(L, &li->li_tv); +! lua_rawseti(L, -2, ++n); +! } + } +! } +! else lua_pushnil(L); +! break; +! } +! case VAR_DICT: { +! dict_T *d = tv->vval.v_dict; +! +! if (d != NULL) +! { +! /* check cache */ +! lua_pushlightuserdata(L, (void *) d); +! lua_rawget(L, LUA_ENVIRONINDEX); +! if (lua_isnil(L, -1)) /* not interned? */ + { +! hashtab_T *ht = &d->dv_hashtab; +! hashitem_T *hi; +! int n = ht->ht_used; /* remaining items */ +! lua_pop(L, 1); /* nil */ +! lua_newtable(L); +! lua_pushlightuserdata(L, (void *) d); +! lua_pushvalue(L, -2); +! lua_rawset(L, LUA_ENVIRONINDEX); +! for (hi = ht->ht_array; n > 0; hi++) +! { +! if (!HASHITEM_EMPTY(hi)) +! { +! dictitem_T *di = dict_lookup(hi); +! luaV_pushtypval(L, &di->di_tv); +! lua_setfield(L, -2, (char *) hi->hi_key); +! n--; +! } +! } + } + } +- else lua_pushnil(L); + break; + } + default: +! luaL_error(L, "invalid type"); + } + } + +--- 468,537 ---- + lua_pushnumber(L, (lua_Number) tv->vval.v_float); + break; + #endif +! case VAR_LIST: +! luaV_pushlist(L, tv->vval.v_list); +! break; +! case VAR_DICT: +! luaV_pushdict(L, tv->vval.v_dict); +! break; +! default: +! lua_pushnil(L); +! } +! } + +! /* converts lua value at 'pos' to typval 'tv' */ +! static void +! luaV_totypval (lua_State *L, int pos, typval_T *tv) +! { +! switch(lua_type(L, pos)) { +! case LUA_TBOOLEAN: +! tv->v_type = VAR_NUMBER; +! tv->vval.v_number = (varnumber_T) lua_toboolean(L, pos); +! break; +! case LUA_TSTRING: +! tv->v_type = VAR_STRING; +! tv->vval.v_string = vim_strsave((char_u *) lua_tostring(L, pos)); +! break; +! case LUA_TNUMBER: +! #ifdef FEAT_FLOAT +! tv->v_type = VAR_FLOAT; +! tv->vval.v_float = (float_T) lua_tonumber(L, pos); +! #else +! tv->v_type = VAR_NUMBER; +! tv->vval.v_number = (varnumber_T) lua_tointeger(L, pos); +! #endif +! break; +! case LUA_TUSERDATA: { +! void *p = lua_touserdata(L, pos); +! if (lua_getmetatable(L, pos)) /* has metatable? */ + { +! /* check list */ +! luaV_getfield(L, LUAVIM_LIST); +! if (lua_rawequal(L, -1, -2)) + { +! tv->v_type = VAR_LIST; +! tv->vval.v_list = *((luaV_List *) p); +! ++tv->vval.v_list->lv_refcount; +! lua_pop(L, 2); /* MTs */ +! return; + } +! /* check dict */ +! luaV_getfield(L, LUAVIM_DICT); +! if (lua_rawequal(L, -1, -3)) + { +! tv->v_type = VAR_DICT; +! tv->vval.v_dict = *((luaV_Dict *) p); +! ++tv->vval.v_dict->dv_refcount; +! lua_pop(L, 3); /* MTs */ +! return; + } ++ lua_pop(L, 3); /* MTs */ + } + break; + } + default: +! tv->v_type = VAR_NUMBER; +! tv->vval.v_number = 0; + } + } + +*************** +*** 481,569 **** + lua_pop(L, 2); /* original and modified strings */ + } + + +! /* ======= Buffer type ======= */ + +! static luaV_Buffer * +! luaV_newbuffer(lua_State *L, buf_T *buf) + { +! luaV_Buffer *b = (luaV_Buffer *) lua_newuserdata(L, sizeof(luaV_Buffer)); +! *b = buf; +! lua_pushlightuserdata(L, (void *) buf); +! lua_pushvalue(L, -2); +! lua_rawset(L, LUA_ENVIRONINDEX); /* env[buf] = udata */ +! /* to avoid GC, store as key in env */ +! lua_pushvalue(L, -1); +! lua_pushboolean(L, 1); +! lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = true */ +! /* set metatable */ +! luaV_getfield(L, LUAVIM_BUFFER); + lua_setmetatable(L, -2); +! return b; + } + +! static luaV_Buffer * +! luaV_pushbuffer (lua_State *L, buf_T *buf) + { +! luaV_Buffer *b = NULL; +! if (buf == NULL) +! lua_pushnil(L); +! else { +! lua_pushlightuserdata(L, (void *) buf); +! lua_rawget(L, LUA_ENVIRONINDEX); +! if (lua_isnil(L, -1)) /* not interned? */ + { +! lua_pop(L, 1); +! b = luaV_newbuffer(L, buf); + } + else +! b = (luaV_Buffer *) lua_touserdata(L, -1); + } +! return b; + } + +! /* Buffer metamethods */ + + static int +! luaV_buffer_tostring(lua_State *L) + { +! lua_pushfstring(L, "%s: %p", LUAVIM_BUFFER, lua_touserdata(L, 1)); + return 1; + } + + static int + luaV_buffer_len(lua_State *L) + { +! luaV_Buffer *b = lua_touserdata(L, 1); +! lua_pushinteger(L, (*b)->b_ml.ml_line_count); + return 1; + } + + static int + luaV_buffer_call(lua_State *L) + { +! luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1); + lua_settop(L, 1); +! set_curbuf(*b, DOBUF_SPLIT); + return 1; + } + + static int + luaV_buffer_index(lua_State *L) + { +! luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1); + linenr_T n = (linenr_T) lua_tointeger(L, 2); +! if (n > 0 && n <= (*b)->b_ml.ml_line_count) +! luaV_pushline(L, *b, n); + else if (lua_isstring(L, 2)) + { + const char *s = lua_tostring(L, 2); + if (strncmp(s, "name", 4) == 0) +! lua_pushstring(L, (char *) (*b)->b_sfname); + else if (strncmp(s, "fname", 5) == 0) +! lua_pushstring(L, (char *) (*b)->b_ffname); + else if (strncmp(s, "number", 6) == 0) +! lua_pushinteger(L, (*b)->b_fnum); + /* methods */ + else if (strncmp(s, "insert", 6) == 0 + || strncmp(s, "next", 4) == 0 +--- 600,1107 ---- + lua_pop(L, 2); /* original and modified strings */ + } + ++ #define luaV_newtype(typ,tname,luatyp,luatname) \ ++ static luatyp * \ ++ luaV_new##tname (lua_State *L, typ *obj) \ ++ { \ ++ luatyp *o = (luatyp *) lua_newuserdata(L, sizeof(luatyp)); \ ++ *o = obj; \ ++ luaV_setudata(L, obj); /* cache[obj] = udata */ \ ++ luaV_getfield(L, luatname); \ ++ lua_setmetatable(L, -2); \ ++ return o; \ ++ } ++ ++ #define luaV_pushtype(typ,tname,luatyp) \ ++ static luatyp * \ ++ luaV_push##tname (lua_State *L, typ *obj) \ ++ { \ ++ luatyp *o = NULL; \ ++ if (obj == NULL) \ ++ lua_pushnil(L); \ ++ else { \ ++ luaV_getudata(L, obj); \ ++ if (lua_isnil(L, -1)) /* not interned? */ \ ++ { \ ++ lua_pop(L, 1); \ ++ o = luaV_new##tname(L, obj); \ ++ } \ ++ else \ ++ o = (luatyp *) lua_touserdata(L, -1); \ ++ } \ ++ return o; \ ++ } ++ ++ #define luaV_type_tostring(tname,luatname) \ ++ static int \ ++ luaV_##tname##_tostring (lua_State *L) \ ++ { \ ++ lua_pushfstring(L, "%s: %p", luatname, lua_touserdata(L, 1)); \ ++ return 1; \ ++ } ++ + +! /* adapted from eval.c */ +! +! #define listitem_alloc() (listitem_T *)alloc(sizeof(listitem_T)) +! +! static listitem_T * +! list_find (list_T *l, long n) +! { +! listitem_T *li; +! if (l == NULL || n < -l->lv_len || n >= l->lv_len) +! return NULL; +! if (n < 0) /* search backward? */ +! for (li = l->lv_last; n < -1; li = li->li_prev) +! n++; +! else /* search forward */ +! for (li = l->lv_first; n > 0; li = li->li_next) +! n--; +! return li; +! } + +! static void +! list_remove (list_T *l, listitem_T *li) + { +! listwatch_T *lw; +! --l->lv_len; +! /* fix watchers */ +! for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next) +! if (lw->lw_item == li) +! lw->lw_item = li->li_next; +! /* fix list pointers */ +! if (li->li_next == NULL) /* last? */ +! l->lv_last = li->li_prev; +! else +! li->li_next->li_prev = li->li_prev; +! if (li->li_prev == NULL) /* first? */ +! l->lv_first = li->li_next; +! else +! li->li_prev->li_next = li->li_next; +! l->lv_idx_item = NULL; +! } +! +! static void +! list_append(list_T *l, listitem_T *item) +! { +! if (l->lv_last == NULL) /* empty list? */ +! l->lv_first = item; +! else +! l->lv_last->li_next = item; +! item->li_prev = l->lv_last; +! item->li_next = NULL; +! l->lv_last = item; +! ++l->lv_len; +! } +! +! static int +! list_insert_tv(list_T *l, typval_T *tv, listitem_T *item) +! { +! listitem_T *ni = listitem_alloc(); +! +! if (ni == NULL) +! return FAIL; +! copy_tv(tv, &ni->li_tv); +! if (item == NULL) +! list_append(l, ni); +! else +! { +! ni->li_prev = item->li_prev; +! ni->li_next = item; +! if (item->li_prev == NULL) +! { +! l->lv_first = ni; +! ++l->lv_idx; +! } +! else +! { +! item->li_prev->li_next = ni; +! l->lv_idx_item = NULL; +! } +! item->li_prev = ni; +! ++l->lv_len; +! } +! return OK; +! } +! +! /* set references */ +! +! static void set_ref_in_tv (typval_T *tv, int copyID); +! +! static void +! set_ref_in_dict(dict_T *d, int copyID) +! { +! hashtab_T *ht = &d->dv_hashtab; +! int n = ht->ht_used; +! hashitem_T *hi; +! for (hi = ht->ht_array; n > 0; ++hi) +! if (!HASHITEM_EMPTY(hi)) +! { +! dictitem_T *di = dict_lookup(hi); +! set_ref_in_tv(&di->di_tv, copyID); +! --n; +! } +! } +! +! static void +! set_ref_in_list(list_T *l, int copyID) +! { +! listitem_T *li; +! for (li = l->lv_first; li != NULL; li = li->li_next) +! set_ref_in_tv(&li->li_tv, copyID); +! } +! +! static void +! set_ref_in_tv(typval_T *tv, int copyID) +! { +! if (tv->v_type == VAR_LIST) +! { +! list_T *l = tv->vval.v_list; +! if (l != NULL && l->lv_copyID != copyID) +! { +! l->lv_copyID = copyID; +! set_ref_in_list(l, copyID); +! } +! } +! else if (tv->v_type == VAR_DICT) +! { +! dict_T *d = tv->vval.v_dict; +! if (d != NULL && d->dv_copyID != copyID) +! { +! d->dv_copyID = copyID; +! set_ref_in_dict(d, copyID); +! } +! } +! } +! +! +! /* ======= List type ======= */ +! +! static luaV_List * +! luaV_newlist (lua_State *L, list_T *lis) +! { +! luaV_List *l = (luaV_List *) lua_newuserdata(L, sizeof(luaV_List)); +! *l = lis; +! lis->lv_refcount++; /* reference in Lua */ +! luaV_setudata(L, lis); /* cache[lis] = udata */ +! luaV_getfield(L, LUAVIM_LIST); + lua_setmetatable(L, -2); +! return l; + } + +! luaV_pushtype(list_T, list, luaV_List) +! luaV_type_tostring(list, LUAVIM_LIST) +! +! static int +! luaV_list_gc (lua_State *L) + { +! list_unref(luaV_unbox(L, luaV_List, 1)); +! return 0; +! } +! +! static int +! luaV_list_len (lua_State *L) +! { +! list_T *l = luaV_unbox(L, luaV_List, 1); +! lua_pushinteger(L, (l == NULL) ? 0 : (int) l->lv_len); +! return 1; +! } +! +! static int +! luaV_list_iter (lua_State *L) +! { +! listitem_T *li = (listitem_T *) lua_touserdata(L, lua_upvalueindex(2)); +! if (li == NULL) return 0; +! luaV_pushtypval(L, &li->li_tv); +! lua_pushlightuserdata(L, (void *) li->li_next); +! lua_replace(L, lua_upvalueindex(2)); +! return 1; +! } +! +! static int +! luaV_list_call (lua_State *L) +! { +! list_T *l = luaV_unbox(L, luaV_List, 1); +! lua_pushvalue(L, lua_upvalueindex(1)); /* pass cache table along */ +! lua_pushlightuserdata(L, (void *) l->lv_first); +! lua_pushcclosure(L, luaV_list_iter, 2); +! return 1; +! } +! +! static int +! luaV_list_index (lua_State *L) +! { +! list_T *l = luaV_unbox(L, luaV_List, 1); +! if (lua_isnumber(L, 2)) /* list item? */ +! { +! listitem_T *li = list_find(l, (long) luaL_checkinteger(L, 2)); +! if (li == NULL) +! lua_pushnil(L); +! else +! luaV_pushtypval(L, &li->li_tv); +! } +! else if (lua_isstring(L, 2)) /* method? */ +! { +! const char *s = lua_tostring(L, 2); +! if (strncmp(s, "add", 3) == 0 +! || strncmp(s, "insert", 6) == 0 +! || strncmp(s, "extend", 6) == 0) + { +! lua_getmetatable(L, 1); +! lua_getfield(L, -1, s); + } + else +! lua_pushnil(L); + } +! else +! lua_pushnil(L); +! return 1; + } + +! static int +! luaV_list_newindex (lua_State *L) +! { +! list_T *l = luaV_unbox(L, luaV_List, 1); +! long n = (long) luaL_checkinteger(L, 2); +! listitem_T *li; +! if (l->lv_lock) +! luaL_error(L, "list is locked"); +! li = list_find(l, n); +! if (li == NULL) return 0; +! if (lua_isnil(L, 3)) /* remove? */ +! { +! list_remove(l, li); +! clear_tv(&li->li_tv); +! vim_free(li); +! } +! else +! { +! typval_T v; +! luaV_totypval(L, 3, &v); +! clear_tv(&li->li_tv); +! copy_tv(&v, &li->li_tv); +! } +! return 0; +! } + + static int +! luaV_list_add (lua_State *L) + { +! luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST); +! list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis); +! listitem_T *li; +! if (l->lv_lock) +! luaL_error(L, "list is locked"); +! li = listitem_alloc(); +! if (li != NULL) +! { +! typval_T v; +! lua_settop(L, 2); +! luaV_totypval(L, 2, &v); +! copy_tv(&v, &li->li_tv); +! list_append(l, li); +! } +! lua_settop(L, 1); + return 1; + } + + static int ++ luaV_list_insert (lua_State *L) ++ { ++ luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST); ++ list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis); ++ long pos = luaL_optlong(L, 3, 0); ++ listitem_T *li = NULL; ++ typval_T v; ++ if (l->lv_lock) ++ luaL_error(L, "list is locked"); ++ if (pos < l->lv_len) ++ { ++ li = list_find(l, pos); ++ if (li == NULL) ++ luaL_error(L, "invalid position"); ++ } ++ lua_settop(L, 2); ++ luaV_totypval(L, 2, &v); ++ list_insert_tv(l, &v, li); ++ lua_settop(L, 1); ++ return 1; ++ } ++ ++ static const luaL_Reg luaV_List_mt[] = { ++ {"__tostring", luaV_list_tostring}, ++ {"__gc", luaV_list_gc}, ++ {"__len", luaV_list_len}, ++ {"__call", luaV_list_call}, ++ {"__index", luaV_list_index}, ++ {"__newindex", luaV_list_newindex}, ++ {"add", luaV_list_add}, ++ {"insert", luaV_list_insert}, ++ {NULL, NULL} ++ }; ++ ++ ++ /* ======= Dict type ======= */ ++ ++ static luaV_Dict * ++ luaV_newdict (lua_State *L, dict_T *dic) ++ { ++ luaV_Dict *d = (luaV_Dict *) lua_newuserdata(L, sizeof(luaV_Dict)); ++ *d = dic; ++ dic->dv_refcount++; /* reference in Lua */ ++ luaV_setudata(L, dic); /* cache[dic] = udata */ ++ luaV_getfield(L, LUAVIM_DICT); ++ lua_setmetatable(L, -2); ++ return d; ++ } ++ ++ luaV_pushtype(dict_T, dict, luaV_Dict) ++ luaV_type_tostring(dict, LUAVIM_DICT) ++ ++ static int ++ luaV_dict_gc (lua_State *L) ++ { ++ dict_unref(luaV_unbox(L, luaV_Dict, 1)); ++ return 0; ++ } ++ ++ static int ++ luaV_dict_len (lua_State *L) ++ { ++ dict_T *d = luaV_unbox(L, luaV_Dict, 1); ++ lua_pushinteger(L, (d == NULL) ? 0 : (int) d->dv_hashtab.ht_used); ++ return 1; ++ } ++ ++ static int ++ luaV_dict_iter (lua_State *L) ++ { ++ hashitem_T *hi = (hashitem_T *) lua_touserdata(L, lua_upvalueindex(2)); ++ int n = lua_tointeger(L, lua_upvalueindex(3)); ++ dictitem_T *di; ++ if (n <= 0) return 0; ++ while (HASHITEM_EMPTY(hi)) hi++; ++ di = dict_lookup(hi); ++ lua_pushstring(L, (char *) hi->hi_key); ++ luaV_pushtypval(L, &di->di_tv); ++ lua_pushlightuserdata(L, (void *) (hi + 1)); ++ lua_replace(L, lua_upvalueindex(2)); ++ lua_pushinteger(L, n - 1); ++ lua_replace(L, lua_upvalueindex(3)); ++ return 2; ++ } ++ ++ static int ++ luaV_dict_call (lua_State *L) ++ { ++ dict_T *d = luaV_unbox(L, luaV_Dict, 1); ++ hashtab_T *ht = &d->dv_hashtab; ++ lua_pushvalue(L, lua_upvalueindex(1)); /* pass cache table along */ ++ lua_pushlightuserdata(L, (void *) ht->ht_array); ++ lua_pushinteger(L, ht->ht_used); /* # remaining items */ ++ lua_pushcclosure(L, luaV_dict_iter, 3); ++ return 1; ++ } ++ ++ static int ++ luaV_dict_index (lua_State *L) ++ { ++ dict_T *d = luaV_unbox(L, luaV_Dict, 1); ++ char_u *key = (char_u *) luaL_checkstring(L, 2); ++ dictitem_T *di = dict_find(d, key, -1); ++ if (di == NULL) ++ lua_pushnil(L); ++ else ++ luaV_pushtypval(L, &di->di_tv); ++ return 1; ++ } ++ ++ static int ++ luaV_dict_newindex (lua_State *L) ++ { ++ dict_T *d = luaV_unbox(L, luaV_Dict, 1); ++ char_u *key = (char_u *) luaL_checkstring(L, 2); ++ dictitem_T *di; ++ if (d->dv_lock) ++ luaL_error(L, "dict is locked"); ++ di = dict_find(d, key, -1); ++ if (di == NULL) /* non-existing key? */ ++ { ++ if (lua_isnil(L, 3)) return 0; ++ di = dictitem_alloc(key); ++ if (di == NULL) return 0; ++ if (dict_add(d, di) == FAIL) ++ { ++ vim_free(di); ++ return 0; ++ } ++ } ++ else ++ clear_tv(&di->di_tv); ++ if (lua_isnil(L, 3)) /* remove? */ ++ { ++ hashitem_T *hi = hash_find(&d->dv_hashtab, di->di_key); ++ hash_remove(&d->dv_hashtab, hi); ++ dictitem_free(di); ++ } ++ else { ++ typval_T v; ++ luaV_totypval(L, 3, &v); ++ copy_tv(&v, &di->di_tv); ++ } ++ return 0; ++ } ++ ++ static const luaL_Reg luaV_Dict_mt[] = { ++ {"__tostring", luaV_dict_tostring}, ++ {"__gc", luaV_dict_gc}, ++ {"__len", luaV_dict_len}, ++ {"__call", luaV_dict_call}, ++ {"__index", luaV_dict_index}, ++ {"__newindex", luaV_dict_newindex}, ++ {NULL, NULL} ++ }; ++ ++ ++ /* ======= Buffer type ======= */ ++ ++ luaV_newtype(buf_T, buffer, luaV_Buffer, LUAVIM_BUFFER) ++ luaV_pushtype(buf_T, buffer, luaV_Buffer) ++ luaV_type_tostring(buffer, LUAVIM_BUFFER) ++ ++ static int + luaV_buffer_len(lua_State *L) + { +! buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1); +! lua_pushinteger(L, b->b_ml.ml_line_count); + return 1; + } + + static int + luaV_buffer_call(lua_State *L) + { +! buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1); + lua_settop(L, 1); +! set_curbuf(b, DOBUF_SPLIT); + return 1; + } + + static int + luaV_buffer_index(lua_State *L) + { +! buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1); + linenr_T n = (linenr_T) lua_tointeger(L, 2); +! if (n > 0 && n <= b->b_ml.ml_line_count) +! luaV_pushline(L, b, n); + else if (lua_isstring(L, 2)) + { + const char *s = lua_tostring(L, 2); + if (strncmp(s, "name", 4) == 0) +! lua_pushstring(L, (char *) b->b_sfname); + else if (strncmp(s, "fname", 5) == 0) +! lua_pushstring(L, (char *) b->b_ffname); + else if (strncmp(s, "number", 6) == 0) +! lua_pushinteger(L, b->b_fnum); + /* methods */ + else if (strncmp(s, "insert", 6) == 0 + || strncmp(s, "next", 4) == 0 +*************** +*** 584,600 **** + static int + luaV_buffer_newindex(lua_State *L) + { +! luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1); + linenr_T n = (linenr_T) luaL_checkinteger(L, 2); + #ifdef HAVE_SANDBOX + luaV_checksandbox(L); + #endif +! if (n < 1 || n > (*b)->b_ml.ml_line_count) + luaL_error(L, "invalid line number"); + if (lua_isnil(L, 3)) /* delete line */ + { + buf_T *buf = curbuf; +! curbuf = *b; + if (u_savedel(n, 1L) == FAIL) + { + curbuf = buf; +--- 1122,1138 ---- + static int + luaV_buffer_newindex(lua_State *L) + { +! buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1); + linenr_T n = (linenr_T) luaL_checkinteger(L, 2); + #ifdef HAVE_SANDBOX + luaV_checksandbox(L); + #endif +! if (n < 1 || n > b->b_ml.ml_line_count) + luaL_error(L, "invalid line number"); + if (lua_isnil(L, 3)) /* delete line */ + { + buf_T *buf = curbuf; +! curbuf = b; + if (u_savedel(n, 1L) == FAIL) + { + curbuf = buf; +*************** +*** 607,613 **** + } + else { + deleted_lines_mark(n, 1L); +! if (*b == curwin->w_buffer) /* fix cursor in current window? */ + { + if (curwin->w_cursor.lnum >= n) + { +--- 1145,1151 ---- + } + else { + deleted_lines_mark(n, 1L); +! if (b == curwin->w_buffer) /* fix cursor in current window? */ + { + if (curwin->w_cursor.lnum >= n) + { +*************** +*** 627,633 **** + else if (lua_isstring(L, 3)) /* update line */ + { + buf_T *buf = curbuf; +! curbuf = *b; + if (u_savesub(n) == FAIL) + { + curbuf = buf; +--- 1165,1171 ---- + else if (lua_isstring(L, 3)) /* update line */ + { + buf_T *buf = curbuf; +! curbuf = b; + if (u_savesub(n) == FAIL) + { + curbuf = buf; +*************** +*** 640,646 **** + } + else changed_bytes(n, 0); + curbuf = buf; +! if (*b == curwin->w_buffer) + check_cursor_col(); + } + else +--- 1178,1184 ---- + } + else changed_bytes(n, 0); + curbuf = buf; +! if (b == curwin->w_buffer) + check_cursor_col(); + } + else +*************** +*** 651,658 **** + static int + luaV_buffer_insert(lua_State *L) + { +! luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); +! linenr_T last = (*b)->b_ml.ml_line_count; + linenr_T n = (linenr_T) luaL_optinteger(L, 3, last); + buf_T *buf; + luaL_checktype(L, 2, LUA_TSTRING); +--- 1189,1197 ---- + static int + luaV_buffer_insert(lua_State *L) + { +! luaV_Buffer *lb = luaV_checkudata(L, 1, LUAVIM_BUFFER); +! buf_T *b = (buf_T *) luaV_checkcache(L, (void *) *lb); +! linenr_T last = b->b_ml.ml_line_count; + linenr_T n = (linenr_T) luaL_optinteger(L, 3, last); + buf_T *buf; + luaL_checktype(L, 2, LUA_TSTRING); +*************** +*** 664,670 **** + if (n > last) n = last; + /* insert */ + buf = curbuf; +! curbuf = *b; + if (u_save(n, n + 1) == FAIL) + { + curbuf = buf; +--- 1203,1209 ---- + if (n > last) n = last; + /* insert */ + buf = curbuf; +! curbuf = b; + if (u_save(n, n + 1) == FAIL) + { + curbuf = buf; +*************** +*** 686,692 **** + luaV_buffer_next(lua_State *L) + { + luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); +! luaV_pushbuffer(L, (*b)->b_next); + return 1; + } + +--- 1225,1232 ---- + luaV_buffer_next(lua_State *L) + { + luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); +! buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b); +! luaV_pushbuffer(L, buf->b_next); + return 1; + } + +*************** +*** 694,700 **** + luaV_buffer_previous(lua_State *L) + { + luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); +! luaV_pushbuffer(L, (*b)->b_prev); + return 1; + } + +--- 1234,1241 ---- + luaV_buffer_previous(lua_State *L) + { + luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); +! buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b); +! luaV_pushbuffer(L, buf->b_prev); + return 1; + } + +*************** +*** 702,709 **** + luaV_buffer_isvalid(lua_State *L) + { + luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); +! lua_pushlightuserdata(L, (void *) (*b)); +! lua_rawget(L, LUA_ENVIRONINDEX); + lua_pushboolean(L, !lua_isnil(L, -1)); + return 1; + } +--- 1243,1249 ---- + luaV_buffer_isvalid(lua_State *L) + { + luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); +! luaV_getudata(L, *b); + lua_pushboolean(L, !lua_isnil(L, -1)); + return 1; + } +*************** +*** 724,801 **** + + /* ======= Window type ======= */ + +! static luaV_Window * +! luaV_newwindow(lua_State *L, win_T *win) +! { +! luaV_Window *w = (luaV_Window *) lua_newuserdata(L, sizeof(luaV_Window)); +! *w = win; +! lua_pushlightuserdata(L, (void *) win); +! lua_pushvalue(L, -2); +! lua_rawset(L, LUA_ENVIRONINDEX); /* env[win] = udata */ +! /* to avoid GC, store as key in env */ +! lua_pushvalue(L, -1); +! lua_pushboolean(L, 1); +! lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = true */ +! /* set metatable */ +! luaV_getfield(L, LUAVIM_WINDOW); +! lua_setmetatable(L, -2); +! return w; +! } +! +! static luaV_Window * +! luaV_pushwindow(lua_State *L, win_T *win) +! { +! luaV_Window *w = NULL; +! if (win == NULL) +! lua_pushnil(L); +! else { +! lua_pushlightuserdata(L, (void *) win); +! lua_rawget(L, LUA_ENVIRONINDEX); +! if (lua_isnil(L, -1)) /* not interned? */ +! { +! lua_pop(L, 1); +! w = luaV_newwindow(L, win); +! } +! else w = (luaV_Window *) lua_touserdata(L, -1); +! } +! return w; +! } +! +! /* Window metamethods */ +! +! static int +! luaV_window_tostring(lua_State *L) +! { +! lua_pushfstring(L, "%s: %p", LUAVIM_WINDOW, lua_touserdata(L, 1)); +! return 1; +! } + + static int + luaV_window_call(lua_State *L) + { +! luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1); + lua_settop(L, 1); +! win_goto(*w); + return 1; + } + + static int + luaV_window_index(lua_State *L) + { +! luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1); + const char *s = luaL_checkstring(L, 2); + if (strncmp(s, "buffer", 6) == 0) +! luaV_pushbuffer(L, (*w)->w_buffer); + else if (strncmp(s, "line", 4) == 0) +! lua_pushinteger(L, (*w)->w_cursor.lnum); + else if (strncmp(s, "col", 3) == 0) +! lua_pushinteger(L, (*w)->w_cursor.col + 1); + #ifdef FEAT_VERTSPLIT + else if (strncmp(s, "width", 5) == 0) +! lua_pushinteger(L, W_WIDTH((*w))); + #endif + else if (strncmp(s, "height", 6) == 0) +! lua_pushinteger(L, (*w)->w_height); + /* methods */ + else if (strncmp(s, "next", 4) == 0 + || strncmp(s, "previous", 8) == 0 +--- 1264,1299 ---- + + /* ======= Window type ======= */ + +! luaV_newtype(win_T, window, luaV_Window, LUAVIM_WINDOW) +! luaV_pushtype(win_T, window, luaV_Window) +! luaV_type_tostring(window, LUAVIM_WINDOW) + + static int + luaV_window_call(lua_State *L) + { +! win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1); + lua_settop(L, 1); +! win_goto(w); + return 1; + } + + static int + luaV_window_index(lua_State *L) + { +! win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1); + const char *s = luaL_checkstring(L, 2); + if (strncmp(s, "buffer", 6) == 0) +! luaV_pushbuffer(L, w->w_buffer); + else if (strncmp(s, "line", 4) == 0) +! lua_pushinteger(L, w->w_cursor.lnum); + else if (strncmp(s, "col", 3) == 0) +! lua_pushinteger(L, w->w_cursor.col + 1); + #ifdef FEAT_VERTSPLIT + else if (strncmp(s, "width", 5) == 0) +! lua_pushinteger(L, W_WIDTH(w)); + #endif + else if (strncmp(s, "height", 6) == 0) +! lua_pushinteger(L, w->w_height); + /* methods */ + else if (strncmp(s, "next", 4) == 0 + || strncmp(s, "previous", 8) == 0 +*************** +*** 812,818 **** + static int + luaV_window_newindex (lua_State *L) + { +! luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1); + const char *s = luaL_checkstring(L, 2); + int v = luaL_checkinteger(L, 3); + if (strncmp(s, "line", 4) == 0) +--- 1310,1316 ---- + static int + luaV_window_newindex (lua_State *L) + { +! win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1); + const char *s = luaL_checkstring(L, 2); + int v = luaL_checkinteger(L, 3); + if (strncmp(s, "line", 4) == 0) +*************** +*** 820,828 **** + #ifdef HAVE_SANDBOX + luaV_checksandbox(L); + #endif +! if (v < 1 || v > (*w)->w_buffer->b_ml.ml_line_count) + luaL_error(L, "line out of range"); +! (*w)->w_cursor.lnum = v; + update_screen(VALID); + } + else if (strncmp(s, "col", 3) == 0) +--- 1318,1326 ---- + #ifdef HAVE_SANDBOX + luaV_checksandbox(L); + #endif +! if (v < 1 || v > w->w_buffer->b_ml.ml_line_count) + luaL_error(L, "line out of range"); +! w->w_cursor.lnum = v; + update_screen(VALID); + } + else if (strncmp(s, "col", 3) == 0) +*************** +*** 830,836 **** + #ifdef HAVE_SANDBOX + luaV_checksandbox(L); + #endif +! (*w)->w_cursor.col = v - 1; + update_screen(VALID); + } + #ifdef FEAT_VERTSPLIT +--- 1328,1334 ---- + #ifdef HAVE_SANDBOX + luaV_checksandbox(L); + #endif +! w->w_cursor.col = v - 1; + update_screen(VALID); + } + #ifdef FEAT_VERTSPLIT +*************** +*** 840,846 **** + #ifdef FEAT_GUI + need_mouse_correct = TRUE; + #endif +! curwin = *w; + win_setwidth(v); + curwin = win; + } +--- 1338,1344 ---- + #ifdef FEAT_GUI + need_mouse_correct = TRUE; + #endif +! curwin = w; + win_setwidth(v); + curwin = win; + } +*************** +*** 851,857 **** + #ifdef FEAT_GUI + need_mouse_correct = TRUE; + #endif +! curwin = *w; + win_setheight(v); + curwin = win; + } +--- 1349,1355 ---- + #ifdef FEAT_GUI + need_mouse_correct = TRUE; + #endif +! curwin = w; + win_setheight(v); + curwin = win; + } +*************** +*** 864,870 **** + luaV_window_next(lua_State *L) + { + luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); +! luaV_pushwindow(L, (*w)->w_next); + return 1; + } + +--- 1362,1369 ---- + luaV_window_next(lua_State *L) + { + luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); +! win_T *win = (win_T *) luaV_checkcache(L, (void *) *w); +! luaV_pushwindow(L, win->w_next); + return 1; + } + +*************** +*** 872,878 **** + luaV_window_previous(lua_State *L) + { + luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); +! luaV_pushwindow(L, (*w)->w_prev); + return 1; + } + +--- 1371,1378 ---- + luaV_window_previous(lua_State *L) + { + luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); +! win_T *win = (win_T *) luaV_checkcache(L, (void *) *w); +! luaV_pushwindow(L, win->w_prev); + return 1; + } + +*************** +*** 880,887 **** + luaV_window_isvalid(lua_State *L) + { + luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); +! lua_pushlightuserdata(L, (void *) (*w)); +! lua_rawget(L, LUA_ENVIRONINDEX); + lua_pushboolean(L, !lua_isnil(L, -1)); + return 1; + } +--- 1380,1386 ---- + luaV_window_isvalid(lua_State *L) + { + luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); +! luaV_getudata(L, *w); + lua_pushboolean(L, !lua_isnil(L, -1)); + return 1; + } +*************** +*** 983,988 **** +--- 1482,1509 ---- + } + + static int ++ luaV_list(lua_State *L) ++ { ++ list_T *l = list_alloc(); ++ if (l == NULL) ++ lua_pushnil(L); ++ else ++ luaV_newlist(L, l); ++ return 1; ++ } ++ ++ static int ++ luaV_dict(lua_State *L) ++ { ++ dict_T *d = dict_alloc(); ++ if (d == NULL) ++ lua_pushnil(L); ++ else ++ luaV_newdict(L, d); ++ return 1; ++ } ++ ++ static int + luaV_buffer(lua_State *L) + { + buf_T *buf; +*************** +*** 1008,1022 **** + break; + } + } +- if (buf == NULL) /* not found? */ +- lua_pushnil(L); +- else +- luaV_pushbuffer(L, buf); + } +! else { + buf = (lua_toboolean(L, 1)) ? firstbuf : curbuf; /* first buffer? */ +! luaV_pushbuffer(L, buf); +! } + return 1; + } + +--- 1529,1538 ---- + break; + } + } + } +! else + buf = (lua_toboolean(L, 1)) ? firstbuf : curbuf; /* first buffer? */ +! luaV_pushbuffer(L, buf); + return 1; + } + +*************** +*** 1029,1043 **** + int n = lua_tointeger(L, 1); + for (win = firstwin; win != NULL; win = win->w_next, n--) + if (n == 1) break; +- if (win == NULL) /* not found? */ +- lua_pushnil(L); +- else +- luaV_pushwindow(L, win); + } +! else { + win = (lua_toboolean(L, 1)) ? firstwin : curwin; /* first window? */ +! luaV_pushwindow(L, win); +! } + return 1; + } + +--- 1545,1554 ---- + int n = lua_tointeger(L, 1); + for (win = firstwin; win != NULL; win = win->w_next, n--) + if (n == 1) break; + } +! else + win = (lua_toboolean(L, 1)) ? firstwin : curwin; /* first window? */ +! luaV_pushwindow(L, win); + return 1; + } + +*************** +*** 1054,1086 **** + } + + static int +! luaV_isbuffer(lua_State *L) +! { +! lua_pushboolean(L, luaV_toudata(L, 1, LUAVIM_BUFFER) != NULL); +! return 1; +! } +! +! static int +! luaV_iswindow(lua_State *L) + { +! lua_pushboolean(L, luaV_toudata(L, 1, LUAVIM_WINDOW) != NULL); +! return 1; +! } +! +! /* for freeing buffer and window objects; lightuserdata as arg */ +! static int +! luaV_free(lua_State *L) +! { +! lua_pushvalue(L, 1); /* lightudata */ +! lua_rawget(L, LUA_ENVIRONINDEX); +! if (!lua_isnil(L, -1)) + { +! lua_pushnil(L); +! lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = nil */ +! lua_pushnil(L); +! lua_rawset(L, LUA_ENVIRONINDEX); /* env[lightudata] = nil */ + } +! return 0; + } + + static const luaL_Reg luaV_module[] = { +--- 1565,1606 ---- + } + + static int +! luaV_type(lua_State *L) + { +! luaL_checkany(L, 1); +! if (lua_type(L, 1) == LUA_TUSERDATA) /* check vim udata? */ + { +! lua_settop(L, 1); +! if (lua_getmetatable(L, 1)) +! { +! luaV_getfield(L, LUAVIM_LIST); +! if (lua_rawequal(L, -1, 2)) +! { +! lua_pushstring(L, "list"); +! return 1; +! } +! luaV_getfield(L, LUAVIM_DICT); +! if (lua_rawequal(L, -1, 2)) +! { +! lua_pushstring(L, "dict"); +! return 1; +! } +! luaV_getfield(L, LUAVIM_BUFFER); +! if (lua_rawequal(L, -1, 2)) +! { +! lua_pushstring(L, "buffer"); +! return 1; +! } +! luaV_getfield(L, LUAVIM_WINDOW); +! if (lua_rawequal(L, -1, 2)) +! { +! lua_pushstring(L, "window"); +! return 1; +! } +! } + } +! lua_pushstring(L, luaL_typename(L, 1)); /* fallback */ +! return 1; + } + + static const luaL_Reg luaV_module[] = { +*************** +*** 1088,1111 **** + {"eval", luaV_eval}, + {"beep", luaV_beep}, + {"line", luaV_line}, + {"buffer", luaV_buffer}, + {"window", luaV_window}, + {"open", luaV_open}, +! {"isbuffer", luaV_isbuffer}, +! {"iswindow", luaV_iswindow}, + {NULL, NULL} + }; + + static int + luaopen_vim(lua_State *L) + { +! /* set environment */ + lua_newtable(L); + lua_newtable(L); +! lua_pushliteral(L, "v"); + lua_setfield(L, -2, "__mode"); +! lua_setmetatable(L, -2); +! lua_replace(L, LUA_ENVIRONINDEX); + /* print */ + lua_pushcfunction(L, luaV_print); + lua_setglobal(L, "print"); +--- 1608,1695 ---- + {"eval", luaV_eval}, + {"beep", luaV_beep}, + {"line", luaV_line}, ++ {"list", luaV_list}, ++ {"dict", luaV_dict}, + {"buffer", luaV_buffer}, + {"window", luaV_window}, + {"open", luaV_open}, +! {"type", luaV_type}, + {NULL, NULL} + }; + ++ /* for freeing list, dict, buffer and window objects; lightuserdata as arg */ ++ static int ++ luaV_free(lua_State *L) ++ { ++ lua_pushnil(L); ++ luaV_setudata(L, lua_touserdata(L, 1)); ++ return 0; ++ } ++ ++ static int ++ luaV_luaeval (lua_State *L) ++ { ++ luaL_Buffer b; ++ size_t l; ++ const char *str = lua_tolstring(L, 1, &l); ++ typval_T *arg = (typval_T *) lua_touserdata(L, 2); ++ typval_T *rettv = (typval_T *) lua_touserdata(L, 3); ++ luaL_buffinit(L, &b); ++ luaL_addlstring(&b, LUAVIM_EVALHEADER, sizeof(LUAVIM_EVALHEADER) - 1); ++ luaL_addlstring(&b, str, l); ++ luaL_pushresult(&b); ++ str = lua_tolstring(L, -1, &l); ++ if (luaL_loadbuffer(L, str, l, LUAVIM_EVALNAME)) /* compile error? */ ++ { ++ luaV_emsg(L); ++ return 0; ++ } ++ luaV_pushtypval(L, arg); ++ if (lua_pcall(L, 1, 1, 0)) /* running error? */ ++ { ++ luaV_emsg(L); ++ return 0; ++ } ++ luaV_totypval(L, -1, rettv); ++ return 0; ++ } ++ ++ static int ++ luaV_setref (lua_State *L) ++ { ++ int copyID = lua_tointeger(L, 1); ++ typval_T tv; ++ luaV_getfield(L, LUAVIM_LIST); ++ luaV_getfield(L, LUAVIM_DICT); ++ lua_pushnil(L); ++ while (lua_next(L, lua_upvalueindex(1)) != 0) /* traverse cache table */ ++ { ++ lua_getmetatable(L, -1); ++ if (lua_rawequal(L, -1, 2)) /* list? */ ++ { ++ tv.v_type = VAR_LIST; ++ tv.vval.v_list = (list_T *) lua_touserdata(L, 4); /* key */ ++ } ++ else if (lua_rawequal(L, -1, 3)) /* dict? */ ++ { ++ tv.v_type = VAR_DICT; ++ tv.vval.v_dict = (dict_T *) lua_touserdata(L, 4); /* key */ ++ } ++ lua_pop(L, 2); /* metatable and value */ ++ set_ref_in_tv(&tv, copyID); ++ } ++ return 0; ++ } ++ + static int + luaopen_vim(lua_State *L) + { +! /* set cache table */ + lua_newtable(L); + lua_newtable(L); +! lua_pushstring(L, "v"); + lua_setfield(L, -2, "__mode"); +! lua_setmetatable(L, -2); /* cache is weak-valued */ + /* print */ + lua_pushcfunction(L, luaV_print); + lua_setglobal(L, "print"); +*************** +*** 1116,1129 **** + lua_pop(L, 1); + /* free */ + lua_pushlightuserdata(L, (void *) LUAVIM_FREE); +! lua_pushcfunction(L, luaV_free); + lua_rawset(L, LUA_REGISTRYINDEX); + /* register */ + luaV_newmetatable(L, LUAVIM_BUFFER); +! luaL_register(L, NULL, luaV_Buffer_mt); + luaV_newmetatable(L, LUAVIM_WINDOW); +! luaL_register(L, NULL, luaV_Window_mt); +! luaL_register(L, LUAVIM_NAME, luaV_module); + return 0; + } + +--- 1700,1735 ---- + lua_pop(L, 1); + /* free */ + lua_pushlightuserdata(L, (void *) LUAVIM_FREE); +! lua_pushvalue(L, 1); /* cache table */ +! lua_pushcclosure(L, luaV_free, 1); +! lua_rawset(L, LUA_REGISTRYINDEX); +! /* luaeval */ +! lua_pushlightuserdata(L, (void *) LUAVIM_LUAEVAL); +! lua_pushvalue(L, 1); /* cache table */ +! lua_pushcclosure(L, luaV_luaeval, 1); +! lua_rawset(L, LUA_REGISTRYINDEX); +! /* setref */ +! lua_pushlightuserdata(L, (void *) LUAVIM_SETREF); +! lua_pushvalue(L, 1); /* cache table */ +! lua_pushcclosure(L, luaV_setref, 1); + lua_rawset(L, LUA_REGISTRYINDEX); + /* register */ ++ luaV_newmetatable(L, LUAVIM_LIST); ++ lua_pushvalue(L, 1); ++ luaV_openlib(L, luaV_List_mt, 1); ++ luaV_newmetatable(L, LUAVIM_DICT); ++ lua_pushvalue(L, 1); ++ luaV_openlib(L, luaV_Dict_mt, 1); + luaV_newmetatable(L, LUAVIM_BUFFER); +! lua_pushvalue(L, 1); /* cache table */ +! luaV_openlib(L, luaV_Buffer_mt, 1); + luaV_newmetatable(L, LUAVIM_WINDOW); +! lua_pushvalue(L, 1); /* cache table */ +! luaV_openlib(L, luaV_Window_mt, 1); +! lua_newtable(L); /* vim table */ +! lua_pushvalue(L, 1); /* cache table */ +! luaV_openlib(L, luaV_module, 1); +! lua_setglobal(L, LUAVIM_NAME); + return 0; + } + +*************** +*** 1154,1160 **** + static lua_State *L = NULL; + + static int +! lua_is_open(void) + { + return L != NULL; + } +--- 1760,1766 ---- + static lua_State *L = NULL; + + static int +! lua_isopen(void) + { + return L != NULL; + } +*************** +*** 1162,1168 **** + static int + lua_init(void) + { +! if (L == NULL) + { + #ifdef DYNAMIC_LUA + if (!lua_enabled(TRUE)) +--- 1768,1774 ---- + static int + lua_init(void) + { +! if (!lua_isopen()) + { + #ifdef DYNAMIC_LUA + if (!lua_enabled(TRUE)) +*************** +*** 1179,1185 **** + void + lua_end(void) + { +! if (L != NULL) + { + lua_close(L); + L = NULL; +--- 1785,1791 ---- + void + lua_end(void) + { +! if (lua_isopen()) + { + lua_close(L); + L = NULL; +*************** +*** 1273,1295 **** + } + } + +! /* buffer */ + void +! lua_buffer_free(buf_T *buf) + { +! if (!lua_is_open()) return; +! luaV_getfield(L, LUAVIM_FREE); +! lua_pushlightuserdata(L, (void *) buf); +! lua_call(L, 1, 0); + } + +- /* window */ + void +! lua_window_free(win_T *win) + { +! if (!lua_is_open()) return; +! luaV_getfield(L, LUAVIM_FREE); +! lua_pushlightuserdata(L, (void *) win); + lua_call(L, 1, 0); + } + +--- 1879,1914 ---- + } + } + +! #define luaV_freetype(typ,tname) \ +! void \ +! lua_##tname##_free(typ *o) \ +! { \ +! if (!lua_isopen()) return; \ +! luaV_getfield(L, LUAVIM_FREE); \ +! lua_pushlightuserdata(L, (void *) o); \ +! lua_call(L, 1, 0); \ +! } +! +! luaV_freetype(buf_T, buffer) +! luaV_freetype(win_T, window) +! + void +! do_luaeval (char_u *str, typval_T *arg, typval_T *rettv) + { +! lua_init(); +! luaV_getfield(L, LUAVIM_LUAEVAL); +! lua_pushstring(L, (char *) str); +! lua_pushlightuserdata(L, (void *) arg); +! lua_pushlightuserdata(L, (void *) rettv); +! lua_call(L, 3, 0); + } + + void +! set_ref_in_lua (int copyID) + { +! if (!lua_isopen()) return; +! luaV_getfield(L, LUAVIM_SETREF); +! lua_pushinteger(L, copyID); + lua_call(L, 1, 0); + } + +*** ../vim-7.3.489/src/proto/if_lua.pro 2010-08-15 21:57:28.000000000 +0200 +--- src/proto/if_lua.pro 2012-04-05 16:41:35.000000000 +0200 +*************** +*** 6,9 **** +--- 6,11 ---- + void ex_luafile __ARGS((exarg_T *eap)); + void lua_buffer_free __ARGS((buf_T *buf)); + void lua_window_free __ARGS((win_T *win)); ++ void do_luaeval __ARGS((char_u *str, typval_T *arg, typval_T *rettv)); ++ void set_ref_in_lua __ARGS((int copyID)); + /* vim: set ft=c : */ +*** ../vim-7.3.489/src/version.c 2012-04-05 16:07:01.000000000 +0200 +--- src/version.c 2012-04-05 16:52:08.000000000 +0200 +*************** +*** 716,717 **** +--- 716,719 ---- + { /* Add new patch number below this line */ ++ /**/ ++ 490, + /**/ + +-- +Even got a Datapoint 3600(?) with a DD50 connector instead of the +usual DB25... what a nightmare trying to figure out the pinout +for *that* with no spex... + + /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ +/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ +\\\ an exciting new programming language -- http://www.Zimbu.org /// + \\\ help me help AIDS victims -- http://ICCF-Holland.org ///