/
base.cr
71 lines (62 loc) · 1.91 KB
/
base.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
module EventEmitter
class Base
record Event, id : Int32, event : String | Regex, listener : Any ->, once : Bool = false
@events = [] of Event
# Listen to all events and run the specified block. This is the
# same as doing `emitter.on(/.*/) { ... }`
def all(once = false, &block : Any ->)
on(/.*/, once: once, &block)
end
# Listen for a particular `event` and fire the block
# every time that event is called. If `once` is `true`
# the event will be removed after it is fired the
# first time.
def on(event, *, once = false, &block : Any ->)
event = event.to_s unless event.is_a?(Regex)
id = @events.empty? ? 0 : @events.last.id + 1
@events << Event.new(
id: id,
event: event,
listener: block,
once: once
)
id
end
# Sugar for `on(event, once: true)`. Will fire the
# event once and then remove the listener.
def once(event, &block : Any ->)
on(event, once: true, &block)
end
# Emit an event with the specified `arg`
def emit(event, arg = nil)
event = event.to_s unless event.is_a?(String)
@events.each do |e|
spawn do
case e.event
when Regex
if event =~ e.event
listener = e.listener
listener.call(EventEmitter.any(arg))
end
when event
listener = e.listener
listener.call(EventEmitter.any(arg))
end
if e.once
remove_listener(e.id)
end
end
end
Fiber.yield
end
# Remove an event listener by id or event.
def remove_listener(id_or_event)
if id_or_event.is_a?(Int)
@events = @events.reject { |e| e.id == id_or_event }
else
event = id_or_event.is_a?(Regex) ? id_or_event : id_or_event.to_s
@events = @events.reject { |e| event == e.event }
end
end
end
end