SergOmarov

event.lua

Oct 18th, 2015
70
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local computer = require("computer")
  2. local keyboard = require("keyboard")
  3.  
  4. local event, listeners, timers = {}, {}, {}
  5. local lastInterrupt = -math.huge
  6.  
  7. local function call(callback, ...)
  8. local result, message = pcall(callback, ...)
  9. if not result and type(event.onError) == "function" then
  10. pcall(event.onError, message)
  11. return
  12. end
  13. return message
  14. end
  15.  
  16. local function dispatch(signal, ...)
  17. if listeners[signal] then
  18. local function callbacks()
  19. local list = {}
  20. for index, listener in ipairs(listeners[signal]) do
  21. list[index] = listener
  22. end
  23. return list
  24. end
  25. for _, callback in ipairs(callbacks()) do
  26. if call(callback, signal, ...) == false then
  27. event.ignore(signal, callback) -- alternative method of removing a listener
  28. end
  29. end
  30. end
  31. end
  32.  
  33. local function tick()
  34. local function elapsed()
  35. local list = {}
  36. for id, timer in pairs(timers) do
  37. if timer.after <= computer.uptime() then
  38. table.insert(list, timer.callback)
  39. timer.times = timer.times - 1
  40. if timer.times <= 0 then
  41. timers[id] = nil
  42. else
  43. timer.after = computer.uptime() + timer.interval
  44. end
  45. end
  46. end
  47. return list
  48. end
  49. for _, callback in ipairs(elapsed()) do
  50. call(callback)
  51. end
  52. end
  53.  
  54. local function createPlainFilter(name, ...)
  55. local filter = table.pack(...)
  56. if name == nil and filter.n == 0 then
  57. return nil
  58. end
  59.  
  60. return function(...)
  61. local signal = table.pack(...)
  62. if name and not (type(signal[1]) == "string" and signal[1]:match(name)) then
  63. return false
  64. end
  65. for i = 1, filter.n do
  66. if filter[i] ~= nil and filter[i] ~= signal[i + 1] then
  67. return false
  68. end
  69. end
  70. return true
  71. end
  72. end
  73.  
  74. local function createMultipleFilter(...)
  75. local filter = table.pack(...)
  76. if filter.n == 0 then
  77. return nil
  78. end
  79.  
  80. return function(...)
  81. local signal = table.pack(...)
  82. if type(signal[1]) ~= "string" then
  83. return false
  84. end
  85. for i = 1, filter.n do
  86. if filter[i] ~= nil and signal[1]:match(filter[i]) then
  87. return true
  88. end
  89. end
  90. return false
  91. end
  92. end
  93. -------------------------------------------------------------------------------
  94.  
  95. function event.cancel(timerId)
  96. checkArg(1, timerId, "number")
  97. if timers[timerId] then
  98. timers[timerId] = nil
  99. return true
  100. end
  101. return false
  102. end
  103.  
  104. function event.ignore(name, callback)
  105. if listeners[name] then
  106. for i = 1, #listeners[name] do
  107. if listeners[name][i] == callback then
  108. table.remove(listeners[name], i)
  109. if #listeners[name] == 0 then
  110. listeners[name] = nil
  111. end
  112. return true
  113. end
  114. end
  115. end
  116. return false
  117. end
  118.  
  119. function event.listen(name, callback)
  120. if listeners[name] then
  121. for i = 1, #listeners[name] do
  122. if listeners[name][i] == callback then
  123. return false
  124. end
  125. end
  126. else
  127. listeners[name] = {}
  128. end
  129. table.insert(listeners[name], callback)
  130. return true
  131. end
  132.  
  133. function event.onError(message)
  134. local log = io.open("/tmp/event.log", "a")
  135. if log then
  136. log:write(message .. "\n")
  137. log:close()
  138. end
  139. end
  140.  
  141. function event.pull(...)
  142. local args = table.pack(...)
  143. if type(args[1]) == "string" then
  144. return event.pullFiltered(createPlainFilter(...))
  145. else
  146. return event.pullFiltered(args[1], createPlainFilter(select(2, ...)))
  147. end
  148. end
  149.  
  150. function event.pullMultiple(...)
  151. local seconds
  152. local args
  153. args = table.pack(...)
  154. return event.pullFiltered(seconds, createMultipleFilter(table.unpack(args, 1, args.n)))
  155.  
  156. end
  157.  
  158. function event.pullFiltered(...)
  159. local args = table.pack(...)
  160. local seconds, filter
  161.  
  162. if type(args[1]) == "function" then
  163. filter = args[1]
  164. else
  165. seconds = args[1]
  166. filter = args[2]
  167. end
  168.  
  169. local deadline = seconds and
  170. (computer.uptime() + seconds) or
  171. (filter and math.huge or 0)
  172. repeat
  173. local closest = seconds and deadline or math.huge
  174. for _, timer in pairs(timers) do
  175. closest = math.min(closest, timer.after)
  176. end
  177. local signal = table.pack(computer.pullSignal(closest - computer.uptime()))
  178. if signal.n > 0 then
  179. dispatch(table.unpack(signal, 1, signal.n))
  180. end
  181. tick()
  182. if event.shouldInterrupt() then
  183. lastInterrupt = computer.uptime()
  184. error("interrupted", 0)
  185. end
  186. if event.shouldSoftInterrupt() and (filter == nil or filter("interrupted", computer.uptime() - lastInterrupt)) then
  187. local awaited = computer.uptime() - lastInterrupt
  188. lastInterrupt = computer.uptime()
  189. return "interrupted", awaited
  190. end
  191. if not (seconds or filter) or filter == nil or filter(table.unpack(signal, 1, signal.n)) then
  192. return table.unpack(signal, 1, signal.n)
  193. end
  194. until computer.uptime() >= deadline
  195. end
  196.  
  197. function event.shouldInterrupt()
  198. return computer.uptime() - lastInterrupt > 1 and
  199. keyboard.isControlDown() and
  200. keyboard.isAltDown() and
  201. keyboard.isKeyDown(keyboard.keys.c)
  202. end
  203.  
  204. function event.shouldSoftInterrupt()
  205. return computer.uptime() - lastInterrupt > 1 and
  206. keyboard.isControlDown() and
  207. keyboard.isKeyDown(keyboard.keys.c)
  208. end
  209.  
  210. function event.timer(interval, callback, times)
  211. local id
  212. repeat
  213. id = math.floor(math.random(1, 0x7FFFFFFF))
  214. until not timers[id]
  215. timers[id] = {
  216. interval = interval,
  217. after = computer.uptime() + interval,
  218. callback = callback,
  219. times = times or 1
  220. }
  221. return id
  222. end
  223.  
  224. -------------------------------------------------------------------------------
  225.  
  226. return event
RAW Paste Data