summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJackson Moore <jacksonmoore@tuta.io>2026-09-04 12:05:52 +0200
committerJackson Moore <jacksonmoore@tuta.io>2026-09-04 12:05:52 +0200
commit7d08a49b62eed6c4afcd19897670fb10930faa46 (patch)
treef258ec84a2093df71a226fba34a43d47d52beaea
parentb5a2d9934368ff15fb195abc1ef69b45226c5b06 (diff)
Report missing previous input
-rw-r--r--lua/clever_f/acquisition_service.lua15
-rw-r--r--tests/run.lua28
2 files changed, 43 insertions, 0 deletions
diff --git a/lua/clever_f/acquisition_service.lua b/lua/clever_f/acquisition_service.lua
index a81c501..52b3949 100644
--- a/lua/clever_f/acquisition_service.lua
+++ b/lua/clever_f/acquisition_service.lua
@@ -20,6 +20,7 @@ M.RepeatedDirection = {
SAME = "same",
}
M.PROMPT = "clever-f: "
+M.PREVIOUS_INPUT_NOT_FOUND = "Previous input not found."
local request_records = setmetatable({}, { __mode = "k" })
local result_records = setmetatable({}, { __mode = "k" })
@@ -142,6 +143,7 @@ function AcquisitionResult.new(request, options)
previous_input_trigger = options.previous_input_trigger,
previous_target_source = options.previous_target_source,
cached_target = options.cached_target,
+ missing_previous_input = options.missing_previous_input == true,
completed = outcome ~= nil or target ~= nil,
}
return result
@@ -187,6 +189,7 @@ function TemporaryResourceScope.new(request, feedback)
previous_input_trigger = nil,
previous_target_source = nil,
cached_target = nil,
+ missing_previous_input = false,
outcome = nil,
}
return scope
@@ -238,6 +241,13 @@ function TemporaryResourceScope:set_cached_target(context, target)
return set_scope_resource(self, "cached_target", target)
end
+function TemporaryResourceScope:set_missing_previous_input(missing)
+ if type(missing) ~= "boolean" then
+ fail("missing previous-input state must be a Boolean", 2)
+ end
+ return set_scope_resource(self, "missing_previous_input", missing)
+end
+
function TemporaryResourceScope:set_outcome(outcome)
if not domain.ActionOutcome.is(outcome) then
fail("temporary resource scope outcome must be an ActionOutcome", 2)
@@ -639,6 +649,10 @@ function AcquisitionService:acquire(descriptor, context, position, count, macro_
scope:set_cached_target(source, cached_target)
if cached_target ~= nil then
target = cached_target
+ else
+ target = nil
+ scope:set_missing_previous_input(true)
+ record.host:emit_diagnostic("error", M.PREVIOUS_INPUT_NOT_FOUND)
end
end
scope:set_resolved_target(target)
@@ -647,6 +661,7 @@ function AcquisitionService:acquire(descriptor, context, position, count, macro_
previous_input_trigger = trigger,
previous_target_source = scope.previous_target_source,
cached_target = scope.cached_target,
+ missing_previous_input = scope.missing_previous_input,
})
end
diff --git a/tests/run.lua b/tests/run.lua
index c968d87..69f5087 100644
--- a/tests/run.lua
+++ b/tests/run.lua
@@ -5257,6 +5257,34 @@ test("Acquisition compares first codes with previous-input triggers", function()
same(nil, acquisition_service.match_previous_input_trigger(122, { "xy" }))
end)
+test("Missing previous input preserves cursor and emits exact diagnostic", function()
+ fresh_sequence_state()
+ local origin = domain.Position.new(1, 2)
+ local host = MemoryHost.new({
+ buffer_lines = { "abc" },
+ cursor = origin,
+ configuration = {
+ mark_cursor = false,
+ hide_cursor_on_cmdline = false,
+ repeat_last_char_inputs = { "\r" },
+ },
+ input_packets = { { kind = "text", text = "\r" } },
+ })
+ local service = acquisition_service.new(host)
+
+ local result = service:acquire("f", "n", origin, nil, nil)
+ truthy(result.missing_previous_input)
+ same(nil, result.target)
+ same(origin, host:read_cursor())
+ same(1, #host:diagnostics())
+ same("error", host:diagnostics()[1].level)
+ same("Previous input not found.", host:diagnostics()[1].text)
+ same(
+ acquisition_service.PREVIOUS_INPUT_NOT_FOUND,
+ host:diagnostics()[1].text
+ )
+end)
+
for _, item in ipairs(tests) do
local ok, failure = xpcall(item.body, debug.traceback)
if not ok then