summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lua/clever_f/sequence_coordinator.lua40
-rw-r--r--tests/run.lua29
2 files changed, 57 insertions, 12 deletions
diff --git a/lua/clever_f/sequence_coordinator.lua b/lua/clever_f/sequence_coordinator.lua
index ee50fbd..cb6bf80 100644
--- a/lua/clever_f/sequence_coordinator.lua
+++ b/lua/clever_f/sequence_coordinator.lua
@@ -424,6 +424,19 @@ function SequenceCoordinator:stored_primary_resolution(
return resolution
end
+function SequenceCoordinator:refresh_primary_feedback(resolution)
+ if type(resolution) ~= "table" or not domain.TargetValue.is(resolution.target) then
+ fail("primary feedback refresh requires a resolved target", 2)
+ end
+ local record = coordinator_records[self]
+ if type(record.feedback.refresh_primary) ~= "function" then
+ fail("FeedbackService must refresh primary feedback", 2)
+ end
+ local window = resolution.timeout and resolution.timeout.window
+ or record.host:read_window()
+ return record.feedback:refresh_primary(resolution.target, window)
+end
+
function SequenceCoordinator:execute_primary_resolution(resolution)
if type(resolution) ~= "table"
or not domain.ModeContext.is(resolution.invocation.context)
@@ -433,20 +446,23 @@ function SequenceCoordinator:execute_primary_resolution(resolution)
end
local record = coordinator_records[self]
record.last_primary_resolution = resolution
+ local outcome
if resolution.skip_destination then
- return domain.ActionOutcome.empty(resolution.invocation.position)
- end
- local view = resolution.text_view or text_topology.from_host(record.host)
- local outcome = record.motion_executor:execute(
- view,
- resolution.invocation.context,
- resolution.motion_plan,
- resolution.invocation.count,
- resolution.first_move
- )
- if not domain.ActionOutcome.is(outcome) then
- fail("MotionExecutor must return an ActionOutcome", 2)
+ outcome = domain.ActionOutcome.empty(resolution.invocation.position)
+ else
+ local view = resolution.text_view or text_topology.from_host(record.host)
+ outcome = record.motion_executor:execute(
+ view,
+ resolution.invocation.context,
+ resolution.motion_plan,
+ resolution.invocation.count,
+ resolution.first_move
+ )
+ if not domain.ActionOutcome.is(outcome) then
+ fail("MotionExecutor must return an ActionOutcome", 2)
+ end
end
+ resolution.highlight_timer = self:refresh_primary_feedback(resolution)
return outcome
end
diff --git a/tests/run.lua b/tests/run.lua
index cf7edb9..d0838e8 100644
--- a/tests/run.lua
+++ b/tests/run.lua
@@ -7605,6 +7605,35 @@ test("Primary coordination executes resolved movement through MotionExecutor", f
)
end)
+test("Fresh and repeated primary actions refresh highlight timeout", function()
+ local state = fresh_sequence_state()
+ local host = MemoryHost.new({
+ buffer_lines = { "aaaa" },
+ cursor = { line = 1, byte_column = 1 },
+ input_packets = { { kind = "text", text = "a" } },
+ configuration = {
+ mark_cursor = false,
+ mark_char = true,
+ highlight_timeout_ms = 25,
+ },
+ emit_movement_events = false,
+ })
+ local coordinator = sequence_coordinator.new({ host = host })
+
+ same(domain.ActionKind.MOVEMENT, coordinator:primary("f").kind)
+ local fresh_timer = state.highlight_timer
+ truthy(fresh_timer ~= nil)
+ same(fresh_timer, coordinator:last_primary_resolution().highlight_timer)
+
+ same(domain.ActionKind.MOVEMENT, coordinator:primary("f").kind)
+ local repeated_timer = state.highlight_timer
+ truthy(repeated_timer ~= nil)
+ falsy(fresh_timer == repeated_timer)
+ falsy(host:timers()[fresh_timer].active)
+ truthy(host:timers()[repeated_timer].active)
+ same(repeated_timer, coordinator:last_primary_resolution().highlight_timer)
+end)
+
for _, item in ipairs(tests) do
local ok, failure = xpcall(item.body, debug.traceback)
if not ok then