summaryrefslogtreecommitdiff
path: root/lua/clever_f/acquisition_service.lua
diff options
context:
space:
mode:
authorJackson Moore <jacksonmoore@tuta.io>2026-09-04 11:55:38 +0200
committerJackson Moore <jacksonmoore@tuta.io>2026-09-04 11:55:38 +0200
commit2cb3cc48f1d6bd3da19b1b618f9be4aeef0f5176 (patch)
treeaf38e7a89cc1f3c2df768f73a2f7281c464c17c4 /lua/clever_f/acquisition_service.lua
parent08bdcf5239e4d69cb08933a0b079ca18e151c3ae (diff)
Accept acquisition request inputs
Diffstat (limited to 'lua/clever_f/acquisition_service.lua')
-rw-r--r--lua/clever_f/acquisition_service.lua137
1 files changed, 137 insertions, 0 deletions
diff --git a/lua/clever_f/acquisition_service.lua b/lua/clever_f/acquisition_service.lua
new file mode 100644
index 0000000..cdbcd81
--- /dev/null
+++ b/lua/clever_f/acquisition_service.lua
@@ -0,0 +1,137 @@
+local domain = require("clever_f.domain")
+
+local M = {}
+local AcquisitionRequest = {}
+local AcquisitionService = {}
+AcquisitionService.__index = AcquisitionService
+M.AcquisitionRequest = AcquisitionRequest
+M.AcquisitionService = AcquisitionService
+
+local request_records = setmetatable({}, { __mode = "k" })
+local service_records = setmetatable({}, { __mode = "k" })
+
+local function fail(message, level)
+ error(message, (level or 1) + 1)
+end
+
+local function normalize_macro_state(value)
+ if type(value) == "table" and not domain.MacroState.is(value) then
+ value = value.register
+ end
+ return domain.MacroState.new(value)
+end
+
+local request_metatable = {
+ __index = function(request, key)
+ local method = AcquisitionRequest[key]
+ if method ~= nil then
+ return method
+ end
+ return request_records[request][key]
+ end,
+ __newindex = function()
+ fail("AcquisitionRequest values are immutable", 2)
+ end,
+ __tostring = function(request)
+ return "acquisition-request:" .. request_records[request].descriptor.value
+ end,
+ __metatable = "clever_f.acquisition_service.AcquisitionRequest",
+}
+
+function AcquisitionRequest.new(descriptor, context, position, count, macro_state)
+ if AcquisitionRequest.is(descriptor) then
+ return descriptor
+ end
+ if type(descriptor) == "table" and not domain.Descriptor.is(descriptor) then
+ local options = descriptor
+ descriptor = options.descriptor
+ context = options.context
+ position = options.position or options.origin
+ count = options.count
+ macro_state = options.macro_state
+ end
+
+ local request = setmetatable({}, request_metatable)
+ request_records[request] = {
+ descriptor = domain.Descriptor.from_string(descriptor),
+ context = domain.ModeContext.from_full_mode(context),
+ position = domain.Position.coerce(position),
+ count = domain.Count.new(count),
+ macro_state = normalize_macro_state(macro_state),
+ }
+ return request
+end
+
+function AcquisitionRequest.is(value)
+ return type(value) == "table" and request_records[value] ~= nil
+end
+
+function AcquisitionRequest:to_table()
+ return {
+ descriptor = self.descriptor.value,
+ context = self.context.key,
+ position = self.position:to_table(),
+ count = self.count.value,
+ macro_register = self.macro_state.register,
+ }
+end
+
+local function normalize_options(options, dependencies)
+ if AcquisitionService.is(options) and dependencies == nil then
+ return options
+ end
+ if type(options) ~= "table" then
+ fail("AcquisitionService options must be a table", 3)
+ end
+ if options.host ~= nil then
+ if dependencies ~= nil then
+ fail("AcquisitionService dependencies must be part of its options", 3)
+ end
+ return options
+ end
+ local result = {}
+ for key, value in pairs(dependencies or {}) do
+ result[key] = value
+ end
+ result.host = options
+ return result
+end
+
+function AcquisitionService.new(options, dependencies)
+ options = normalize_options(options, dependencies)
+ if AcquisitionService.is(options) then
+ return options
+ end
+ if type(options.host) ~= "table" then
+ fail("AcquisitionService host must be a table", 2)
+ end
+ local service = setmetatable({}, AcquisitionService)
+ service_records[service] = {
+ host = options.host,
+ }
+ return service
+end
+
+function AcquisitionService.is(value)
+ return type(value) == "table" and service_records[value] ~= nil
+end
+
+function AcquisitionService:request(descriptor, context, position, count, macro_state)
+ return AcquisitionRequest.new(descriptor, context, position, count, macro_state)
+end
+
+function AcquisitionService:acquire(descriptor, context, position, count, macro_state)
+ return self:request(descriptor, context, position, count, macro_state)
+end
+
+function M.new(options, dependencies)
+ return AcquisitionService.new(options, dependencies)
+end
+
+setmetatable(M, {
+ __call = function(_, options, dependencies)
+ return AcquisitionService.new(options, dependencies)
+ end,
+})
+
+return M