diff options
| author | Jackson Moore <jacksonmoore@tuta.io> | 2026-09-04 10:27:53 +0200 |
|---|---|---|
| committer | Jackson Moore <jacksonmoore@tuta.io> | 2026-09-04 10:27:53 +0200 |
| commit | fafe4dfe8ae5ef86ead6667f6d821c32cb5e13ed (patch) | |
| tree | 351a789a76e72088a1799f9861b810db429c1b29 | |
| parent | 1d7cf6fe16c4b1e9a2cfc71b9feb098118cf7ca8 (diff) | |
Stop counts at search boundaries
| -rw-r--r-- | lua/clever_f/destination_engine.lua | 9 | ||||
| -rw-r--r-- | tests/run.lua | 27 |
2 files changed, 34 insertions, 2 deletions
diff --git a/lua/clever_f/destination_engine.lua b/lua/clever_f/destination_engine.lua index 8a07328..e039851 100644 --- a/lua/clever_f/destination_engine.lua +++ b/lua/clever_f/destination_engine.lua @@ -151,6 +151,7 @@ function DestinationEngine:calculate(view, origin, plan, count, first_move) local request = calculation_inputs(view, origin, plan, count, first_move) local current_origin = request.origin local successful_steps = 0 + local boundary_reached = false while successful_steps < request.count.value do local destination = next_destination( @@ -159,13 +160,17 @@ function DestinationEngine:calculate(view, origin, plan, count, first_move) till_equality_allowed(request, successful_steps) ) if destination == nil then - return domain.SearchOutcome.boundary_before_any(request.origin) + boundary_reached = true + break end current_origin = destination successful_steps = successful_steps + 1 end - return domain.SearchOutcome.complete(current_origin, successful_steps) + if not boundary_reached then + return domain.SearchOutcome.complete(current_origin, successful_steps) + end + return domain.SearchOutcome.boundary_before_any(request.origin) end function M.new() diff --git a/tests/run.lua b/tests/run.lua index 209cf28..c6905b5 100644 --- a/tests/run.lua +++ b/tests/run.lua @@ -2744,6 +2744,33 @@ test("Sequential counts reuse each accepted destination as origin", function() ) end) +test("Count calculation stops when its fixed boundary is reached", function() + local visits = 0 + local view = text_topology.new({ "axaxa" }, "utf-8") + local target_match = domain.TargetPlan.new({ + target = target("a"), + kind = domain.TargetPlanKind.LITERAL, + case_mode = domain.CaseMode.SENSITIVE, + matcher = function(character) + visits = visits + 1 + return character == "a" + end, + }) + local plan = motion_plan.build(target_match, "f", "buffer") + local engine = destination_engine.new() + local origin = domain.Position.new(1, 1) + + local complete = engine:calculate(view, origin, plan, 2, true) + same(domain.SearchStatus.COMPLETE, complete.status) + same(domain.Position.new(1, 5), complete.endpoint) + same(4, visits) + + visits = 0 + local incomplete = engine:calculate(view, origin, plan, 3, true) + falsy(incomplete.complete) + same(4, visits) +end) + for _, item in ipairs(tests) do local ok, failure = xpcall(item.body, debug.traceback) if not ok then |
