From 0b03e0980316288706b6cb3ee64cdeeb74ec0acd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20Garc=C3=ADa=20Cota?= Date: Sun, 29 Jan 2012 13:56:34 +0100 Subject: [PATCH] changed "beholder:foo" by "beholder.foo". Removed "self checks" --- README.textile | 62 ++++++++++----------- beholder.lua | 43 +++++++-------- spec/acceptance.lua | 58 ++++++++++---------- spec/unit.lua | 127 ++++++++++++++++++-------------------------- 4 files changed, 133 insertions(+), 157 deletions(-) diff --git a/README.textile b/README.textile index 03d4cd7..eed8dcb 100644 --- a/README.textile +++ b/README.textile @@ -10,18 +10,18 @@ beholder = require 'beholder' ... local goblin1 = {x=100, y=100} -goblin1.pauseId = beholder:observe("PAUSE", function() goblin1.paused = true end) +goblin1.pauseId = beholder.observe("PAUSE", function() goblin1.paused = true end) ... local goblin2 = {x=200, y=100} -goblin2.pauseId = beholder:observe("PAUSE", function() goblin2.paused = true end) +goblin2.pauseId = beholder.observe("PAUSE", function() goblin2.paused = true end) ... function pauseButtonPressed() - beholder:trigger("PAUSE") + beholder.trigger("PAUSE") end @@ -38,23 +38,23 @@ end ... function destroyGoblin(goblin) - beholder:stopObserving(goblin.pauseId) + beholder.stopObserving(goblin.pauseId) end -(Note: if you are doing lots of that "if whatever.state then ..." you might want to give a look to "stateful.lua":http://github.com/kikito/stateful.lua ) +(Note. if you are doing lots of that "if whatever.state then ..." you might want to give a look to "stateful.lua".http.//github.com/kikito/stateful.lua ) h1. Why? -This library tries to solve the following problem: some actions need to be executed when some asynchronous condition is fulfilled. By "asyncronous" we mean that it something that typically doesn't depend on the code. Hence precalculating it beforehand is impractical. +This library tries to solve the following problem. some actions need to be executed when some asynchronous condition is fulfilled. By "asyncronous" we mean that it something that typically doesn't depend on the code. Hence precalculating it beforehand is impractical. -Some examples: +Some examples. * The pause menu is brought up, and all the actors in your videogame need to be frozen. * An image has item has been loaded from disk, and a progress bar needs to be updated. * The user presses certain combination of keys. -The way these problems are typically handed is by continuously polling for the trigger condition. For example, on the pause menu, one would find this code on the enemy movement routines: +The way these problems are typically handed is by continuously polling for the trigger condition. For example, on the pause menu, one would find this code on the enemy movement routines.
 if pause_menu_is_up then
@@ -64,72 +64,72 @@ else
 end
 
-You will have a code similar to that on each part that needs to be stopped: on your enemy code, the bullet code, the player code, etc. +You will have a code similar to that on each part that needs to be stopped. on your enemy code, the bullet code, the player code, etc. But the biggest problem with that code is lack of separation. The code dealign with your goblins should only deal with goblin stuff. It should not "know" about the menu system, or the keyboard actions, or the file loader. And the same goes with your bullet code, player code, etc. They don't need to know about exernal systems, such as the keyboard. -This library allows you to build "walls" between them: your keyboard code will just raise events, and your player code will observe those events. This allows for better encapsulation; if you later add multiplayer functionality, for example, the network module will just have to raise the same events just like the keyboard module did; your player logic will be unaffected. +This library allows you to build "walls" between them. your keyboard code will just raise events, and your player code will observe those events. This allows for better encapsulation; if you later add multiplayer functionality, for example, the network module will just have to raise the same events just like the keyboard module did; your player logic will be unaffected. You can obviously attach any number of observers to any given event. Similarly, you are h1. Halting event observation -Every call to @beholder:observe@ returns an identifier which can be stored: +Every call to @beholder.observe@ returns an identifier which can be stored. -
local id = beholder:observe("FOO", bar, baz)
+
local id = beholder.observe("FOO", bar, baz)
-That identifier can be used to cancel the observation at any moment. You can do so by using the @beholder:stopObserving@ method: +That identifier can be used to cancel the observation at any moment. You can do so by using the @beholder.stopObserving@ method. -
beholder:stopObserving(id)
+
beholder.stopObserving(id)
h1. Composed events Events can be any type of Lua object. On the example, we used the "PAUSE" string. It could also be a number, a function or a table. The == operator is used in all cases. -Composed events are built from more than one lua object. You can do them by simply adding more parameters to the observe/trigger functions. For example, this trigger: +Composed events are built from more than one lua object. You can do them by simply adding more parameters to the observe/trigger functions. For example, this trigger. -
Beholder:trigger('PLAYERDETECTION', player1, 100, 200)
+
Beholder.trigger('PLAYERDETECTION', player1, 100, 200)
-Will trigger this action: +Will trigger this action. -
Beholder:observe('PLAYERDETECTION', player1, 100, 200, function() print("player1 detected at 100, 200") end)
+
Beholder.observe('PLAYERDETECTION', player1, 100, 200, function() print("player1 detected at 100, 200") end)
Composed events are inclusive. This means that this other observer will also get activated by the aforementioned trigger. -
Beholder:observe('PLAYERDETECTION', player1, function(x,y) print("player1 detected at ",x,y)
+
Beholder.observe('PLAYERDETECTION', player1, function(x,y) print("player1 detected at ",x,y)
Notice that the two "non-observed integers" will be passed to the callback as additional parameters. That second action will be executed any time player1 is detected, no matter what coordinates. -Similarly, you can add an action that will be triggered for any player detection: +Similarly, you can add an action that will be triggered for any player detection. -
Beholder:observe('PLAYERDETECTION', function(player,x,y) print(player.no," detected at ",x,y)
+
Beholder.observe('PLAYERDETECTION', function(player,x,y) print(player.no," detected at ",x,y)
h1. The nil event -If you want to detect all signals raised (i.e. for logging and debugging) you can do so by observing the "empty" event - simply pass a function to observe, without adding any more params: +If you want to detect all signals raised (i.e. for logging and debugging) you can do so by observing the "empty" event - simply pass a function to observe, without adding any more params. -
Beholder:observe(function(...) log("Event triggered", ...) end)
+
Beholder.observe(function(...) log("Event triggered", ...) end)
-A quick and dirty way of dumping all events in the standard output is just observing the nil event with @print@: +A quick and dirty way of dumping all events in the standard output is just observing the nil event with @print@. -
Beholder:observe(print)
+
Beholder.observe(print)
-If you want to trigger the events attached only to the nil event, you can do so by calling trigger without params: +If you want to trigger the events attached only to the nil event, you can do so by calling trigger without params. -
Beholder:trigger()
+
Beholder.trigger()
h1. Triggering all callbacks -You can use the @triggerAll@ method to trigger all observed events (this will be useful mostly for debugging): +You can use the @triggerAll@ method to trigger all observed events (this will be useful mostly for debugging). -
Beholder:triggerAll(...)
+
Beholder.triggerAll(...)
Note that you can pass parameters to @triggerAll@. These will be passed to all callbacks (make sure that they are prepared for this, or you will get errors). h1. Installation -Just copy the beholder.lua file wherever you want it (for example on a lib/ folder). Then write this in any Lua file where you want to use it: +Just copy the beholder.lua file wherever you want it (for example on a lib/ folder). Then write this in any Lua file where you want to use it.
local Beholder = require 'beholder'
@@ -141,7 +141,7 @@ Please make sure that you read the license, too (for your convenience it's now i h1. Specs -This project uses "telescope":https://github.com/norman/telescope for its specs. If you want to run the specs, you will have to install telescope first. Then just execute the following from the root inspect folder: +This project uses "telescope".https.//github.com/norman/telescope for its specs. If you want to run the specs, you will have to install telescope first. Then just execute the following from the root inspect folder.
 tsc -f spec/*.lua
diff --git a/beholder.lua b/beholder.lua
index 2134e1c..d7f51a2 100644
--- a/beholder.lua
+++ b/beholder.lua
@@ -83,59 +83,56 @@ function Node:removeCallback(id)
   Node._nodesById[id] = nil
 end
 
+
+------ beholder table
+
+local beholder = {}
+
+
 -- beholder private functions
+local root = nil
 
 local function falseIfZero(n)
   return n > 0 and n
 end
 
-local function checkSelf(self, methodName)
-  assert(type(self)=="table" and self._root, "Use beholder:" .. methodName .. " instead of beholder." .. methodName)
-end
-
 local function extractEventAndCallbackFromParams(params)
   assert(#params > 0, "beholder:observe requires at least one parameter - the callback. You usually want to use two, i.e.: beholder:observe('EVENT', callback)")
   local callback = table.remove(params, #params)
   return params, callback
 end
 
-local function initialize(self)
-  self._root = Node:new()
+local function initialize()
+  root = Node:new()
 end
 
+
 ------ Public interface
 
-local beholder = {}
-
-function beholder:observe(...)
-  checkSelf(self, 'observe')
+function beholder.observe(...)
   local event, callback = extractEventAndCallbackFromParams({...})
-  return self._root:findOrCreateDescendant(event):addCallback(callback)
+  return root:findOrCreateDescendant(event):addCallback(callback)
 end
 
-function beholder:stopObserving(id)
-  checkSelf(self, 'stopObserving')
+function beholder.stopObserving(id)
   local node = Node:findById(id)
   if not node then return false end
   node:removeCallback(id)
   return true
 end
 
-function beholder:trigger(...)
-  checkSelf(self, 'trigger')
-  return falseIfZero( self._root:invokeCallbacksFromPath({...}) )
+function beholder.trigger(...)
+  return falseIfZero( root:invokeCallbacksFromPath({...}) )
 end
 
-function beholder:triggerAll(...)
-  checkSelf(self, 'triggerAll')
-  return falseIfZero( self._root:invokeAllCallbacksInSubTree({...}) )
+function beholder.triggerAll(...)
+  return falseIfZero( root:invokeAllCallbacksInSubTree({...}) )
 end
 
-function beholder:reset()
-  checkSelf(self, 'reset')
-  initialize(self)
+function beholder.reset()
+  initialize()
 end
 
-initialize(beholder)
+initialize()
 
 return beholder
diff --git a/spec/acceptance.lua b/spec/acceptance.lua
index 4630c0c..585769a 100644
--- a/spec/acceptance.lua
+++ b/spec/acceptance.lua
@@ -4,23 +4,23 @@ local beholder = require 'beholder'
 describe("Acceptance", function()
 
   before(function()
-    beholder:reset()
+    beholder.reset()
   end)
 
   test("Normal behavior", function()
 
     local counter = 0
 
-    local id = beholder:observe("EVENT", function() counter = counter + 1 end)
+    local id = beholder.observe("EVENT", function() counter = counter + 1 end)
 
-    beholder:trigger("EVENT")
-    beholder:trigger("EVENT")
+    beholder.trigger("EVENT")
+    beholder.trigger("EVENT")
 
     assert_equal(counter, 2)
 
-    beholder:stopObserving(id)
+    beholder.stopObserving(id)
 
-    beholder:trigger("EVENT")
+    beholder.trigger("EVENT")
 
     assert_equal(counter, 2)
 
@@ -30,24 +30,24 @@ describe("Acceptance", function()
 
     local counter1, counter2 = 0,0
 
-    local id1 = beholder:observe("EVENT", function() counter1 = counter1 + 1 end)
-    local id2 = beholder:observe("EVENT", function() counter2 = counter2 + 1 end)
+    local id1 = beholder.observe("EVENT", function() counter1 = counter1 + 1 end)
+    local id2 = beholder.observe("EVENT", function() counter2 = counter2 + 1 end)
 
-    beholder:trigger("EVENT")
-    beholder:trigger("EVENT")
+    beholder.trigger("EVENT")
+    beholder.trigger("EVENT")
 
     assert_equal(counter1, 2)
     assert_equal(counter2, 2)
 
-    beholder:stopObserving(id1)
+    beholder.stopObserving(id1)
 
-    beholder:trigger("EVENT")
+    beholder.trigger("EVENT")
     assert_equal(counter1, 2)
     assert_equal(counter2, 3)
 
-    beholder:stopObserving(id2)
+    beholder.stopObserving(id2)
 
-    beholder:trigger("EVENT")
+    beholder.trigger("EVENT")
     assert_equal(counter1, 2)
     assert_equal(counter2, 3)
 
@@ -59,17 +59,17 @@ describe("Acceptance", function()
     local enterPressed = false
     local escapePressed = false
 
-    beholder:observe("KEYPRESS", function() counter = counter + 1 end)
-    beholder:observe("KEYPRESS", function(key) lastKey = key end)
-    beholder:observe("KEYPRESS", "enter", function() enterPressed = true end)
+    beholder.observe("KEYPRESS", function() counter = counter + 1 end)
+    beholder.observe("KEYPRESS", function(key) lastKey = key end)
+    beholder.observe("KEYPRESS", "enter", function() enterPressed = true end)
 
-    beholder:trigger("KEYPRESS", "space")
+    beholder.trigger("KEYPRESS", "space")
     assert_equal(counter, 1)
     assert_equal(lastKey, "space")
     assert_false(enterPressed)
     assert_false(escapePressed)
 
-    beholder:trigger("KEYPRESS", "enter")
+    beholder.trigger("KEYPRESS", "enter")
     assert_equal(counter, 2)
     assert_equal(lastKey, "enter")
     assert_true(enterPressed)
@@ -79,18 +79,18 @@ describe("Acceptance", function()
   test("nil events", function()
     local counter = 0
 
-    local id = beholder:observe(function(_, x) counter = counter + x end)
+    local id = beholder.observe(function(_, x) counter = counter + x end)
 
-    beholder:trigger("FOO", 1)
-    beholder:trigger("BAR", 2)
+    beholder.trigger("FOO", 1)
+    beholder.trigger("BAR", 2)
 
     assert_equal(3, counter)
 
-    beholder:stopObserving(id)
+    beholder.stopObserving(id)
 
-    beholder:observe(function() counter = 10 end)
+    beholder.observe(function() counter = 10 end)
 
-    beholder:trigger()
+    beholder.trigger()
 
     assert_equal(10, counter)
   end)
@@ -99,15 +99,15 @@ describe("Acceptance", function()
     local even = 0
     local uneven = 1
 
-    beholder:observe("EVEN", function(x) even = even + 2*x end)
-    beholder:observe("UNEVEN", function(x) uneven = uneven + 2*x end)
+    beholder.observe("EVEN", function(x) even = even + 2*x end)
+    beholder.observe("UNEVEN", function(x) uneven = uneven + 2*x end)
 
-    beholder:triggerAll(1)
+    beholder.triggerAll(1)
 
     assert_equal(even, 2)
     assert_equal(uneven, 3)
 
-    beholder:triggerAll(2)
+    beholder.triggerAll(2)
 
     assert_equal(even, 6)
     assert_equal(uneven, 7)
diff --git a/spec/unit.lua b/spec/unit.lua
index 9178df9..422a074 100644
--- a/spec/unit.lua
+++ b/spec/unit.lua
@@ -3,84 +3,77 @@ local beholder = require 'beholder'
 describe("Unit", function()
 
   before(function()
-    beholder:reset()
+    beholder.reset()
   end)
 
-  describe(":observe", function()
-    it("checks self", function()
-      assert_error(function() beholder.observe("X", function() end) end)
-    end)
-
+  describe(".observe", function()
     it("notices simple events so that trigger works", function()
       local counter = 0
-      beholder:observe("EVENT", function() counter = counter + 1 end)
-      beholder:trigger("EVENT")
+      beholder.observe("EVENT", function() counter = counter + 1 end)
+      beholder.trigger("EVENT")
       assert_equal(counter, 1)
     end)
 
     it("remembers if more than one action is associated to the same event", function()
       local counter1, counter2 = 0,0
-      beholder:observe("EVENT", function() counter1 = counter1 + 1 end)
-      beholder:observe("EVENT", function() counter2 = counter2 + 1 end)
-      beholder:trigger("EVENT")
+      beholder.observe("EVENT", function() counter1 = counter1 + 1 end)
+      beholder.observe("EVENT", function() counter2 = counter2 + 1 end)
+      beholder.trigger("EVENT")
       assert_equal(counter1, 1)
       assert_equal(counter2, 1)
     end)
 
     it("allows observing composed events", function()
       local counter = 0
-      beholder:observe("KEYPRESS", "start", function() counter = counter + 1 end)
-      beholder:trigger("KEYPRESS", "start")
+      beholder.observe("KEYPRESS", "start", function() counter = counter + 1 end)
+      beholder.trigger("KEYPRESS", "start")
       assert_equal(counter, 1)
     end)
 
     it("observes all events with the nil event", function()
       local counter = 0
-      beholder:observe(function(_,x) counter = counter + x end)
-      beholder:trigger("FOO", 1)
-      beholder:trigger("BAR", 2)
+      beholder.observe(function(_,x) counter = counter + x end)
+      beholder.trigger("FOO", 1)
+      beholder.trigger("BAR", 2)
       assert_equal(3, counter)
     end)
 
     it("throws an error if called without at least one parameter", function()
-      assert_error(function() beholder:observe() end)
+      assert_error(function() beholder.observe() end)
     end)
 
     it("does not store hard references to variables", function()
       local counter = 0
       local x = {}
-      beholder:observe(x, function() counter = counter + 1 end)
-      beholder:triggerAll()
+      beholder.observe(x, function() counter = counter + 1 end)
+      beholder.triggerAll()
       x = nil
       collectgarbage("collect")
-      beholder:triggerAll()
+      beholder.triggerAll()
       assert_equal(1, counter)
     end)
   end)
 
-  describe(":stopObserving", function()
-    it("checks self", function()
-      assert_error(function() beholder.stopObserving() end)
-    end)
+  describe(".stopObserving", function()
     it("stops noticing events so trigger doesn't work any more", function()
       local counter = 0
-      local id = beholder:observe("EVENT", function() counter = counter + 1 end)
-      beholder:trigger("EVENT")
-      beholder:stopObserving(id)
-      beholder:trigger("EVENT")
+      local id = beholder.observe("EVENT", function() counter = counter + 1 end)
+      beholder.trigger("EVENT")
+      beholder.stopObserving(id)
+      beholder.trigger("EVENT")
       assert_equal(counter, 1)
     end)
 
     it("stops observing one id without disturbing the others", function()
       local counter1, counter2 = 0,0
-      local id1 = beholder:observe("EVENT", function() counter1 = counter1 + 1 end)
-      beholder:observe("EVENT", function() counter2 = counter2 + 1 end)
-      beholder:trigger("EVENT")
+      local id1 = beholder.observe("EVENT", function() counter1 = counter1 + 1 end)
+      beholder.observe("EVENT", function() counter2 = counter2 + 1 end)
+      beholder.trigger("EVENT")
 
       assert_equal(counter1, 1)
       assert_equal(counter2, 1)
-      beholder:stopObserving(id1)
-      beholder:trigger("EVENT")
+      beholder.stopObserving(id1)
+      beholder.trigger("EVENT")
 
       assert_equal(counter1, 1)
       assert_equal(counter2, 2)
@@ -90,95 +83,81 @@ describe("Unit", function()
     it("passes parameters to the actions", function()
       local counter = 0
 
-      beholder:observe("EVENT", function(x) counter = counter + x end)
-      beholder:trigger("EVENT", 1)
+      beholder.observe("EVENT", function(x) counter = counter + x end)
+      beholder.trigger("EVENT", 1)
 
       assert_equal(counter, 1)
-      beholder:trigger("EVENT", 5)
+      beholder.trigger("EVENT", 5)
 
       assert_equal(counter, 6)
     end)
 
     it("does not raise an error when stopping observing an inexisting event", function()
-      assert_not_error(function() beholder:stopObserving({}) end)
+      assert_not_error(function() beholder.stopObserving({}) end)
     end)
 
     it("returns false when no action was found for an id", function()
-      assert_equal(false, beholder:stopObserving({}))
+      assert_equal(false, beholder.stopObserving({}))
     end)
 
     it("returns true when an action was found and removed", function()
-      local id = beholder:observe("X", function() end)
-      assert_true(beholder:stopObserving(id))
+      local id = beholder.observe("X", function() end)
+      assert_true(beholder.stopObserving(id))
     end)
 
   end)
 
-  describe(":trigger", function()
-    it("checks self", function()
-      assert_error(function() beholder.trigger() end)
-    end)
+  describe(".trigger", function()
     it("does not error on random stuff", function()
-      assert_not_error(function() beholder:trigger("FOO") end)
+      assert_not_error(function() beholder.trigger("FOO") end)
     end)
 
     it("returns false on events with no actions", function()
-      assert_equal(false, beholder:trigger("FOO"))
+      assert_equal(false, beholder.trigger("FOO"))
     end)
 
     it("returns false if there was a node with no actions", function()
-      beholder:observe("ONE","TWO", function() end)
-      assert_equal(false, beholder:trigger("ONE"))
+      beholder.observe("ONE","TWO", function() end)
+      assert_equal(false, beholder.trigger("ONE"))
     end)
 
     it("returns the number of actions executed", function()
-      beholder:observe("X", function() end)
-      beholder:observe("X", function() end)
-      assert_equal(2, beholder:trigger("X"))
+      beholder.observe("X", function() end)
+      beholder.observe("X", function() end)
+      assert_equal(2, beholder.trigger("X"))
     end)
 
     it("triggers callbacks within the nil event only", function()
       local counter = 0
-      beholder:observe("X", function() counter = counter + 10 end)
-      beholder:observe(function() counter = counter + 5 end)
+      beholder.observe("X", function() counter = counter + 10 end)
+      beholder.observe(function() counter = counter + 5 end)
 
-      beholder:trigger()
+      beholder.trigger()
 
       assert_equal(5, counter)
     end)
   end)
 
-  describe(":triggerAll", function()
-    it("checks self", function()
-      assert_error(function() beholder.triggerAll() end)
-    end)
+  describe(".triggerAll", function()
     it("calls all registered callbacks", function()
       local counter = 0
-      beholder:observe("X", function() counter = counter + 1 end)
-      beholder:triggerAll()
+      beholder.observe("X", function() counter = counter + 1 end)
+      beholder.triggerAll()
       assert_equal(1, counter)
     end)
     it("passes parameters to callbacks", function()
       local counter = 0
-      beholder:observe(function(x) counter = counter + x end)
-      beholder:triggerAll(2)
+      beholder.observe(function(x) counter = counter + x end)
+      beholder.triggerAll(2)
       assert_equal(2, counter)
     end)
     it("returns false if no actions where found", function()
-      assert_false(beholder:triggerAll())
+      assert_false(beholder.triggerAll())
     end)
     it("returns the number of actions executed", function()
-      beholder:observe("X", function() end)
-      beholder:observe("Y", function() end)
-      assert_equal(2, beholder:triggerAll())
+      beholder.observe("X", function() end)
+      beholder.observe("Y", function() end)
+      assert_equal(2, beholder.triggerAll())
     end)
   end)
-
-  describe(":reset", function()
-    it("checks self", function()
-      assert_error(function() beholder.reset() end)
-    end)
-  end)
-
-
 end)