local computer=require("computer") local keyboard=require("keyboard") local event={} local handlers={} local lastInterrupt=-math.huge event.handlers=handlers function event.register(key,callback,interval,times,opt_handlers) local handler= { key=key, times=times or 1, callback=callback, interval=interval or math.huge, } handler.timeout=computer.uptime()+handler.interval opt_handlers=opt_handlers or handlers local id=0 repeat id=id+1 until not opt_handlers[id] opt_handlers[id]=handler return id end local _pullSignal=computer.pullSignal setmetatable(handlers,{__call=function(_,...)return _pullSignal(...)end}) computer.pullSignal=function(seconds) checkArg(1,seconds,"number","nil") seconds=seconds or math.huge local uptime=computer.uptime local deadline=uptime()+seconds repeat local interrupting=uptime()-lastInterrupt>1 and keyboard.isControlDown()and keyboard.isKeyDown(keyboard.keys.c) and(not event.interruptHook or event.interruptHook()) if interrupting then lastInterrupt=uptime() if keyboard.isAltDown()then require("process").info().data.signal("interrupted",0) return end event.push("interrupted",lastInterrupt) end local closest=deadline for _,handler in pairs(handlers)do local timeout=handler.timeout if timeout=handler.timeout then handler.times=handler.times-1 handler.timeout=handler.timeout+handler.interval if handler.times<=0 and handlers[id]==handler then handlers[id]=nil end local result,message=pcall(handler.callback,table.unpack(event_data,1,event_data.n)) if not result then pcall(event.onError,message) elseif message==false and handlers[id]==handler then handlers[id]=nil end end end if signal then return table.unpack(event_data,1,event_data.n) end until uptime()>=deadline end local function createPlainFilter(name,...) local filter=table.pack(...) if name==nil and filter.n==0 then return nil end return function(...) local signal=table.pack(...) if name and not(type(signal[1])=="string"and signal[1]:match(name))then return false end for i=1,filter.n do if filter[i]~=nil and filter[i]~=signal[i+1]then return false end end return true end end function event.listen(name,callback) checkArg(1,name,"string") checkArg(2,callback,"function") for _,handler in pairs(handlers)do if handler.key==name and handler.callback==callback then return false end end return event.register(name,callback,math.huge,math.huge) end function event.pull(...) local args=table.pack(...) if type(args[1])=="string"then return event.pullFiltered(createPlainFilter(...)) else checkArg(1,args[1],"number","nil") checkArg(2,args[2],"string","nil") return event.pullFiltered(args[1],createPlainFilter(select(2,...))) end end function event.pullFiltered(...) local args=table.pack(...) local seconds,filter=math.huge if type(args[1])=="function"then filter=args[1] else checkArg(1,args[1],"number","nil") checkArg(2,args[2],"function","nil") seconds=args[1] filter=args[2] end local deadline=computer.uptime()+(seconds or math.huge) repeat local waitTime=deadline-computer.uptime() if waitTime<0 then break end local signal=table.pack(computer.pullSignal(waitTime)) if signal.n>0 then if not(seconds or filter)or filter==nil or filter(table.unpack(signal,1,signal.n))then return table.unpack(signal,1,signal.n) end end until signal.n==0 end event.push=computer.pushSignal require("package").delay(event,"/lib/core/full_event.lua") return event