summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lua/clever_f/host_adapter.lua72
-rw-r--r--tests/run.lua54
2 files changed, 126 insertions, 0 deletions
diff --git a/lua/clever_f/host_adapter.lua b/lua/clever_f/host_adapter.lua
index ab3467c..51591a9 100644
--- a/lua/clever_f/host_adapter.lua
+++ b/lua/clever_f/host_adapter.lua
@@ -45,6 +45,7 @@ function HostAdapter.new(options)
next_identity = 1,
highlights = {},
timers = {},
+ cursor_presentations = {},
events = {},
event_order = {},
augroup = nil,
@@ -417,6 +418,77 @@ function HostAdapter:commit_action_transition(token)
return adapter_records[self].event_queue:commit_transition(token)
end
+local function terminal_cursor_option(runtime)
+ return runtime.fn.eval("&t_ve")
+end
+
+local function set_terminal_cursor_option(runtime, value)
+ runtime.api.nvim_cmd({
+ cmd = "let",
+ args = { "&t_ve", "=", runtime.fn.string(value) },
+ }, {})
+end
+
+function HostAdapter:supports_cursor_presentation()
+ local runtime = self:runtime()
+ return type(runtime.api.nvim_get_option_value) == "function"
+ and type(runtime.api.nvim_set_option_value) == "function"
+ and type(runtime.api.nvim_cmd) == "function"
+ and type(runtime.fn) == "table"
+ and type(runtime.fn.exists) == "function"
+ and runtime.fn.exists("+t_ve") == 1
+ and type(runtime.fn.eval) == "function"
+ and type(runtime.fn.string) == "function"
+end
+
+function HostAdapter:suppress_cursor_presentation()
+ if not self:supports_cursor_presentation() then
+ return nil
+ end
+ local record = adapter_records[self]
+ local runtime = record.runtime
+ local identity = next_identity(self, "cursor-presentation")
+ local saved = {
+ guicursor = runtime.api.nvim_get_option_value(
+ "guicursor",
+ { scope = "global" }
+ ),
+ terminal_cursor = terminal_cursor_option(runtime),
+ }
+ runtime.api.nvim_set_option_value(
+ "guicursor",
+ "a:ver1",
+ { scope = "global" }
+ )
+ local ok, failure = pcall(set_terminal_cursor_option, runtime, "")
+ if not ok then
+ runtime.api.nvim_set_option_value(
+ "guicursor",
+ saved.guicursor,
+ { scope = "global" }
+ )
+ error(failure, 0)
+ end
+ record.cursor_presentations[identity] = saved
+ return identity
+end
+
+function HostAdapter:restore_cursor_presentation(identity)
+ local record = adapter_records[self]
+ local saved = record.cursor_presentations[identity]
+ if saved == nil then
+ return false
+ end
+ record.cursor_presentations[identity] = nil
+ record.runtime.api.nvim_set_option_value(
+ "guicursor",
+ saved.guicursor,
+ { scope = "global" }
+ )
+ set_terminal_cursor_option(record.runtime, saved.terminal_cursor)
+ return true
+end
+
local function escape_key(runtime)
if type(runtime.keycode) == "function" then
return runtime.keycode("<Esc>")
diff --git a/tests/run.lua b/tests/run.lua
index e0c9b0c..5ca4f34 100644
--- a/tests/run.lua
+++ b/tests/run.lua
@@ -361,6 +361,60 @@ test("ActionOutcome and DotPayload retain resolved result data", function()
same("problem", domain.ActionOutcome.error(destination, "problem").diagnostic)
end)
+test("Host adapter restores exact cursor presentation values", function()
+ local options = {
+ guicursor = "n:block,i:ver37-blinkon123",
+ t_ve = "terminal-visible-sequence",
+ }
+ local writes = {}
+ local runtime = {
+ api = {
+ nvim_get_option_value = function(name, request)
+ same("global", request.scope)
+ return options[name]
+ end,
+ nvim_set_option_value = function(name, value, request)
+ same("global", request.scope)
+ options[name] = value
+ writes[#writes + 1] = { name = name, value = value }
+ end,
+ nvim_cmd = function(command)
+ same("let", command.cmd)
+ same("&t_ve", command.args[1])
+ same("=", command.args[2])
+ options.t_ve = command.args[3]
+ writes[#writes + 1] = { name = "t_ve", value = command.args[3] }
+ end,
+ },
+ fn = {
+ exists = function(name)
+ same("+t_ve", name)
+ return 1
+ end,
+ eval = function(name)
+ same("&t_ve", name)
+ return options.t_ve
+ end,
+ string = function(value)
+ return value
+ end,
+ },
+ }
+ local adapter = host_adapter.new({ runtime = runtime })
+ truthy(adapter:supports_cursor_presentation())
+
+ local lease = adapter:suppress_cursor_presentation()
+ truthy(lease ~= nil)
+ same("a:ver1", options.guicursor)
+ same("", options.t_ve)
+
+ truthy(adapter:restore_cursor_presentation(lease))
+ same("n:block,i:ver37-blinkon123", options.guicursor)
+ same("terminal-visible-sequence", options.t_ve)
+ falsy(adapter:restore_cursor_presentation(lease))
+ same(4, #writes)
+end)
+
test("Host adapter owns Nvim timers and event registrations", function()
local timer_callbacks = {}
local stopped_timers = {}