summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lua/clever_f/feedback_service.lua58
-rw-r--r--tests/run.lua36
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