summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJackson Moore <jacksonmoore@tuta.io>2026-09-04 10:27:07 +0200
committerJackson Moore <jacksonmoore@tuta.io>2026-09-04 10:27:07 +0200
commit1d7cf6fe16c4b1e9a2cfc71b9feb098118cf7ca8 (patch)
treeb38d4322e8c037f763d0811784f37c28a19b651c
parenta9ece4278ad0feb098db9027be1419121d61aca9 (diff)
Advance sequential count origins
-rw-r--r--lua/clever_f/destination_engine.lua24
-rw-r--r--tests/run.lua32
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