summaryrefslogtreecommitdiff
path: root/lua/clever_f/destination_engine.lua
diff options
context:
space:
mode:
authorJackson Moore <jacksonmoore@tuta.io>2026-09-04 18:44:32 +0200
committerJackson Moore <jacksonmoore@tuta.io>2026-09-04 18:44:32 +0200
commitc7b14ffb6d14969c9c41864e827f33f8e80fc24e (patch)
treec7c0ac23dc93a4a8b75449d2be4d0e05c4f05f9e /lua/clever_f/destination_engine.lua
parent9013636a57144e1f57c9339e7888d588430aae6a (diff)
Rename plugin to clever-tee
Diffstat (limited to 'lua/clever_f/destination_engine.lua')
-rw-r--r--lua/clever_f/destination_engine.lua201
1 files changed, 0 insertions, 201 deletions
diff --git a/lua/clever_f/destination_engine.lua b/lua/clever_f/destination_engine.lua
deleted file mode 100644
index 53cb654..0000000
--- a/lua/clever_f/destination_engine.lua
+++ /dev/null
@@ -1,201 +0,0 @@
-local domain = require("clever_f.domain")
-local text_topology = require("clever_f.text_topology")
-
-local M = {}
-local DestinationEngine = {}
-M.DestinationEngine = DestinationEngine
-
-local engines = setmetatable({}, { __mode = "k" })
-
-local function fail(message, level)
- error(message, (level or 1) + 1)
-end
-
-local engine_metatable = {
- __index = DestinationEngine,
- __newindex = function()
- fail("DestinationEngine values are immutable", 2)
- end,
- __tostring = function()
- return "destination-engine"
- end,
- __metatable = "clever_f.destination_engine.DestinationEngine",
-}
-
-function DestinationEngine.new()
- local engine = setmetatable({}, engine_metatable)
- engines[engine] = true
- return engine
-end
-
-function DestinationEngine.is(value)
- return type(value) == "table" and engines[value] == true
-end
-
-local function calculation_inputs(view, origin, plan, count, first_move)
- if not text_topology.TextView.is(view) then
- fail("destination calculation view must be a TextView", 3)
- end
-
- origin = domain.Position.coerce(origin)
- if not view:is_valid_cursor_position(origin) then
- fail("destination calculation origin must be a valid cursor position", 3)
- end
- if not domain.ResolvedMotionPlan.is(plan) then
- fail("destination calculation plan must be a ResolvedMotionPlan", 3)
- end
- count = domain.Count.new(count)
- if type(first_move) ~= "boolean" then
- fail("destination calculation first_move must be a Boolean", 3)
- end
-
- local bounds = view:match_start_bounds(plan.search_scope, origin)
- return {
- view = view,
- origin = origin,
- plan = plan,
- count = count,
- first_move = first_move,
- bounds = bounds,
- }
-end
-
-local function candidate_starts(request, origin)
- return request.view:iter_strict(
- origin,
- request.plan.descriptor.direction,
- request.bounds
- )
-end
-
-local function regular_destination(request, target_position)
- local descriptor = request.plan.descriptor
- if descriptor.family == domain.Family.FIND then
- return target_position
- end
- if descriptor.direction == domain.Direction.FORWARD then
- return request.view:predecessor(target_position)
- end
- return request.view:successor(target_position)
-end
-
-local function target_destination(request, target_position)
- local descriptor = request.plan.descriptor
- if request.plan.endpoint_policy == domain.EndpointPolicy.VISUAL_EXCLUSIVE
- and descriptor.direction == domain.Direction.FORWARD
- then
- if descriptor.family == domain.Family.FIND then
- return request.view:successor(target_position)
- end
- return target_position
- end
- return regular_destination(request, target_position)
-end
-
-local function strict_destination(descriptor, destination, origin)
- local comparison = domain.Position.compare(destination, origin)
- if descriptor.direction == domain.Direction.FORWARD then
- return comparison > 0
- end
- return comparison < 0
-end
-
-local function acceptable_destination(
- request,
- destination,
- origin,
- allow_till_equality
-)
- local descriptor = request.plan.descriptor
- if strict_destination(descriptor, destination, origin) then
- return true
- end
- return descriptor.family == domain.Family.TILL
- and allow_till_equality
- and domain.Position.equal(destination, origin)
-end
-
-local function next_destination(request, origin, allow_till_equality)
- local candidates = candidate_starts(request, origin)
-
- while true do
- local target_position, character = candidates()
- if target_position == nil then
- return nil
- end
- if request.plan.target_plan:matches(
- character,
- target_position,
- request.view
- ) then
- local destination = target_destination(request, target_position)
- if destination ~= nil
- and acceptable_destination(
- request,
- destination,
- origin,
- allow_till_equality
- )
- then
- return destination
- end
- end
- end
-end
-
-local function till_equality_allowed(request, successful_steps)
- return request.first_move and successful_steps == 0
-end
-
-local function boundary_outcome(request, endpoint, successful_steps)
- if successful_steps > 0 then
- return domain.SearchOutcome.boundary_after_partial(
- endpoint,
- successful_steps
- )
- end
- return domain.SearchOutcome.boundary_before_any(request.origin)
-end
-
-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
-
- while successful_steps < request.count.value do
- local destination = next_destination(
- request,
- current_origin,
- till_equality_allowed(request, successful_steps)
- )
- if destination == nil then
- break
- end
- current_origin = destination
- successful_steps = successful_steps + 1
- end
-
- if successful_steps == request.count.value then
- return domain.SearchOutcome.complete(current_origin, successful_steps)
- end
- return boundary_outcome(request, current_origin, successful_steps)
-end
-
-function M.new()
- return DestinationEngine.new()
-end
-
-function M.calculate(view, origin, plan, count, first_move)
- return DestinationEngine.new():calculate(view, origin, plan, count, first_move)
-end
-
-M.resolve = M.calculate
-M.search = M.calculate
-
-setmetatable(M, {
- __call = function()
- return DestinationEngine.new()
- end,
-})
-
-return M