From 1d7cf6fe16c4b1e9a2cfc71b9feb098118cf7ca8 Mon Sep 17 00:00:00 2001 From: Jackson Moore Date: Fri, 4 Sep 2026 10:27:07 +0200 Subject: Advance sequential count origins --- lua/clever_f/destination_engine.lua | 24 ++++++++++++++++-------- tests/run.lua | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/lua/clever_f/destination_engine.lua b/lua/clever_f/destination_engine.lua index 53b26fe..8a07328 100644 --- a/lua/clever_f/destination_engine.lua +++ b/lua/clever_f/destination_engine.lua @@ -149,15 +149,23 @@ end function DestinationEngine:calculate(view, origin, plan, count, first_move) local request = calculation_inputs(view, origin, plan, count, first_move) - local destination = next_destination( - request, - request.origin, - till_equality_allowed(request, 0) - ) - if destination == nil then - return domain.SearchOutcome.boundary_before_any(request.origin) + local current_origin = request.origin + local successful_steps = 0 + + while successful_steps < request.count.value do + local destination = next_destination( + request, + current_origin, + till_equality_allowed(request, successful_steps) + ) + if destination == nil then + return domain.SearchOutcome.boundary_before_any(request.origin) + end + current_origin = destination + successful_steps = successful_steps + 1 end - return domain.SearchOutcome.complete(destination, 1) + + return domain.SearchOutcome.complete(current_origin, successful_steps) end function M.new() diff --git a/tests/run.lua b/tests/run.lua index 6d9289e..209cf28 100644 --- a/tests/run.lua +++ b/tests/run.lua @@ -2712,6 +2712,38 @@ test("Later TILL moves skip an adjacent stationary destination", function() ) end) +test("Sequential counts reuse each accepted destination as origin", function() + local view = text_topology.new({ "abxbxb" }, "utf-8") + local matched_starts = {} + local target_match = domain.TargetPlan.new({ + target = target("b"), + kind = domain.TargetPlanKind.LITERAL, + case_mode = domain.CaseMode.SENSITIVE, + matcher = function(character, position) + if character == "b" then + matched_starts[#matched_starts + 1] = tostring(position) + return true + end + return false + end, + }) + local outcome = destination_engine.calculate( + view, + domain.Position.new(1, 1), + motion_plan.build(target_match, "t"), + 3, + true + ) + + same(domain.SearchStatus.COMPLETE, outcome.status) + same(domain.Position.new(1, 5), outcome.endpoint) + same(3, outcome.successful_steps) + list_same( + { "(1,2)", "(1,2)", "(1,4)", "(1,4)", "(1,6)" }, + matched_starts + ) +end) + for _, item in ipairs(tests) do local ok, failure = xpcall(item.body, debug.traceback) if not ok then -- cgit v1.2.3