class Amun::EventManager

Event manager

Stores a stack of methods to call for each event, when an event is triggered it executes methods in Last-In-First-Out if a method returned true it continue execution of the next item in stack, if the method returned false it will stop executing the rest of stack.

Usage

could be used to register keyboard events, registering a set of actions to be executed when a key combination is pressed, the stack implementation will help stop execution at certain action if it needs to hijack that key.

Also could be used to as instrumentation tool between modules, some modules register for event, and others fire it when happens, e.g Window module needs to update it's title when a file is saved, so it register update_title method to after_file_save event, when the Buffer module saves a file it should trigger that event, which executed the update_title.

Constants

CHAINED

Event needs to be chained, will wait for next event

CONTINUE

Event is to be continued

INTERRUPTED

Event is interrupted and no need to continue

Public Class Methods

clear() click to toggle source

clear the globally bound events if you need to reset this class to its default state, this method should clear all events and its associated objects/methods

# File lib/amun/event_manager.rb, line 156
def clear
  @instance = nil
end
join(event, *event_managers) click to toggle source

trigger an array of event_managers with an event and return one of the 3 statuses (INTERRUPTED, CHAINED, CONTINUE)

if any manager returned false or INTERRUPTED will not execute further and return INTERRUPTED,

if it faced an event that wants to chain the event it will return CHAINED if all next managers returned CONTINUE or also CHAINED

will return CONTINUE if all manangers returned continue

event(Symbol)

an event to trigger on all provided managers

*event_managers(*Array)

you can pass as many event managers as

you like as parameters to this method, it will be triggered in order

# File lib/amun/event_manager.rb, line 138
def join(event, *event_managers)
  event_managers.inject(CONTINUE) do |result, manager|
    case manager.trigger(event)
    when INTERRUPTED, false
      break INTERRUPTED
    when CHAINED
      CHAINED
    else
      result
    end
  end
end
new() click to toggle source
# File lib/amun/event_manager.rb, line 30
def initialize
  @bindings = Hash.new { |h, k| h[k] = [] }
  @chains = Set.new
end

Private Class Methods

instance() click to toggle source
# File lib/amun/event_manager.rb, line 162
def instance
  @instance ||= new
end

Public Instance Methods

bind(event, object, method) click to toggle source

register an objects' method to be executed when the event is triggered

event(String)

and event to bind the method to

object(Object)

an object or class, that respond to method

method(Symbol)

a method name that should be executed when the event

is triggered

# File lib/amun/event_manager.rb, line 42
def bind(event, object, method)
  if !object.nil? && !object.respond_to?(method)
    raise ArgumentError, "#{method} : is not a method for #{object}"
  end

  add_chain(event.to_s)
  @bindings[event.to_s].unshift(object: object, method: method)
end
bind_all(object, method) click to toggle source

bind an object method to be executed when any event is triggered it uses a stack called all to register this method, this stack will be executed after the event specific stack is executed and didn't stop execution

# File lib/amun/event_manager.rb, line 68
def bind_all(object, method)
  bind "all", object, method
end
trigger(event) click to toggle source

execute event stack of methods in Last-In-First-Out, then execute methods registered to be executed after all events with bind_all method if any method in this chain returned false, it will stop the rest of the stack.

a chained event is an event that contain a space between 2 or more events lie “C-c C-x” so this event should be executed when these 2 events occure after each other, if you tried to trigger the first part C-c the trigger method will return CHAINED, assuming that C-c is not handled and also if handled the handle execution didn't return false to interrupt the execution

# File lib/amun/event_manager.rb, line 94
def trigger(event)
  return INTERRUPTED unless trigger_for_event(event, event) &&
                            trigger_for_event("all", event)
  return CHAINED if chained?(event)
  CONTINUE
end
unbind(event, object, method) click to toggle source

remove all occurence of method from the event stack

event(String)

the event name

object(Object)

object that we bind it's method before

method(Symbol)

method name we bind before

# File lib/amun/event_manager.rb, line 56
def unbind(event, object, method)
  @bindings[event].delete_if do |binding|
    binding[:object] == object && binding[:method] == method
  end
  @bindings.delete(event) if @bindings[event].empty?
  update_chains
end
unbind_all(object, method) click to toggle source

remove the method from executing after every event, only if you registered this method with bind_all,

this won't remove the method if it was registered with bind

# File lib/amun/event_manager.rb, line 76
def unbind_all(object, method)
  unbind "all", object, method
end

Private Instance Methods

add_chain(event) click to toggle source
# File lib/amun/event_manager.rb, line 182
def add_chain(event)
  return unless event.to_s.include?(' ')
  event.to_s.split(" ")[0...-1].inject("") do |chain, evt|
    new_chain = (chain + " " + evt).strip
    @chains << new_chain
    new_chain
  end
end
chained?(event) click to toggle source
# File lib/amun/event_manager.rb, line 191
def chained?(event)
  @chains.include? event
end
trigger_for_event(stack, event) click to toggle source
# File lib/amun/event_manager.rb, line 169
def trigger_for_event(stack, event)
  @bindings[stack].all? do |binding|
    binding[:object].send binding[:method], event
  end
end
update_chains() click to toggle source
# File lib/amun/event_manager.rb, line 175
def update_chains
  @chains = Set.new
  @bindings.each do |event|
    add_chain(event)
  end
end