From 614eb6bd3f7059d297b4c940af5de154214091b3 Mon Sep 17 00:00:00 2001 From: Jackson Moore Date: Fri, 4 Sep 2026 13:36:23 +0200 Subject: Acquire pressed primary targets --- lua/clever_f/sequence_coordinator.lua | 41 +++++++++++++++++++++++++++++++++++ tests/run.lua | 34 ++++++++++++++++++++++++++--- 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/lua/clever_f/sequence_coordinator.lua b/lua/clever_f/sequence_coordinator.lua index 334e058..d391eec 100644 --- a/lua/clever_f/sequence_coordinator.lua +++ b/lua/clever_f/sequence_coordinator.lua @@ -1,4 +1,6 @@ +local acquisition_service_factory = require("clever_f.acquisition_service") local domain = require("clever_f.domain") +local feedback_service_factory = require("clever_f.feedback_service") local policy = require("clever_f.policy") local repeat_resolver_factory = require("clever_f.repeat_resolver") local sequence_state = require("clever_f.sequence_state") @@ -59,6 +61,26 @@ function SequenceCoordinator.new(options) if type(resolver) ~= "table" or type(resolver.decide) ~= "function" then fail("SequenceCoordinator repeat resolver must provide decide", 2) end + local feedback = options.feedback + or options.feedback_service + or feedback_service_factory.new({ + host = host, + state = state, + transitions = transitions, + policy = policy_service, + }) + local acquisition = options.acquisition + or options.acquisition_service + or acquisition_service_factory.new({ + host = host, + state = state, + transitions = transitions, + policy = policy_service, + feedback = feedback, + }) + if type(acquisition) ~= "table" or type(acquisition.acquire) ~= "function" then + fail("SequenceCoordinator acquisition service must provide acquire", 2) + end local coordinator = setmetatable({}, SequenceCoordinator) coordinator_records[coordinator] = { @@ -67,6 +89,8 @@ function SequenceCoordinator.new(options) transitions = transitions, policy = policy_service, repeat_resolver = resolver, + feedback = feedback, + acquisition = acquisition, } return coordinator end @@ -166,6 +190,20 @@ function SequenceCoordinator:decide_primary(invocation) ) end +function SequenceCoordinator:acquire_primary(descriptor, invocation) + descriptor = self:validate_primary_descriptor(descriptor) + if type(invocation) ~= "table" then + fail("primary acquisition requires invocation state", 2) + end + return coordinator_records[self].acquisition:acquire( + descriptor, + invocation.context, + invocation.position, + invocation.count, + invocation.macro_state + ) +end + function SequenceCoordinator:primary(value) local descriptor = self:validate_primary_descriptor(value) local invocation = self:read_primary_invocation() @@ -175,6 +213,9 @@ function SequenceCoordinator:primary(value) invocation.fold_state ) invocation.repeat_decision = self:decide_primary(invocation) + if invocation.repeat_decision == repeat_resolver_factory.Decision.ACQUIRE then + return self:acquire_primary(descriptor, invocation) + end return descriptor end diff --git a/tests/run.lua b/tests/run.lua index e72114d..f004a23 100644 --- a/tests/run.lua +++ b/tests/run.lua @@ -7072,7 +7072,10 @@ end) test("Primary coordination accepts only the four motion descriptors", function() local coordinator = sequence_coordinator.new({ host = MemoryHost.new() }) for _, value in ipairs({ "f", "F", "t", "T" }) do - same(domain.Descriptor.from_string(value), coordinator:primary(value)) + same( + domain.Descriptor.from_string(value), + coordinator:validate_primary_descriptor(value) + ) end fails(function() coordinator:primary("x") @@ -7104,11 +7107,12 @@ test("Primary coordination inspects fold policy during preflight", function() closed_fold_levels = 1, }) local coordinator = sequence_coordinator.new({ host = host }) + local invocation = coordinator:read_primary_invocation() - same(domain.Descriptor.FIND_FORWARD, coordinator:primary("f")) + local folds = coordinator:inspect_fold_open_policy(invocation) local operations = host:operations() same("read_fold_state", operations[#operations].operation) - truthy(host:read_fold_state():opens("horizontal")) + truthy(folds:opens("horizontal")) end) test("Primary preflight opens folds for horizontal and all policies", function() @@ -7195,6 +7199,30 @@ test("Primary repetition guard runs after fold preflight", function() same(0, observed_levels) end) +test("Acquiring primary coordination passes the pressed descriptor", function() + local state, transitions = fresh_sequence_state() + local host = MemoryHost.new({ + buffer_lines = { "aba" }, + cursor = { line = 1, byte_column = 1 }, + input_packets = { { kind = "text", text = "a" } }, + configuration = { + mark_cursor = false, + mark_char = false, + }, + }) + local result = sequence_coordinator.new({ + host = host, + state = state, + transitions = transitions, + }):primary("t") + + truthy(acquisition_service.AcquisitionResult.is(result)) + truthy(result.resolved) + same(domain.Descriptor.TILL_FORWARD, result.request.descriptor) + same(domain.Descriptor.TILL_FORWARD, state:get_previous_descriptor("n")) + same("a", result.target.value) +end) + for _, item in ipairs(tests) do local ok, failure = xpcall(item.body, debug.traceback) if not ok then -- cgit v1.2.3