From 107d14db6ac0731215c3e34eebe1c06b4e8fdb6a Mon Sep 17 00:00:00 2001 From: Jackson Moore Date: Fri, 4 Sep 2026 12:38:27 +0200 Subject: Finalize divergent cursor movement --- lua/clever_f/feedback_service.lua | 13 ++++++++++++- tests/run.lua | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/lua/clever_f/feedback_service.lua b/lua/clever_f/feedback_service.lua index bb78c17..6fb40df 100644 --- a/lua/clever_f/feedback_service.lua +++ b/lua/clever_f/feedback_service.lua @@ -107,6 +107,7 @@ local function require_host(host) or type(host.remove_highlight) ~= "function" or type(host.read_buffer) ~= "function" or type(host.read_cursor) ~= "function" + or type(host.read_window) ~= "function" or type(host.register_events) ~= "function" or type(host.remove_event_registration) ~= "function" or type(host.supports_cursor_presentation) ~= "function" @@ -127,6 +128,7 @@ local function require_transitions(transitions, state) or type(transitions.ClearTargetOverlays) ~= "function" or type(transitions.AddFinalizer) ~= "function" or type(transitions.RemoveFinalizer) ~= "function" + or type(transitions.FullFinalization) ~= "function" then fail("FeedbackService transitions must manage overlay resources", 3) end @@ -482,11 +484,20 @@ function FeedbackService:cursor_moved_decision() } end -function FeedbackService:handle_finalizer_event(name) +function FeedbackService:full_finalize(window) + local record = service_records[self] + window = window or record.host:read_window() + return record.transitions:FullFinalization(window) +end + +function FeedbackService:handle_finalizer_event(name, payload) if name == "CursorMoved" then local decision = self:cursor_moved_decision() if decision.equal then decision.action = M.FinalizerAction.PRESERVE + else + decision.action = M.FinalizerAction.FINALIZE + decision.cleanup = self:full_finalize(payload and payload.window) end return decision end diff --git a/tests/run.lua b/tests/run.lua index baa8f29..2fe0460 100644 --- a/tests/run.lua +++ b/tests/run.lua @@ -6193,6 +6193,40 @@ test("Matching CursorMoved preserves the active sequence", function() same(1, #state.finalizers) end) +test("Different CursorMoved applies full finalization", function() + local state, transitions = fresh_sequence_state() + local host = MemoryHost.new({ + buffer_lines = { "aba" }, + cursor = { line = 1, byte_column = 2 }, + }) + local feedback = feedback_service.new({ + host = host, + transitions = transitions, + }) + local shared_target = target_plan.build(target("a"), matching_policy()) + local movement = motion_plan.build(shared_target, "f") + transitions:BeginAcquisition("n", "f") + transitions:CommitAcquiredTarget("n", target("a")) + transitions:CommitCommandSuccess("n", domain.Position.new(1, 3), true) + transitions:BeginAcquisition("v", "t") + transitions:CommitVisualSuccess("v", domain.Position.new(1, 2)) + feedback:request_persistent({ + context = "n", + anchor = domain.Position.new(1, 1), + target_plan = shared_target, + motion_plan = movement, + window = "window-1", + }) + + host:deliver_event("CursorMoved", {}) + + same(nil, state:get_previous_landing("n")) + same(nil, state:get_previous_landing("v")) + falsy(state.moved_forward) + same(0, #state.target_overlays) + same(0, #state.finalizers) +end) + for _, item in ipairs(tests) do local ok, failure = xpcall(item.body, debug.traceback) if not ok then -- cgit v1.2.3