Allow using unnamed functions as handlers.
authorSadrul Habib Chowdhury <sadrul@users.sourceforge.net>
Tue, 9 Jun 2009 21:22:19 +0000 (9 17:22 -0400)
committerSadrul Habib Chowdhury <sadrul@users.sourceforge.net>
Tue, 9 Jun 2009 21:23:37 +0000 (9 17:23 -0400)
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]

src/lua.c
src/script.c
src/scripts/cmdcallback.lua

index 0fa4c06..0cee0ee 100644 (file)
--- 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))
     {
index 6804f69..22b8a27 100644 (file)
@@ -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)
dissimilarity index 82%
index 1ab01d0..84bb380 100644 (file)
@@ -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")
+