module Safubot ## # A mixin granting simple event firing and handler binding. module Evented ## # Binds an event handler, which is a Hash of the form: # # { :evid => Symbol, :id => Symbol, :repeat => Boolean, :proc => Proc } # # See {on}[rdoc-ref:Safubot::Evented#on] and {once}[rdoc-ref:Safubot::Evented#once] for sugar. def bind(evid, handler) @handlers ||= {} @handlers[evid] ||= {} handler[:evid] = evid handler[:id] ||= @handlers[evid].length @handlers[evid][handler[:id]] = handler end ## # Unbinds the given handler. def unbind(handler) @handlers[handler[:evid]].delete(handler[:id]) end ## # Binds a block to the specified event id. # Returns the bound handler. def on(evid, opts={}, &callback) bind(evid, { :repeat => true, :proc => callback }.merge(opts)) end ## # Binds a block to the specified event id, to be executed only once. # Returns the bound handler. def once(evid, opts={}, &callback) bind(evid, { :repeat => false, :proc => callback }.merge(opts)) end ## # Fires an evid event with the given arguments. def emit(evid, *args) return unless @handlers && @handlers[evid] @handlers[evid].each do |id, handler| begin handler[:proc].call(*args) ensure @handlers[evid].delete(id) if !handler[:repeat] end end end end end