From a3127187d21b6095db9314fd036b38a95b26df4a Mon Sep 17 00:00:00 2001 From: Jackson Moore Date: Fri, 4 Sep 2026 12:49:46 +0200 Subject: Clean eager feedback resources --- lua/clever_f/feedback_service.lua | 9 ++++++++ tests/run.lua | 43 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/lua/clever_f/feedback_service.lua b/lua/clever_f/feedback_service.lua index 3575f27..b79a5e7 100644 --- a/lua/clever_f/feedback_service.lua +++ b/lua/clever_f/feedback_service.lua @@ -151,6 +151,7 @@ local function require_transitions(transitions, state) or type(transitions.AddFinalizer) ~= "function" or type(transitions.RemoveFinalizer) ~= "function" or type(transitions.FullFinalization) ~= "function" + or type(transitions.ClearTargetFeedback) ~= "function" or type(transitions.SetHighlightTimer) ~= "function" or type(transitions.ClearHighlightTimer) ~= "function" then @@ -836,6 +837,14 @@ function FeedbackService:handle_eager_event(name, payload) mark_char = record.policy:sample_markers().mark_char, cleaned = false, } + if decision.mark_char then + local window = payload and payload.window or record.host:read_window() + local cleanup = record.transitions:ClearTargetFeedback(window) + release_highlight_timer(record, cleanup.highlight_timer) + release_target_overlays(record, cleanup.target_overlays) + decision.cleaned = true + decision.cleanup = cleanup + end record.last_eager_decision = decision return decision end diff --git a/tests/run.lua b/tests/run.lua index 4290460..38edcda 100644 --- a/tests/run.lua +++ b/tests/run.lua @@ -6955,6 +6955,49 @@ test("Every eager event samples live character-marker policy", function() end end) +test("Enabled eager events remove overlays and cancel timers", function() + for _, event_name in ipairs(feedback_service.EAGER_EVENTS) do + local state, transitions = fresh_sequence_state() + local host = MemoryHost.new({ + buffer_lines = { "aba" }, + configuration = { + clean_labels_eagerly = true, + mark_char = true, + highlight_timeout_ms = 25, + }, + }) + local feedback = feedback_service.new({ + host = host, + transitions = transitions, + }) + local activation = feedback:activate() + local shared_target = target_plan.build(target("a"), matching_policy()) + local movement = motion_plan.build(shared_target, "f") + local persistent = feedback:request_persistent({ + context = "n", + anchor = domain.Position.new(1, 1), + target_plan = shared_target, + motion_plan = movement, + window = "window-1", + }) + local timer = feedback:start_highlight_timer("window-1") + + host:deliver_event(event_name, { window = "window-1" }) + + local decision = feedback:last_eager_decision() + truthy(decision.cleaned, event_name) + same(timer, decision.cleanup.highlight_timer, event_name) + same(nil, state.highlight_timer, event_name) + same(0, #state.target_overlays, event_name) + same(nil, host:highlights()[persistent.identity], event_name) + falsy(host:timers()[timer].active, event_name) + truthy( + host:event_registrations()[activation.eager_registration].active, + event_name + ) + end +end) + for _, item in ipairs(tests) do local ok, failure = xpcall(item.body, debug.traceback) if not ok then -- cgit v1.2.3