diff options
| author | Jackson Moore <jacksonmoore@tuta.io> | 2026-09-04 10:57:10 +0200 |
|---|---|---|
| committer | Jackson Moore <jacksonmoore@tuta.io> | 2026-09-04 10:57:10 +0200 |
| commit | b7af716a32e548987e3853f5e91198e53d051d27 (patch) | |
| tree | 659bcd3372f8c015b02c1da9c4f4c32483aaea18 /lua/clever_f/motion_executor.lua | |
| parent | be971036f82c688e0a07fa2e3ff286e414cc5c1d (diff) | |
Execute resolved dot payloads
Diffstat (limited to 'lua/clever_f/motion_executor.lua')
| -rw-r--r-- | lua/clever_f/motion_executor.lua | 96 |
1 files changed, 91 insertions, 5 deletions
diff --git a/lua/clever_f/motion_executor.lua b/lua/clever_f/motion_executor.lua index 062a57f..79cc2ab 100644 --- a/lua/clever_f/motion_executor.lua +++ b/lua/clever_f/motion_executor.lua @@ -52,6 +52,24 @@ function M.create_dot_payload(plan) return domain.DotPayload.new(plan.descriptor, plan.target_plan.target) end +function M.plan_for_dot_payload(plan, payload) + if not domain.ResolvedMotionPlan.is(plan) then + fail("dot replay plan must be a ResolvedMotionPlan", 2) + end + if not domain.DotPayload.is(payload) then + fail("dot replay payload must be a DotPayload", 2) + end + if payload.target ~= plan.target_plan.target then + fail("dot replay payload target must match its resolved target plan", 2) + end + return domain.ResolvedMotionPlan.new({ + target_plan = plan.target_plan, + descriptor = payload.descriptor, + search_scope = plan.search_scope, + endpoint_policy = plan.endpoint_policy, + }) +end + local function copy_options(options) local result = {} for key, value in pairs(options or {}) do @@ -81,8 +99,10 @@ end local function require_host(host) if type(host) ~= "table" or type(host.read_cursor) ~= "function" + or type(host.read_encoding) ~= "function" or type(host.read_pending_operator) ~= "function" or type(host.read_selection) ~= "function" + or type(host.read_text) ~= "function" or type(host.apply_cursor) ~= "function" or type(host.apply_selection) ~= "function" or type(host.set_operator_inclusive) ~= "function" @@ -169,7 +189,14 @@ function MotionExecutor.is(value) return type(value) == "table" and executor_records[value] ~= nil end -local function execution_request(view, context, plan, count, first_move) +local function execution_request( + view, + context, + plan, + count, + first_move, + execution_options +) if not text_topology.TextView.is(view) then fail("motion execution view must be a TextView", 3) end @@ -181,12 +208,28 @@ local function execution_request(view, context, plan, count, first_move) if type(first_move) ~= "boolean" then fail("motion execution first_move must be a Boolean", 3) end + execution_options = execution_options or {} + if type(execution_options) ~= "table" then + fail("motion execution options must be a table", 3) + end + local dot_payload = execution_options.dot_payload + if dot_payload ~= nil and not domain.DotPayload.is(dot_payload) then + fail("motion execution dot_payload must be a DotPayload", 3) + end + local register_dot_repeat = execution_options.register_dot_repeat + if register_dot_repeat == nil then + register_dot_repeat = true + elseif type(register_dot_repeat) ~= "boolean" then + fail("motion execution register_dot_repeat must be a Boolean", 3) + end return { view = view, context = context, plan = plan, count = count, first_move = first_move, + dot_payload = dot_payload, + register_dot_repeat = register_dot_repeat, } end @@ -218,6 +261,19 @@ local function command_action( }) end +local function register_dot_replay(executor, request, payload) + local host = executor_records[executor].host + host:register_dot_repeat(payload, function(replayed_payload, replay_count) + return executor:execute_dot( + text_topology.from_host(host), + request.context, + request.plan, + replayed_payload, + replay_count + ) + end) +end + local function migrate_command_feedback(executor, request, origin, outcome) local record = executor_records[executor] local feedback = record.feedback_service @@ -280,8 +336,10 @@ function MotionExecutor:_execute_command(request) ) local dot_payload if pending_operator ~= nil and pending_operator ~= "" then - dot_payload = M.create_dot_payload(request.plan) - host:register_dot_repeat(dot_payload) + dot_payload = request.dot_payload or M.create_dot_payload(request.plan) + if request.register_dot_repeat then + register_dot_replay(self, request, dot_payload) + end end return command_action( host, @@ -317,14 +375,42 @@ function MotionExecutor:_execute_visual(request) return domain.ActionOutcome.from_search(outcome, request.plan.descriptor) end -function MotionExecutor:execute(view, context, plan, count, first_move) - local request = execution_request(view, context, plan, count, first_move) +function MotionExecutor:execute( + view, + context, + plan, + count, + first_move, + execution_options +) + local request = execution_request( + view, + context, + plan, + count, + first_move, + execution_options + ) if M.execution_path(request.context) == M.ExecutionPath.VISUAL then return self:_execute_visual(request) end return self:_execute_command(request) end +function MotionExecutor:execute_dot(view, context, plan, payload, count) + return self:execute( + view, + context, + M.plan_for_dot_payload(plan, payload), + count, + false, + { + dot_payload = payload, + register_dot_repeat = false, + } + ) +end + function M.new(options, dependencies) return MotionExecutor.new(options, dependencies) end |
