diff options
| author | Jackson Moore <jacksonmoore@tuta.io> | 2026-09-04 12:11:58 +0200 |
|---|---|---|
| committer | Jackson Moore <jacksonmoore@tuta.io> | 2026-09-04 12:11:58 +0200 |
| commit | ba6df9a71fcbcb3520e162284fe72ff60ff34c2a (patch) | |
| tree | 36e2df2ff5cb288e86b943119438f9a3bc5eb9dc | |
| parent | 0b7341d3363ce56995f8a28c03b8444c1f7718ff (diff) | |
Redraw completed interactive prompt
| -rw-r--r-- | lua/clever_f/acquisition_service.lua | 35 | ||||
| -rw-r--r-- | tests/run.lua | 55 |
2 files changed, 86 insertions, 4 deletions
diff --git a/lua/clever_f/acquisition_service.lua b/lua/clever_f/acquisition_service.lua index e86bd73..3708ca4 100644 --- a/lua/clever_f/acquisition_service.lua +++ b/lua/clever_f/acquisition_service.lua @@ -191,7 +191,7 @@ local scope_metatable = { __metatable = "clever_f.acquisition_service.TemporaryResourceScope", } -function TemporaryResourceScope.new(request, feedback) +function TemporaryResourceScope.new(request, feedback, host) if not AcquisitionRequest.is(request) then fail("temporary resource scope requires an AcquisitionRequest", 2) end @@ -199,7 +199,12 @@ function TemporaryResourceScope.new(request, feedback) scope_records[scope] = { request = request, feedback = feedback, + host = host, active = true, + interactive = not request.macro_state.executing, + prompt_shown = false, + input_completed = false, + acquisition_completed = false, cursor_marker = nil, direct_marker = nil, cursor_presentation_lease = nil, @@ -247,6 +252,18 @@ function TemporaryResourceScope:set_input_packet(packet) return set_scope_resource(self, "input_packet", packet) end +function TemporaryResourceScope:mark_prompt_shown() + return set_scope_resource(self, "prompt_shown", true) +end + +function TemporaryResourceScope:mark_input_completed() + return set_scope_resource(self, "input_completed", true) +end + +function TemporaryResourceScope:mark_acquisition_completed() + return set_scope_resource(self, "acquisition_completed", true) +end + function TemporaryResourceScope:set_acquired_target(target) return set_scope_resource(self, "acquired_target", target) end @@ -304,6 +321,13 @@ function TemporaryResourceScope:release() if record == nil then fail("temporary resource scope is invalid", 2) end + if record.interactive + and record.prompt_shown + and record.input_completed + and record.acquisition_completed + then + record.host:redraw("full") + end record.active = false end @@ -466,7 +490,7 @@ end function AcquisitionService:start_temporary_scope(request) request = AcquisitionRequest.new(request) local record = service_records[self] - local scope = TemporaryResourceScope.new(request, record.feedback) + local scope = TemporaryResourceScope.new(request, record.feedback, record.host) record.last_scope = scope record.started_scope_count = record.started_scope_count + 1 return scope @@ -702,9 +726,11 @@ function AcquisitionService:acquire(descriptor, context, position, count, macro_ end if acquisition.show_prompt and not request.macro_state.executing then record.host:show_prompt(M.PROMPT) + scope:mark_prompt_shown() end record.transitions:BeginAcquisition(request.context, request.descriptor) local packet = scope:set_input_packet(read_input_packet(record.host)) + scope:mark_input_completed() if M.is_escape(packet) then local outcome = scope:set_outcome(domain.ActionOutcome.escape(request.position)) scope:release() @@ -789,7 +815,7 @@ function AcquisitionService:acquire(descriptor, context, position, count, macro_ window = window, }) end - return AcquisitionResult.new(request, { + local result = AcquisitionResult.new(request, { target = target, target_plan = target_plan, motion_plan = motion_plan, @@ -800,6 +826,9 @@ function AcquisitionService:acquire(descriptor, context, position, count, macro_ cached_target = scope.cached_target, missing_previous_input = scope.missing_previous_input, }) + scope:mark_acquisition_completed() + scope:release() + return result end function M.new(options, dependencies) diff --git a/tests/run.lua b/tests/run.lua index 78789c6..42ebe89 100644 --- a/tests/run.lua +++ b/tests/run.lua @@ -4914,7 +4914,7 @@ test("Acquisition starts one temporary resource scope", function() truthy(acquisition_service.AcquisitionRequest.is(result.request)) truthy(acquisition_service.TemporaryResourceScope.is(scope)) same(result.request, scope.request) - truthy(scope.active) + falsy(scope.active) same(1, service:started_scope_count()) end) @@ -5057,6 +5057,7 @@ test("Acquisition emits the exact enabled prompt", function() ) same("clever-f: ", acquisition_service.PROMPT) list_same({ "clever-f: " }, host:prompts()) + list_same({ "full" }, host:redraws()) fresh_sequence_state() local macro_host = MemoryHost.new({ @@ -5459,6 +5460,58 @@ test("Acquisition requests eligible persistent target feedback", function() falsy(feedback_service.persistent_context_eligible("no")) end) +test("Completed interactive prompt input requests a full redraw", function() + fresh_sequence_state() + local host = MemoryHost.new({ + buffer_lines = { "ab" }, + configuration = { + mark_cursor = false, + mark_direct = false, + mark_char = false, + show_prompt = true, + }, + input_packets = { { kind = "text", text = "b" } }, + }) + acquisition_service.new(host):acquire( + "f", + "n", + domain.Position.new(1, 1), + nil, + nil + ) + list_same({ "full" }, host:redraws()) + + local input_index + local redraw_index + for index, operation in ipairs(host:operations()) do + if operation.operation == "read_input" then + input_index = index + elseif operation.operation == "redraw" and operation.kind == "full" then + redraw_index = index + end + end + truthy(redraw_index > input_index) + + fresh_sequence_state() + local escape_host = MemoryHost.new({ + configuration = { + mark_cursor = false, + show_prompt = true, + }, + input_packets = { + { kind = "special_key", name = "Escape", bytes = { 27 } }, + }, + }) + acquisition_service.new(escape_host):acquire( + "f", + "n", + domain.Position.new(1, 1), + nil, + nil + ) + same(0, #escape_host:redraws()) +end) + for _, item in ipairs(tests) do local ok, failure = xpcall(item.body, debug.traceback) if not ok then |
