summaryrefslogtreecommitdiff
path: root/lua/clever_f/acquisition_service.lua
diff options
context:
space:
mode:
authorJackson Moore <jacksonmoore@tuta.io>2026-09-04 11:57:51 +0200
committerJackson Moore <jacksonmoore@tuta.io>2026-09-04 11:57:51 +0200
commit385be6c13c70bc458b13f000cbc59f07fb963182 (patch)
tree952a1948d203d00aeb3c82b603c9c4fee5cb019a /lua/clever_f/acquisition_service.lua
parentdec674e613fefd0b4cf764f121322dcaa1976031 (diff)
Create enabled acquisition cursor marker
Diffstat (limited to 'lua/clever_f/acquisition_service.lua')
-rw-r--r--lua/clever_f/acquisition_service.lua96
1 files changed, 93 insertions, 3 deletions
diff --git a/lua/clever_f/acquisition_service.lua b/lua/clever_f/acquisition_service.lua
index 5f15fa1..a68e458 100644
--- a/lua/clever_f/acquisition_service.lua
+++ b/lua/clever_f/acquisition_service.lua
@@ -1,4 +1,8 @@
local domain = require("clever_f.domain")
+local feedback_service = require("clever_f.feedback_service")
+local policy = require("clever_f.policy")
+local sequence_state = require("clever_f.sequence_state")
+local state_transitions = require("clever_f.state_transitions")
local M = {}
local AcquisitionRequest = {}
@@ -98,14 +102,16 @@ local scope_metatable = {
__metatable = "clever_f.acquisition_service.TemporaryResourceScope",
}
-function TemporaryResourceScope.new(request)
+function TemporaryResourceScope.new(request, feedback)
if not AcquisitionRequest.is(request) then
fail("temporary resource scope requires an AcquisitionRequest", 2)
end
local scope = setmetatable({}, scope_metatable)
scope_records[scope] = {
request = request,
+ feedback = feedback,
active = true,
+ cursor_marker = nil,
}
return scope
end
@@ -114,6 +120,15 @@ function TemporaryResourceScope.is(value)
return type(value) == "table" and scope_records[value] ~= nil
end
+function TemporaryResourceScope:set_cursor_marker(marker)
+ local record = scope_records[self]
+ if record == nil or not record.active then
+ fail("temporary resource scope must be active", 2)
+ end
+ record.cursor_marker = marker
+ return marker
+end
+
function TemporaryResourceScope:release()
local record = scope_records[self]
if record == nil then
@@ -122,6 +137,42 @@ function TemporaryResourceScope:release()
record.active = false
end
+local function require_policy(service, host)
+ service = service or policy.new(host)
+ if type(service) ~= "table" or type(service.sample_acquisition) ~= "function" then
+ fail("AcquisitionService policy must sample acquisition settings", 3)
+ end
+ return service
+end
+
+local function require_state(state)
+ state = state or sequence_state.get()
+ if not sequence_state.is(state) then
+ fail("AcquisitionService state must be the plugin-global SequenceState", 3)
+ end
+ return state
+end
+
+local function require_transitions(transitions, state)
+ transitions = transitions or state_transitions.new(state)
+ if type(transitions) ~= "table" or type(transitions.BeginAcquisition) ~= "function" then
+ fail("AcquisitionService transitions must begin acquisition", 3)
+ end
+ return transitions
+end
+
+local function require_feedback(feedback, host, policy_service, transitions)
+ feedback = feedback or feedback_service.new({
+ host = host,
+ policy = policy_service,
+ transitions = transitions,
+ })
+ if type(feedback) ~= "table" or type(feedback.create_cursor_marker) ~= "function" then
+ fail("AcquisitionService feedback must create cursor markers", 3)
+ end
+ return feedback
+end
+
local function normalize_options(options, dependencies)
if AcquisitionService.is(options) and dependencies == nil then
return options
@@ -151,9 +202,27 @@ function AcquisitionService.new(options, dependencies)
if type(options.host) ~= "table" then
fail("AcquisitionService host must be a table", 2)
end
+ local state = require_state(options.state)
+ local transitions = require_transitions(
+ options.transitions or options.state_transitions,
+ state
+ )
+ local policy_service = require_policy(
+ options.policy or options.policy_service,
+ options.host
+ )
local service = setmetatable({}, AcquisitionService)
service_records[service] = {
host = options.host,
+ policy = policy_service,
+ transitions = transitions,
+ feedback = require_feedback(
+ options.feedback or options.feedback_service,
+ options.host,
+ policy_service,
+ transitions
+ ),
+ window = options.window or options.current_window,
last_scope = nil,
started_scope_count = 0,
}
@@ -168,10 +237,24 @@ function AcquisitionService:request(descriptor, context, position, count, macro_
return AcquisitionRequest.new(descriptor, context, position, count, macro_state)
end
+local function current_window(record)
+ local window = record.window
+ if type(window) == "function" then
+ window = window()
+ end
+ if window == nil and type(record.host.read_window) == "function" then
+ window = record.host:read_window()
+ end
+ if window == nil then
+ fail("AcquisitionService requires a current window identity", 3)
+ end
+ return window
+end
+
function AcquisitionService:start_temporary_scope(request)
request = AcquisitionRequest.new(request)
local record = service_records[self]
- local scope = TemporaryResourceScope.new(request)
+ local scope = TemporaryResourceScope.new(request, record.feedback)
record.last_scope = scope
record.started_scope_count = record.started_scope_count + 1
return scope
@@ -187,7 +270,14 @@ end
function AcquisitionService:acquire(descriptor, context, position, count, macro_state)
local request = self:request(descriptor, context, position, count, macro_state)
- self:start_temporary_scope(request)
+ local scope = self:start_temporary_scope(request)
+ local record = service_records[self]
+ if record.policy:sample_acquisition().mark_cursor then
+ scope:set_cursor_marker(record.feedback:create_cursor_marker(
+ request.position,
+ current_window(record)
+ ))
+ end
return request
end