Simplify matrix.eventable for the common use cases
This removes the support for passing values to eventable.functions() and eventable.object() which are bound to be passed to handlers. On top of simplifying the code overall, this also avoids having three different implementations of the fire() function. In the existing code, the only case in which a handler argument is fixed is for objects which pass themselves. This use case is covered by eventable.object(), so the removed code was not realy ever used.
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
local _select, _pack, _unpack = select, table.pack, table.unpack or unpack
|
local _select, _pack, _unpack = select, table.pack, table.unpack or unpack
|
||||||
|
|
||||||
if not _pack then
|
if not _pack then
|
||||||
|
-- Provide a table.pack() implementation for Lua 5.1 and LuaJIT.
|
||||||
_pack = function (...)
|
_pack = function (...)
|
||||||
local n = _select("#", ...)
|
local n = _select("#", ...)
|
||||||
local r = { n = n }
|
local r = { n = n }
|
||||||
@@ -18,28 +19,15 @@ if not _pack then
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function _expack (args, ...)
|
|
||||||
local r = { n = args.n }
|
|
||||||
local n = _select("#", ...)
|
|
||||||
for i = 1, args.n do
|
|
||||||
r[i] = args[i]
|
|
||||||
end
|
|
||||||
for i = 1, n do
|
|
||||||
r[r.n + i] = _select(i, ...)
|
|
||||||
end
|
|
||||||
r.n = r.n + n
|
|
||||||
return _unpack(r)
|
|
||||||
end
|
|
||||||
|
|
||||||
local log = (function ()
|
local log = (function ()
|
||||||
local env_value = os.getenv("MATRIX_EVENTABLE_DEBUG_LOG")
|
local env_value = os.getenv("MATRIX_EVENTABLE_DEBUG_LOG")
|
||||||
if env_value and #env_value > 0 and env_value ~= "0" then
|
if env_value and #env_value > 0 and env_value ~= "0" then
|
||||||
local out, _tostring = io.stderr, tostring
|
local out, _tostring = io.stderr, tostring
|
||||||
return function (...)
|
return function (...)
|
||||||
out:write("[eventable]")
|
out:write("[eventable]")
|
||||||
local args = _pack(...)
|
local n = _select("#", ...)
|
||||||
for i = 1, args.n do
|
for i = 1, n do
|
||||||
out:write(" " .. _tostring(args[i]))
|
out:write(" " .. _tostring(_select(i, ...)))
|
||||||
end
|
end
|
||||||
out:write("\n")
|
out:write("\n")
|
||||||
out:flush()
|
out:flush()
|
||||||
@@ -49,10 +37,7 @@ local log = (function ()
|
|||||||
end
|
end
|
||||||
end)()
|
end)()
|
||||||
|
|
||||||
local function eventable_functions (...)
|
local function do_hook(event_map, event, handler)
|
||||||
local event_map = {}
|
|
||||||
|
|
||||||
local hook = function (event, handler)
|
|
||||||
log("hook:", event, handler)
|
log("hook:", event, handler)
|
||||||
if not handler then
|
if not handler then
|
||||||
event_map[event] = nil
|
event_map[event] = nil
|
||||||
@@ -65,7 +50,7 @@ local function eventable_functions (...)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local unhook = function (event, handler)
|
local function do_unhook(event_map, event, handler)
|
||||||
log("unhook:", event, handler)
|
log("unhook:", event, handler)
|
||||||
local old_handlers = event_map[event]
|
local old_handlers = event_map[event]
|
||||||
if old_handlers then
|
if old_handlers then
|
||||||
@@ -80,12 +65,7 @@ local function eventable_functions (...)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local fire
|
local function do_fire(event_map, event, ...)
|
||||||
|
|
||||||
local nargs = _select("#", ...)
|
|
||||||
if nargs == 0 then
|
|
||||||
-- Simplest version, no arguments.
|
|
||||||
fire = function (event, ...)
|
|
||||||
log("fire: " .. event .. ":", ...)
|
log("fire: " .. event .. ":", ...)
|
||||||
local handlers = event_map[event]
|
local handlers = event_map[event]
|
||||||
if handlers then
|
if handlers then
|
||||||
@@ -97,52 +77,26 @@ local function eventable_functions (...)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif nargs == 1 then
|
|
||||||
-- Common single-argument case: optimized.
|
local function eventable_functions (event_map)
|
||||||
local arg = _select(1, ...)
|
if not event_map then event_map = {} end
|
||||||
fire = function (event, ...)
|
return function (e, ...) return do_fire(event_map, e, ...) end,
|
||||||
log("fire: " .. event .. ":", arg, ...)
|
function (e, h) return do_hook(event_map, e, h) end,
|
||||||
local handlers = event_map[event]
|
function (e, h) return do_unhook(event_map, e, h) end
|
||||||
if handlers then
|
|
||||||
for i = 1, #handlers do
|
|
||||||
local ret = _pack(handlers[i](arg, ...))
|
|
||||||
if ret.n > 0 then
|
|
||||||
return _unpack(ret)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- Generic multi-argument case.
|
|
||||||
local args = _pack(...)
|
|
||||||
fire = function (event, ...)
|
|
||||||
log("fire: " .. event .. ":", _expack(args, ...))
|
|
||||||
local handlers = event_map[event]
|
|
||||||
if handlers then
|
|
||||||
for i = 1, #handlers do
|
|
||||||
local ret = _pack(handlers[i](_expack(args, ...)))
|
|
||||||
if ret.n > 0 then
|
|
||||||
return _unpack(ret)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return fire, hook, unhook
|
local function eventable_object(obj, event_map)
|
||||||
end
|
if not obj then obj = {} end
|
||||||
|
if not event_map then event_map = {} end
|
||||||
local function eventable_object(obj)
|
function obj:fire(e, ...)
|
||||||
local fire, hook, unhook = eventable_functions()
|
return do_fire(event_map, e, self, ...)
|
||||||
function obj:fire(name, ...)
|
|
||||||
return fire(name, self, ...)
|
|
||||||
end
|
end
|
||||||
function obj:hook(...)
|
function obj:hook(...)
|
||||||
hook(...)
|
do_hook(event_map, ...)
|
||||||
return self -- Allow chaining
|
return self -- Allow chaining
|
||||||
end
|
end
|
||||||
function obj:unhook(...)
|
function obj:unhook(...)
|
||||||
unhook(...)
|
do_unhook(event_map, ...)
|
||||||
return self -- Allow chaining
|
return self -- Allow chaining
|
||||||
end
|
end
|
||||||
return obj
|
return obj
|
||||||
|
|||||||
Reference in New Issue
Block a user