summaryrefslogtreecommitdiff
path: root/lua/clever_tee/action_facade.lua
diff options
context:
space:
mode:
authorJackson Moore <jacksonmoore@tuta.io>2026-09-04 18:44:32 +0200
committerJackson Moore <jacksonmoore@tuta.io>2026-09-04 18:44:32 +0200
commitc7b14ffb6d14969c9c41864e827f33f8e80fc24e (patch)
treec7c0ac23dc93a4a8b75449d2be4d0e05c4f05f9e /lua/clever_tee/action_facade.lua
parent9013636a57144e1f57c9339e7888d588430aae6a (diff)
Rename plugin to clever-tee
Diffstat (limited to 'lua/clever_tee/action_facade.lua')
-rw-r--r--lua/clever_tee/action_facade.lua134
1 files changed, 134 insertions, 0 deletions
diff --git a/lua/clever_tee/action_facade.lua b/lua/clever_tee/action_facade.lua
new file mode 100644
index 0000000..fe7a035
--- /dev/null
+++ b/lua/clever_tee/action_facade.lua
@@ -0,0 +1,134 @@
+local domain = require("clever_tee.domain")
+local sequence_coordinator = require("clever_tee.sequence_coordinator")
+
+local M = {}
+local ActionFacade = {}
+ActionFacade.__index = ActionFacade
+M.ActionFacade = ActionFacade
+
+local facade_records = setmetatable({}, { __mode = "k" })
+
+local function fail(message, level)
+ error(message, (level or 1) + 1)
+end
+
+function ActionFacade.new(options)
+ if ActionFacade.is(options) then
+ return options
+ end
+ local coordinator
+ if sequence_coordinator.SequenceCoordinator.is(options) then
+ coordinator = options
+ elseif type(options) == "table" then
+ coordinator = options.coordinator
+ or options.sequence_coordinator
+ or sequence_coordinator.new(options)
+ else
+ fail("ActionFacade options must be a table", 2)
+ end
+ if not sequence_coordinator.SequenceCoordinator.is(coordinator) then
+ fail("ActionFacade requires a SequenceCoordinator", 2)
+ end
+
+ local facade = setmetatable({}, ActionFacade)
+ facade_records[facade] = { coordinator = coordinator }
+ return facade
+end
+
+function ActionFacade.is(value)
+ return type(value) == "table" and facade_records[value] ~= nil
+end
+
+function ActionFacade:coordinator()
+ return facade_records[self].coordinator
+end
+
+function ActionFacade:primary(descriptor)
+ local outcome = self:coordinator():primary(descriptor)
+ if not domain.ActionOutcome.is(outcome) then
+ fail("SequenceCoordinator must return an ActionOutcome", 2)
+ end
+ return outcome
+end
+
+function ActionFacade:invoke_descriptor(value)
+ local descriptor = sequence_coordinator.validate_primary_descriptor(value)
+ return self:primary(descriptor)
+end
+
+ActionFacade.invoke_primary = ActionFacade.invoke_descriptor
+ActionFacade.start = ActionFacade.invoke_descriptor
+ActionFacade.FreeForm = ActionFacade.invoke_descriptor
+
+function ActionFacade:start_find_forward()
+ return self:primary("f")
+end
+
+function ActionFacade:start_find_backward()
+ return self:primary("F")
+end
+
+function ActionFacade:start_till_forward()
+ return self:primary("t")
+end
+
+function ActionFacade:start_till_backward()
+ return self:primary("T")
+end
+
+ActionFacade.StartFindForward = ActionFacade.start_find_forward
+ActionFacade.StartFindBackward = ActionFacade.start_find_backward
+ActionFacade.StartTillForward = ActionFacade.start_till_forward
+ActionFacade.StartTillBackward = ActionFacade.start_till_backward
+
+function ActionFacade:reset()
+ local outcome = self:coordinator():reset()
+ if not domain.ActionOutcome.is(outcome) then
+ fail("SequenceCoordinator must return an ActionOutcome", 2)
+ end
+ return outcome
+end
+
+ActionFacade.Reset = ActionFacade.reset
+
+function ActionFacade:diagnostic_full_reset()
+ local outcome = self:coordinator():diagnostic_full_reset()
+ if not domain.ActionOutcome.is(outcome) then
+ fail("SequenceCoordinator must return an ActionOutcome", 2)
+ end
+ return outcome
+end
+
+ActionFacade.DiagnosticFullReset = ActionFacade.diagnostic_full_reset
+
+local function explicit_outcome(facade, method_name)
+ local coordinator = facade:coordinator()
+ local outcome = coordinator[method_name](coordinator)
+ if not domain.ActionOutcome.is(outcome) then
+ fail("SequenceCoordinator must return an ActionOutcome", 3)
+ end
+ return outcome
+end
+
+function ActionFacade:repeat_same_direction()
+ return explicit_outcome(self, "repeat_same_direction")
+end
+
+function ActionFacade:repeat_opposite_direction()
+ return explicit_outcome(self, "repeat_opposite_direction")
+end
+
+ActionFacade.RepeatSameDirection = ActionFacade.repeat_same_direction
+ActionFacade.RepeatOppositeDirection = ActionFacade.repeat_opposite_direction
+
+function M.new(options)
+ return ActionFacade.new(options)
+end
+
+setmetatable(M, {
+ __call = function(_, options)
+ return ActionFacade.new(options)
+ end,
+})
+
+return M