diff options
| -rw-r--r-- | lua/clever_f/feedback_service.lua | 51 | ||||
| -rw-r--r-- | tests/run.lua | 25 |
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 |
