diff options
Diffstat (limited to 'lua/clever_f')
| -rw-r--r-- | lua/clever_f/acquisition_service.lua | 96 | ||||
| -rw-r--r-- | lua/clever_f/testing/memory_host.lua | 13 |
2 files changed, 106 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 diff --git a/lua/clever_f/testing/memory_host.lua b/lua/clever_f/testing/memory_host.lua index 929b357..b815c2f 100644 --- a/lua/clever_f/testing/memory_host.lua +++ b/lua/clever_f/testing/memory_host.lua @@ -139,6 +139,7 @@ function MemoryHost.new(options) local self = setmetatable({ _text = text_snapshot(options.text or options.buffer_lines or { "" }), _cursor = domain.Position.coerce(options.cursor or { line = 1, byte_column = 1 }), + _window = options.window or "window-1", _mode = raw_mode, _selection = selection_value(options.selection), _count = domain.Count.new(options.count), @@ -228,6 +229,11 @@ function MemoryHost:read_cursor() return self._cursor end +function MemoryHost:read_window() + self:_record("read_window", { window = self._window }) + return self._window +end + function MemoryHost:read_mode() self:_record("read_mode", { mode = self._mode }) return self._mode @@ -316,6 +322,13 @@ function MemoryHost:set_cursor(position) self._cursor = domain.Position.coerce(position) end +function MemoryHost:set_window(window) + if window == nil then + error("window identity must be present", 2) + end + self._window = window +end + function MemoryHost:set_mode(full_mode) if domain.ModeContext.is(full_mode) then full_mode = full_mode.full_mode |
