summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lua/clever_f/feedback_service.lua51
-rw-r--r--tests/run.lua25
2 files changed, 76 insertions, 0 deletions
diff --git a/lua/clever_f/feedback_service.lua b/lua/clever_f/feedback_service.lua
index 9d7e085..b915f6a 100644
--- a/lua/clever_f/feedback_service.lua
+++ b/lua/clever_f/feedback_service.lua
@@ -1,4 +1,6 @@
+local domain = require("clever_f.domain")
local policy = require("clever_f.policy")
+local state_transitions = require("clever_f.state_transitions")
local M = {}
local FeedbackService = {}
@@ -81,12 +83,25 @@ local function require_host(host)
if type(host) ~= "table"
or type(host.read_highlight_group) ~= "function"
or type(host.define_highlight_group) ~= "function"
+ or type(host.create_highlight) ~= "function"
+ or type(host.remove_highlight) ~= "function"
then
fail("FeedbackService host must provide highlight groups", 3)
end
return host
end
+local function require_transitions(transitions, state)
+ transitions = transitions or state_transitions.new(state)
+ if type(transitions) ~= "table"
+ or type(transitions.AddTemporaryOverlay) ~= "function"
+ or type(transitions.RemoveTemporaryOverlay) ~= "function"
+ then
+ fail("FeedbackService transitions must manage temporary overlays", 3)
+ end
+ return transitions
+end
+
local function require_policy(service, host)
service = service or policy.new(host)
if type(service) ~= "table"
@@ -107,6 +122,10 @@ function FeedbackService.new(options)
service_records[service] = {
host = host,
policy = require_policy(options.policy or options.policy_service, host),
+ transitions = require_transitions(
+ options.transitions or options.state_transitions,
+ options.state
+ ),
}
return service
end
@@ -115,6 +134,38 @@ function FeedbackService.is(value)
return type(value) == "table" and service_records[value] ~= nil
end
+function FeedbackService:create_cursor_marker(position, window)
+ position = domain.Position.coerce(position)
+ if window == nil then
+ fail("cursor marker window must identify its host window", 2)
+ end
+
+ local record = service_records[self]
+ local identity = record.host:create_highlight({
+ group = "CleverFCursor",
+ window = window,
+ position = position,
+ priority = M.overlay_priority("CleverFCursor"),
+ })
+ record.transitions:AddTemporaryOverlay(identity, window, "CleverFCursor")
+ return {
+ identity = identity,
+ window = window,
+ group = "CleverFCursor",
+ position = position,
+ }
+end
+
+function FeedbackService:remove_temporary_overlay(resource)
+ if type(resource) ~= "table" or resource.identity == nil then
+ fail("temporary overlay resource must identify its highlight", 2)
+ end
+ local record = service_records[self]
+ local removed = record.host:remove_highlight(resource.identity)
+ record.transitions:RemoveTemporaryOverlay(resource.identity, resource.window)
+ return removed
+end
+
function FeedbackService:evaluate_feature_links()
local record = service_records[self]
local rules = record.policy:evaluate_highlight_links()
diff --git a/tests/run.lua b/tests/run.lua
index 1a3536f..1bd0c64 100644
--- a/tests/run.lua
+++ b/tests/run.lua
@@ -4432,6 +4432,31 @@ test("Direct overlays use ordinary priority", function()
)
end)
+test("Cursor marker overlays the exact cursor byte position", function()
+ local state, transitions = fresh_sequence_state()
+ local host = MemoryHost.new({
+ buffer_lines = { "a\227\129\130b" },
+ cursor = { line = 1, byte_column = 5 },
+ })
+ local feedback = feedback_service.new({
+ host = host,
+ transitions = transitions,
+ })
+ local cursor = host:read_cursor()
+
+ local marker = feedback:create_cursor_marker(cursor, "window-1")
+ local highlight = host:highlights()[marker.identity]
+ same("CleverFCursor", highlight.group)
+ same("window-1", highlight.window)
+ same(domain.Position.new(1, 5), highlight.position)
+ same(feedback_service.Priority.HIGH, highlight.priority)
+ same(marker.identity, state:temporary_overlay_identities()[1])
+
+ truthy(feedback:remove_temporary_overlay(marker))
+ same(nil, host:highlights()[marker.identity])
+ same(0, #state:temporary_overlay_identities())
+end)
+
for _, item in ipairs(tests) do
local ok, failure = xpcall(item.body, debug.traceback)
if not ok then