local M = {} function M.new_store() return {} end function M.add(store, event_name, fn) if type(event_name) ~= "string" or event_name == "" then return false, "event name must be a non-empty string" end if type(fn) ~= "function" then return false, "hook must be a function" end local bucket = store[event_name] if not bucket then bucket = {} store[event_name] = bucket end bucket[#bucket + 1] = fn return true end function M.run(store, event_name, ...) local bucket = store[event_name] if not bucket then return true end local ok_all = true for i = 1, #bucket do local ok, err = pcall(bucket[i], ...) if not ok then ok_all = false print(string.format("lemacs hook error [%s]: %s", event_name, tostring(err))) end end return ok_all end function M.run_first_truthy(store, event_name, ...) local bucket = store[event_name] if not bucket then return false end for i = 1, #bucket do local ok, result = pcall(bucket[i], ...) if not ok then print(string.format("lemacs hook error [%s]: %s", event_name, tostring(result))) elseif result then return true end end return false end return M