summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJackson Moore <jacksonmoore@tuta.io>2026-09-04 10:27:53 +0200
committerJackson Moore <jacksonmoore@tuta.io>2026-09-04 10:27:53 +0200
commitfafe4dfe8ae5ef86ead6667f6d821c32cb5e13ed (patch)
tree351a789a76e72088a1799f9861b810db429c1b29
parent1d7cf6fe16c4b1e9a2cfc71b9feb098118cf7ca8 (diff)
Stop counts at search boundaries
-rw-r--r--lua/clever_f/destination_engine.lua9
-rw-r--r--tests/run.lua27
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