diff options
| -rw-r--r-- | lua/clever_f/feedback_service.lua | 58 | ||||
| -rw-r--r-- | tests/run.lua | 36 |
2 files changed, 94 insertions, 0 deletions
diff --git a/lua/clever_f/feedback_service.lua b/lua/clever_f/feedback_service.lua index b915f6a..a06f6d8 100644 --- a/lua/clever_f/feedback_service.lua +++ b/lua/clever_f/feedback_service.lua @@ -6,6 +6,8 @@ local M = {} local FeedbackService = {} FeedbackService.__index = FeedbackService M.FeedbackService = FeedbackService +local CursorPresentationLease = {} +M.CursorPresentationLease = CursorPresentationLease M.DEFAULT_LABEL_GROUP = "CleverFDefaultLabel" M.Priority = { @@ -20,6 +22,7 @@ local OVERLAY_PRIORITIES = { } local service_records = setmetatable({}, { __mode = "k" }) +local cursor_lease_records = setmetatable({}, { __mode = "k" }) local FEATURE_GROUPS = { "CleverFCursor", @@ -85,6 +88,8 @@ 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.suppress_cursor_presentation) ~= "function" + or type(host.restore_cursor_presentation) ~= "function" then fail("FeedbackService host must provide highlight groups", 3) end @@ -134,6 +139,59 @@ function FeedbackService.is(value) return type(value) == "table" and service_records[value] ~= nil end +local cursor_lease_metatable = { + __index = function(lease, key) + local method = CursorPresentationLease[key] + if method ~= nil then + return method + end + local record = cursor_lease_records[lease] + if key == "identity" then + return record.identity + end + if key == "active" then + return record.active + end + return nil + end, + __newindex = function() + fail("cursor presentation leases are read-only", 2) + end, + __metatable = "clever_f.feedback_service.CursorPresentationLease", +} + +local function new_cursor_presentation_lease(host) + local lease = setmetatable({}, cursor_lease_metatable) + local identity = host:suppress_cursor_presentation() + cursor_lease_records[lease] = { + host = host, + identity = identity, + active = identity ~= nil, + } + return lease +end + +function CursorPresentationLease.is(value) + return type(value) == "table" and cursor_lease_records[value] ~= nil +end + +function CursorPresentationLease:release() + local record = cursor_lease_records[self] + if record == nil then + fail("cursor presentation lease is invalid", 2) + end + if not record.active then + return false + end + record.host:restore_cursor_presentation(record.identity) + record.active = false + return true +end + +function FeedbackService:create_cursor_presentation_lease() + return new_cursor_presentation_lease(service_records[self].host) +end + function FeedbackService:create_cursor_marker(position, window) position = domain.Position.coerce(position) if window == nil then diff --git a/tests/run.lua b/tests/run.lua index 1bd0c64..be2a8b3 100644 --- a/tests/run.lua +++ b/tests/run.lua @@ -4457,6 +4457,42 @@ test("Cursor marker overlays the exact cursor byte position", function() same(0, #state:temporary_overlay_identities()) end) +test("Cursor presentation lease restores every prior value", function() + local prior = { + guicursor = "n-v:block,i:ver25", + terminal_cursor_visible = false, + terminal_cursor_shape = "beam", + hidden = false, + ui = { + blinkon = 375, + blinkoff = 225, + }, + } + local host = MemoryHost.new({ cursor_presentation = prior }) + local feedback = feedback_service.new(host) + + local lease = feedback:create_cursor_presentation_lease() + truthy(feedback_service.CursorPresentationLease.is(lease)) + truthy(lease.active) + truthy(lease.identity ~= nil) + local suppressed = host:cursor_presentation() + truthy(suppressed.hidden) + same(prior.guicursor, suppressed.guicursor) + same(prior.terminal_cursor_visible, suppressed.terminal_cursor_visible) + same(prior.ui.blinkon, suppressed.ui.blinkon) + + truthy(lease:release()) + falsy(lease.active) + local restored = host:cursor_presentation() + same(prior.guicursor, restored.guicursor) + same(prior.terminal_cursor_visible, restored.terminal_cursor_visible) + same(prior.terminal_cursor_shape, restored.terminal_cursor_shape) + same(prior.hidden, restored.hidden) + same(prior.ui.blinkon, restored.ui.blinkon) + same(prior.ui.blinkoff, restored.ui.blinkoff) + falsy(lease:release()) +end) + for _, item in ipairs(tests) do local ok, failure = xpcall(item.body, debug.traceback) if not ok then |
