Eventable

A Series of Tubes for Lua tables.

Eventable lightly extends your tables to create a "network" of tables that can listen for, and send events. Works across modules too. It's basically a chat room for your tables and mods.

Install

Put the Eventable.lua somewhere in your project, and require it where ever you need it

--== main.lua ==--
local Eventable = require('Eventable')

Usage

For a table to be part of the Eventable messaging loop, it must be evented like so:

local et = require('Eventable')

--== evented table
local tbl = et:new()

You now have a table that is also part of the Eventable messaging network. Use it as you would any other table. Just be sure not to overwrite any of the Eventable methods (see API below).

As long as you don't use any of the Eventable method names, you can pass in any starting data table.

local starter_tbl = { username = "Fred", age = 55 }
local etbl = Eventable:new( starter_tbl )

Listening for events in the network.

--== Listening for 'tweet' event
local etbl = et:new()
etbl:on('tweet', function( evt, message )
  print( 'The '..evt.name..' was '..message )
end)

--== Sending
local starter_tbl = { greeting = "Hello!" }
local etbl2 = et:new( starter_tbl ) --wrap it

etbl2:emit('tweet', self.greeting )

--> The tweet was Hello!

Listening for events once.

etbl:once( 'tweet', function( evt, message )
  print( 'tweet: ' .. message )
  print( 'bye tweety!')
end)

--> tweet Goodbye!

--> bye tweety!

The event callback will trigger one time, and never again, unless you re-register the on handler.

Sending events through the network.

etbl:emit('my-event', someval, otherval, alotofvals )

After specifying an event name, you can pass as many arguments as you need, comma separated.

Any evented table can opt-in to listening to any event from any other evented table.

local et = require('Eventable')

--Create some new evented tables
local cook = et:new()
local waiter = et:new()

--Cook waits for order
cook:on('order', function( evt, food )
  print('Now cooking'..food)
  -- ...
  self:emit( 'order-up', food )
end)

--Waiter listens for order
waiter:on('order-up', function( evt, food )
  print( 'Your ' .. food .. ' are served.')
end)

--Waiter places order
waiter:emit('order', 'Pancakes')

--> Now cooking Pancakes

--> Your Panackes are served

Communication through modules.

In this example, the first two modules are listening for a greeting event. The third module emits the event. You might also notice the use of the once method, instead of the more common on. Usually once your greeted, you don't need to be re-greeted. So here once makes sense.

--== mod_one.lua ==--
local et = require('Eventable')
local mod = et:new()

mod:once('greeting', function( evt, message )
  print( message )
end)

return mod
--== mod_two.lua ==--
local et = require('Eventable')
local mod = et:new()

mod:once('greeting', function( evt, message )
  print( 'this is my greeting: ' .. message )
end)

return mod
--== mod_three.lua ==--
local et = require('Eventable')
local mod = et:new()

mod:emit( 'greeting', 'Hello!' )

return mod

--> Hello!

--> this is my greeting: Hello!

Managing your listening options.

Stop listening for a certain event. Other events are unaffected.

etbl:off( 'tweet' )

Stop listening for any and all events.

etbl:allOff()

Once you release events using off or allOff, you will need to re-register your on handler again. You can also use mute, which does not remove your events, as shown below.

Temporary silencing of all events. Events are not released.

-- Mute all events
etbl:mute( true )

-- Listen to all events again
etbl:mute( false )

Check if table listening is muted.

local trueOrFalse = etbl:isMuted()

Eventable API

The following methods are available on any evented table. Please do not overwrite them.

You can call methods directly on the evented table object, or through using self internally.

local etbl = et:new()
etbl:emit('party', 'tonight')
local etbl = et:new()
etbl:goParty = function(when)
  self:emit('party', when)
end
etbl:goParty('tonight')

Methods

:new([starting_table])

Creates a fresh evented table. This table can message with other evented tables and mods. Can optionally take a starting_table that will become 'wrapped' into an evented table.

local et = require('Eventable')

local etbl = et:new()
-- or
local etbl = et:new( { username = "Bob" } )

:emit( event_name, ... )

Broadcast data parameters to any other evented tables listening for this event_name.

local et = require('Eventable')

local etbl = et:new()
etbl:emit( 'greeting', 'Good Day!')

:on( event_name, callback )

Listens for a specific event name to be emitted, and take action with the callback. The callback will return an event object and any other arguments available.

In the event object you can find the event name and target key, which points to the table that triggered this event.

local et = require('Eventable')

local etbl = et:new()
etbl:on('greeting', function( evt, message )
  print( message )
end)

:once( event_name, callback )

Listens for a specific event_name to be emitted, and take action with the callback only one time, and no more.

local et = require('Eventable')

local etbl = et:new()
etbl:once('greeting', function( event, message )
  print( message )
  print( 'Bye bye!')
end)

Something like a "greeting" is a good candidate for using once, since you only greet someone one time each session.


:off( event_name )

Stop listening for the specified event_name. Once a event is turned off, it can only be added as a new on instance. See the mute method for an alternative.

etbl:off( 'greeting' )

Will no longer listen for the greeting event.


:allOff()

Removes all events from the table / mod.

etbl:allOff()

Will no longer listen for any events.

:mute( trueOrFalse )

Mutes all event input while enabled. Event listeners are left active unlike off or allOff.

etbl:mute( true ) --no events read

-- or

etbl:mute( false ) --read events again

Toggle mute for all events. But listeners will remain.

:isMuted()

Checks whether the evented table is muted. Will return true or false.

local is_muted = etbl:isMuted()

Eventable static methods

Print a table into human readable form.

Eventable.p( tbl )

To get a count of all the evented tables.

local count = Eventable.count()

Print all event names active to the terminal. (needs work)

Eventable.list()

Release a table from Eventable messaging loop. You cannot reattach after this action. You must create a new instance. Generally, you shouldn't need to use this action.

Eventable.release( etbl )