summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lua/clever_f/repeat_resolver.lua72
-rw-r--r--tests/run.lua17
2 files changed, 89 insertions, 0 deletions
diff --git a/lua/clever_f/repeat_resolver.lua b/lua/clever_f/repeat_resolver.lua
new file mode 100644
index 0000000..1b74420
--- /dev/null
+++ b/lua/clever_f/repeat_resolver.lua
@@ -0,0 +1,72 @@
+local domain = require("clever_f.domain")
+local sequence_state = require("clever_f.sequence_state")
+
+local M = {}
+local RepeatResolver = {}
+M.RepeatResolver = RepeatResolver
+
+local resolver_records = setmetatable({}, { __mode = "k" })
+
+local function fail(message, level)
+ error(message, (level or 1) + 1)
+end
+
+local resolver_metatable = {
+ __index = RepeatResolver,
+ __newindex = function()
+ fail("RepeatResolver values are immutable", 2)
+ end,
+ __tostring = function()
+ return "repeat-resolver"
+ end,
+ __metatable = "clever_f.repeat_resolver.RepeatResolver",
+}
+
+function RepeatResolver.new(options)
+ if RepeatResolver.is(options) then
+ return options
+ end
+ if options == nil then
+ options = {}
+ elseif sequence_state.is(options) then
+ options = { state = options }
+ elseif type(options) ~= "table" then
+ fail("RepeatResolver options must be a table", 2)
+ end
+
+ local state = options.state or sequence_state.get()
+ if not sequence_state.is(state) then
+ fail("RepeatResolver state must be the plugin-global SequenceState", 2)
+ end
+
+ local resolver = setmetatable({}, resolver_metatable)
+ resolver_records[resolver] = {
+ state = state,
+ }
+ return resolver
+end
+
+function RepeatResolver.is(value)
+ return type(value) == "table" and resolver_records[value] ~= nil
+end
+
+function RepeatResolver:previous_landing(context)
+ context = domain.ModeContext.from_full_mode(context)
+ return resolver_records[self].state:get_previous_landing(context)
+end
+
+function M.new(options)
+ return RepeatResolver.new(options)
+end
+
+M.landing = function(context, options)
+ return RepeatResolver.new(options):previous_landing(context)
+end
+
+setmetatable(M, {
+ __call = function(_, options)
+ return RepeatResolver.new(options)
+ end,
+})
+
+return M
diff --git a/tests/run.lua b/tests/run.lua
index 48928e7..3095e6d 100644
--- a/tests/run.lua
+++ b/tests/run.lua
@@ -11,6 +11,7 @@ local capabilities = require("clever_f.capabilities")
local destination_engine = require("clever_f.destination_engine")
local case_policy = require("clever_f.case_policy")
local policy = require("clever_f.policy")
+local repeat_resolver = require("clever_f.repeat_resolver")
local migemo_catalog = require("clever_f.migemo_catalog")
local motion_plan = require("clever_f.motion_plan")
local motion_executor = require("clever_f.motion_executor")
@@ -3786,6 +3787,22 @@ test("Select contexts execute through the command path", function()
same(0, applied_selection)
end)
+test("RepeatResolver reads the normalized contextual landing", function()
+ local _, transitions = fresh_sequence_state()
+ local landing = domain.Position.new(3, 7)
+ transitions:BeginAcquisition("nov", "f")
+ transitions:CommitCommandSuccess("noV", landing, true)
+
+ local resolver = repeat_resolver.new()
+ same(landing, resolver:previous_landing("no" .. string.char(0x16)))
+ same(nil, resolver:previous_landing("n"))
+ truthy(repeat_resolver.RepeatResolver.is(resolver))
+ same(resolver, repeat_resolver.new(resolver))
+ fails(function()
+ resolver.extra = true
+ end, "immutable")
+end)
+
for _, item in ipairs(tests) do
local ok, failure = xpcall(item.body, debug.traceback)
if not ok then