From: Sadrul Habib Chowdhury Date: Tue, 9 Jun 2009 21:22:19 +0000 (-0400) Subject: Allow using unnamed functions as handlers. X-Git-Url: https://repo.or.cz/w/screen-lua.git/commitdiff_plain/ac24b9b43c47468f9dc82b253c21763a3c2eb565 Allow using unnamed functions as handlers. Allow both named and unnamed functions for callbacks. This is pretty cool, and should allow for interesting scripts. [This breaks unregistering. Working on that shortly] --- diff --git a/src/lua.c b/src/lua.c index 0fa4c06..0cee0ee 100644 --- a/src/lua.c +++ b/src/lua.c @@ -79,6 +79,22 @@ static int LuaDispatch(void *handler, const char *params, va_list va); static int LuaRegEvent(lua_State *L); static int LuaUnRegEvent(lua_State *L); +enum +{ + LUA_HANDLER_TYPE_N = 1, + LUA_HANDLER_TYPE_F +}; + +struct lua_handler +{ + int type; + union + { + char *name; + int reference; + } u; +}; + /** Template {{{ */ #define CHECK_TYPE(name, type) \ @@ -813,10 +829,14 @@ int LuaCall(char *func, char **argv) static int LuaDispatch(void *handler, const char *params, va_list va) { - const char *func = handler; + struct lua_handler *lh = handler; int argc, retvalue; - lua_getfield(L, LUA_GLOBALSINDEX, func); + if (lh->type == LUA_HANDLER_TYPE_N) + lua_getfield(L, LUA_GLOBALSINDEX, lh->u.name); + else + lua_rawgeti(L, LUA_REGISTRYINDEX, lh->u.reference); + if (lua_isnil(L, -1)) return 0; argc = LuaPushParams(L, params, va); @@ -867,12 +887,13 @@ LuaRegEvent(lua_State *L) * returns: A ticket for later unregister. */ int idx = 1, argc = lua_gettop(L); int priv = 31; /* Default privilege */ + struct lua_handler lh; char *obj = NULL; const char *objname = "global"; static char evbuf[SEVNAME_MAX]; - const char *event, *handler; + const char *event; struct script_event *sev; @@ -892,7 +913,19 @@ LuaRegEvent(lua_State *L) event = luaL_checkstring(L, idx++); snprintf(evbuf, SEVNAME_MAX, "%s_%s", objname, event); - handler = luaL_checkstring(L, idx++); + + if (lua_isfunction(L, idx)) + { + lua_pushvalue(L, idx); + lh.u.reference = luaL_ref(L, LUA_REGISTRYINDEX); + lh.type = LUA_HANDLER_TYPE_F; + idx++; + } + else + { + lh.type = LUA_HANDLER_TYPE_N; + lh.u.name = luaL_checkstring(L, idx++); + } StackDump(L, "In RegEvent\n"); @@ -906,15 +939,20 @@ LuaRegEvent(lua_State *L) l = (struct listener *)malloc(sizeof(struct listener)); if (!l) return luaL_error(L, "Out of memory"); - l->handler = (void *)handler; + l->handler = &lh; l->priv = priv; l->dispatcher = LuaDispatch; if (register_listener(sev, l)) { free(l); - return luaL_error(L, "Handler %s has already been registered", handler); + if (lh.type == LUA_HANDLER_TYPE_N) + return luaL_error(L, "Handler %s has already been registered", lh.u.name); + else + return luaL_error(L, "Handler has already been registered"); } - /*Return the handler for un-register*/ + /* Return the handler for un-register */ + l->handler = malloc(sizeof(struct lua_handler)); + memcpy(l->handler, &lh, sizeof(struct lua_handler)); lua_pushlightuserdata(L, l); } else @@ -946,7 +984,7 @@ LuaUnRegEvent(lua_State *L) l = (struct listener*)lua_touserdata(L, idx++); handler = luaL_checkstring(L, idx++); - /*Validate the listener structure*/ + /* Validate the listener structure */ if (!l || !l->handler || strncmp((char *)handler, (char *)l->handler, SEVNAME_MAX)) { diff --git a/src/script.c b/src/script.c index 6804f69..22b8a27 100644 --- a/src/script.c +++ b/src/script.c @@ -198,6 +198,7 @@ register_listener(struct script_event *ev, struct listener *l) unsigned int priv = l->priv; struct listener *p, *iter = &ev->listeners; +#if 0 while(iter->chain && priv >= iter->chain->priv) { iter = iter->chain; @@ -206,17 +207,9 @@ register_listener(struct script_event *ev, struct listener *l) && iter->dispatcher == l->dispatcher) return 1; } +#endif p = iter; - while(iter->chain) - { - iter = iter->chain; - /* return if duplicate found*/ - if (iter->handler == l->handler - && iter->dispatcher == l->dispatcher) - return 1; - } - l->chain = p->chain; l->prev = p; if (p->chain) diff --git a/src/scripts/cmdcallback.lua b/src/scripts/cmdcallback.lua dissimilarity index 82% index 1ab01d0..84bb380 100644 --- a/src/scripts/cmdcallback.lua +++ b/src/scripts/cmdcallback.lua @@ -1,22 +1,31 @@ ---[[ For now, this sample function will simply record all the commands executed ]]-- -function command_executed(name, args) - os.execute('mkdir -p /tmp/debug') - local f = io.open('/tmp/debug/ll', 'a') - f:write("Command executed: " .. name) - - for i, c in pairs(args) do - f:write(" " .. c) - end - - f:write("\n") - f:close() -end - -function toggle_cmd_log() - if (type(ticket) == "nil") then - ticket = screen.hook("cmdexecuted", "command_executed") - else - screen.unhook(ticket, "command_executed") - ticket = nil - end -end +--[[ For now, this sample function will simply record all the commands executed ]]-- +screen.hook("cmdexecuted", function(name, args) + os.execute('mkdir -p /tmp/debug') + local f = io.open('/tmp/debug/22', 'a') + f:write("Command executed: " .. name) + + for i, c in pairs(args) do + f:write(" " .. c) + end + + f:write("\n") + f:close() + return 0 + end) + +function cmd(name, args) + os.execute('mkdir -p /tmp/debug') + local f = io.open('/tmp/debug/11', 'a') + f:write("Command executed: " .. name) + + for i, c in pairs(args) do + f:write(" " .. c) + end + + f:write("\n") + f:close() + return 0 +end + +screen.hook("cmdexecuted", "cmd") +