summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lua/clever_f/destination_engine.lua24
-rw-r--r--tests/run.lua37
2 files changed, 60 insertions, 1 deletions
diff --git a/lua/clever_f/destination_engine.lua b/lua/clever_f/destination_engine.lua
index 9b528d0..c17dc83 100644
--- a/lua/clever_f/destination_engine.lua
+++ b/lua/clever_f/destination_engine.lua
@@ -60,9 +60,31 @@ local function calculation_inputs(view, origin, plan, count, first_move)
}
end
+local function next_matching_start(request, origin)
+ local candidates = request.view:iter_strict(
+ origin,
+ request.plan.descriptor.direction,
+ request.bounds
+ )
+
+ while true do
+ local position, character = candidates()
+ if position == nil then
+ return nil
+ end
+ if request.plan.target_plan:matches(character, position, request.view) then
+ return position
+ end
+ end
+end
+
function DestinationEngine:calculate(view, origin, plan, count, first_move)
local request = calculation_inputs(view, origin, plan, count, first_move)
- return domain.SearchOutcome.boundary_before_any(request.origin)
+ local target_position = next_matching_start(request, request.origin)
+ if target_position == nil then
+ return domain.SearchOutcome.boundary_before_any(request.origin)
+ end
+ return domain.SearchOutcome.complete(target_position, 1)
end
function M.new()
diff --git a/tests/run.lua b/tests/run.lua
index f684d65..e84c12a 100644
--- a/tests/run.lua
+++ b/tests/run.lua
@@ -2201,6 +2201,43 @@ test("DestinationEngine accepts pure calculation inputs", function()
end, "valid cursor")
end)
+test("DestinationEngine enumerates target starts in motion order", function()
+ local view = text_topology.new({ "abaca" }, "utf-8")
+ local origin = domain.Position.new(1, 3)
+ local visits = {}
+ local target_match = domain.TargetPlan.new({
+ target = target("a"),
+ kind = domain.TargetPlanKind.LITERAL,
+ case_mode = domain.CaseMode.SENSITIVE,
+ matcher = function(character, position)
+ visits[#visits + 1] = character .. ":" .. tostring(position)
+ return character == "a"
+ end,
+ })
+ local engine = destination_engine.new()
+
+ local forward = engine:calculate(
+ view,
+ origin,
+ motion_plan.build(target_match, "f"),
+ 1,
+ true
+ )
+ same(domain.Position.new(1, 5), forward.endpoint)
+ list_same({ "c:(1,4)", "a:(1,5)" }, visits)
+
+ visits = {}
+ local backward = engine:calculate(
+ view,
+ origin,
+ motion_plan.build(target_match, "F"),
+ 1,
+ true
+ )
+ same(domain.Position.new(1, 1), backward.endpoint)
+ list_same({ "b:(1,2)", "a:(1,1)" }, visits)
+end)
+
for _, item in ipairs(tests) do
local ok, failure = xpcall(item.body, debug.traceback)
if not ok then