From 07cb5088325b7272f8718bfaee9e85515ae6a81e Mon Sep 17 00:00:00 2001 From: Jackson Moore Date: Fri, 4 Sep 2026 11:39:56 +0200 Subject: Gate command-line cursor suppression --- lua/clever_f/capabilities.lua | 1 + lua/clever_f/feedback_service.lua | 17 ++++++++++--- lua/clever_f/testing/memory_host.lua | 7 ++++++ tests/run.lua | 47 ++++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 4 deletions(-) diff --git a/lua/clever_f/capabilities.lua b/lua/clever_f/capabilities.lua index 3e770bd..7478fb2 100644 --- a/lua/clever_f/capabilities.lua +++ b/lua/clever_f/capabilities.lua @@ -28,6 +28,7 @@ M.effect_methods = { "remove_highlight", }, cursor_presentation = { + "supports_cursor_presentation", "suppress_cursor_presentation", "restore_cursor_presentation", }, diff --git a/lua/clever_f/feedback_service.lua b/lua/clever_f/feedback_service.lua index a06f6d8..e8c387d 100644 --- a/lua/clever_f/feedback_service.lua +++ b/lua/clever_f/feedback_service.lua @@ -88,6 +88,7 @@ local function require_host(host) or type(host.define_highlight_group) ~= "function" or type(host.create_highlight) ~= "function" or type(host.remove_highlight) ~= "function" + or type(host.supports_cursor_presentation) ~= "function" or type(host.suppress_cursor_presentation) ~= "function" or type(host.restore_cursor_presentation) ~= "function" then @@ -111,6 +112,7 @@ local function require_policy(service, host) service = service or policy.new(host) if type(service) ~= "table" or type(service.evaluate_highlight_links) ~= "function" + or type(service.sample_acquisition) ~= "function" then fail("FeedbackService policy must evaluate highlight links", 3) end @@ -160,9 +162,9 @@ local cursor_lease_metatable = { __metatable = "clever_f.feedback_service.CursorPresentationLease", } -local function new_cursor_presentation_lease(host) +local function new_cursor_presentation_lease(host, suppress) local lease = setmetatable({}, cursor_lease_metatable) - local identity = host:suppress_cursor_presentation() + local identity = suppress and host:suppress_cursor_presentation() or nil cursor_lease_records[lease] = { host = host, identity = identity, @@ -188,8 +190,15 @@ function CursorPresentationLease:release() return true end -function FeedbackService:create_cursor_presentation_lease() - return new_cursor_presentation_lease(service_records[self].host) +function FeedbackService:create_cursor_presentation_lease(enabled) + local record = service_records[self] + if enabled == nil then + enabled = record.policy:sample_acquisition().hide_cursor_on_cmdline + elseif type(enabled) ~= "boolean" then + fail("cursor presentation policy must be a Boolean", 2) + end + local supported = enabled and record.host:supports_cursor_presentation() + return new_cursor_presentation_lease(record.host, supported == true) end function FeedbackService:create_cursor_marker(position, window) diff --git a/lua/clever_f/testing/memory_host.lua b/lua/clever_f/testing/memory_host.lua index 0f8fc2d..929b357 100644 --- a/lua/clever_f/testing/memory_host.lua +++ b/lua/clever_f/testing/memory_host.lua @@ -727,6 +727,13 @@ function MemoryHost:highlights() return copy(self._highlights) end +function MemoryHost:supports_cursor_presentation() + self:_record("supports_cursor_presentation", { + supported = self._cursor_presentation_support, + }) + return self._cursor_presentation_support +end + function MemoryHost:suppress_cursor_presentation() if not self._cursor_presentation_support then self:_record("suppress_cursor_presentation", { supported = false }) diff --git a/tests/run.lua b/tests/run.lua index be2a8b3..7ca4e3c 100644 --- a/tests/run.lua +++ b/tests/run.lua @@ -4493,6 +4493,53 @@ test("Cursor presentation lease restores every prior value", function() falsy(lease:release()) end) +test("Cursor suppression requires policy and runtime support", function() + local policy_disabled = MemoryHost.new({ + configuration = { hide_cursor_on_cmdline = false }, + cursor_presentation_support = true, + }) + local disabled_lease = feedback_service.new(policy_disabled) + :create_cursor_presentation_lease() + falsy(disabled_lease.active) + falsy(policy_disabled:cursor_presentation().hidden) + + local runtime_disabled = MemoryHost.new({ + configuration = { hide_cursor_on_cmdline = true }, + cursor_presentation_support = false, + }) + local unsupported_lease = feedback_service.new(runtime_disabled) + :create_cursor_presentation_lease() + falsy(unsupported_lease.active) + falsy(runtime_disabled:cursor_presentation().hidden) + + local enabled = MemoryHost.new({ + configuration = { hide_cursor_on_cmdline = true }, + cursor_presentation_support = true, + }) + local enabled_lease = feedback_service.new(enabled) + :create_cursor_presentation_lease() + truthy(enabled_lease.active) + truthy(enabled:cursor_presentation().hidden) + truthy(enabled_lease:release()) + + local function operation_count(host, name) + local count = 0 + for _, operation in ipairs(host:operations()) do + if operation.operation == name then + count = count + 1 + end + end + return count + end + + same(0, operation_count(policy_disabled, "supports_cursor_presentation")) + same(0, operation_count(policy_disabled, "suppress_cursor_presentation")) + same(1, operation_count(runtime_disabled, "supports_cursor_presentation")) + same(0, operation_count(runtime_disabled, "suppress_cursor_presentation")) + same(1, operation_count(enabled, "supports_cursor_presentation")) + same(1, operation_count(enabled, "suppress_cursor_presentation")) +end) + for _, item in ipairs(tests) do local ok, failure = xpcall(item.body, debug.traceback) if not ok then -- cgit v1.2.3