summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lua/clever_f/action_facade.lua67
-rw-r--r--tests/run.lua24
2 files changed, 91 insertions, 0 deletions
diff --git a/lua/clever_f/action_facade.lua b/lua/clever_f/action_facade.lua
new file mode 100644
index 0000000..5d8da67
--- /dev/null
+++ b/lua/clever_f/action_facade.lua
@@ -0,0 +1,67 @@
+local domain = require("clever_f.domain")
+local sequence_coordinator = require("clever_f.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
+
+ActionFacade.invoke_primary = ActionFacade.primary
+ActionFacade.start = ActionFacade.primary
+
+function M.new(options)
+ return ActionFacade.new(options)
+end
+
+setmetatable(M, {
+ __call = function(_, options)
+ return ActionFacade.new(options)
+ end,
+})
+
+return M
diff --git a/tests/run.lua b/tests/run.lua
index 97a9a6d..7e49e62 100644
--- a/tests/run.lua
+++ b/tests/run.lua
@@ -7,6 +7,7 @@ package.path = table.concat({
}, ";")
local domain = require("clever_f.domain")
+local action_facade = require("clever_f.action_facade")
local acquisition_service = require("clever_f.acquisition_service")
local capabilities = require("clever_f.capabilities")
local destination_engine = require("clever_f.destination_engine")
@@ -7682,6 +7683,29 @@ test("Failed resolved primary search still refreshes highlight timeout", functio
truthy(host:timers()[state.highlight_timer].active)
end)
+test("ActionFacade returns typed primary action outcomes", function()
+ fresh_sequence_state()
+ local host = MemoryHost.new({
+ buffer_lines = { "aba" },
+ input_packets = { { kind = "text", text = "b" } },
+ configuration = {
+ mark_cursor = false,
+ mark_char = false,
+ },
+ emit_movement_events = false,
+ })
+ local facade = action_facade.new({ host = host })
+
+ local outcome = facade:primary("f")
+
+ truthy(domain.ActionOutcome.is(outcome))
+ same(domain.ActionKind.MOVEMENT, outcome.kind)
+ same(domain.Position.new(1, 2), outcome.position)
+ fails(function()
+ facade:primary("x")
+ end, "clever-f: Invalid mapping 'x'")
+end)
+
for _, item in ipairs(tests) do
local ok, failure = xpcall(item.body, debug.traceback)
if not ok then