summaryrefslogtreecommitdiff
path: root/lua/clever_f/host_adapter.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/clever_f/host_adapter.lua')
-rw-r--r--lua/clever_f/host_adapter.lua160
1 files changed, 160 insertions, 0 deletions
diff --git a/lua/clever_f/host_adapter.lua b/lua/clever_f/host_adapter.lua
index a0eec66..747d9b8 100644
--- a/lua/clever_f/host_adapter.lua
+++ b/lua/clever_f/host_adapter.lua
@@ -41,6 +41,8 @@ function HostAdapter.new(options)
local adapter = setmetatable({}, HostAdapter)
adapter_records[adapter] = {
runtime = require_runtime(current_runtime(options)),
+ next_identity = 1,
+ highlights = {},
}
return adapter
end
@@ -53,6 +55,164 @@ function HostAdapter:runtime()
return adapter_records[self].runtime
end
+local function next_identity(adapter, prefix)
+ local record = adapter_records[adapter]
+ local identity = prefix .. "-" .. tostring(record.next_identity)
+ record.next_identity = record.next_identity + 1
+ return identity
+end
+
+local function highlight_exists(runtime, name)
+ if type(runtime.fn) == "table" and type(runtime.fn.hlexists) == "function" then
+ return runtime.fn.hlexists(name) == 1
+ end
+ local definition = runtime.api.nvim_get_hl(0, {
+ name = name,
+ link = true,
+ create = false,
+ })
+ return next(definition) ~= nil
+end
+
+function HostAdapter:read_highlight_group(name)
+ if type(name) ~= "string" or name == "" then
+ fail("highlight group name must be a nonempty string", 2)
+ end
+ local runtime = self:runtime()
+ if not highlight_exists(runtime, name) then
+ return nil
+ end
+ return runtime.api.nvim_get_hl(0, {
+ name = name,
+ link = true,
+ create = false,
+ })
+end
+
+local function native_highlight_definition(definition, options)
+ if type(definition) ~= "table" then
+ fail("highlight group definition must be a table", 3)
+ end
+ options = options or {}
+ if type(options) ~= "table" then
+ fail("highlight group options must be a table", 3)
+ end
+ local native = {}
+ for key, value in pairs(definition) do
+ if key ~= "guifg" and key ~= "guibg" and key ~= "gui" then
+ native[key] = value
+ end
+ end
+ if definition.guifg ~= nil then
+ native.fg = definition.guifg
+ end
+ if definition.guibg ~= nil then
+ native.bg = definition.guibg
+ end
+ for key, value in pairs(definition.gui or {}) do
+ native[key] = value
+ end
+ if options.default ~= nil then
+ native.default = options.default
+ end
+ if options.force ~= nil then
+ native.force = options.force
+ end
+ return native
+end
+
+function HostAdapter:define_highlight_group(name, definition, options)
+ if type(name) ~= "string" or name == "" then
+ fail("highlight group name must be a nonempty string", 2)
+ end
+ options = options or {}
+ local runtime = self:runtime()
+ if options.default and highlight_exists(runtime, name) then
+ return false
+ end
+ runtime.api.nvim_set_hl(
+ 0,
+ name,
+ native_highlight_definition(definition, options)
+ )
+ return true
+end
+
+local function overlay_positions(specification)
+ local positions = specification.positions
+ if positions == nil and specification.position ~= nil then
+ positions = { specification.position }
+ end
+ if type(positions) ~= "table" then
+ fail("highlight positions must be a list", 3)
+ end
+ local native = {}
+ for index, position in ipairs(positions) do
+ position = domain.Position.coerce(position)
+ native[index] = { position.line, position.byte_column }
+ end
+ if #native == 0 then
+ native[1] = { 0 }
+ end
+ return native
+end
+
+local function overlay_priority(value)
+ if value == "high" then
+ return 100
+ end
+ if value == "ordinary" or value == nil then
+ return 10
+ end
+ if type(value) == "number" then
+ return value
+ end
+ fail("highlight priority must be high, ordinary, or numeric", 3)
+end
+
+function HostAdapter:create_highlight(specification)
+ if type(specification) ~= "table" then
+ fail("highlight specification must be a table", 2)
+ end
+ if type(specification.group) ~= "string" or specification.group == "" then
+ fail("highlight group must be a nonempty string", 2)
+ end
+ if specification.window == nil then
+ fail("highlight window must identify its Nvim window", 2)
+ end
+ local record = adapter_records[self]
+ local identity = specification.identity or next_identity(self, "highlight")
+ if record.highlights[identity] ~= nil then
+ fail("highlight identity is already active", 2)
+ end
+ local match_id = record.runtime.fn.matchaddpos(
+ specification.group,
+ overlay_positions(specification),
+ overlay_priority(specification.priority),
+ -1,
+ { window = specification.window }
+ )
+ if type(match_id) ~= "number" or match_id < 0 then
+ fail("Nvim could not create the window-local highlight", 2)
+ end
+ record.highlights[identity] = {
+ match_id = match_id,
+ window = specification.window,
+ }
+ return identity
+end
+
+function HostAdapter:remove_highlight(identity)
+ local record = adapter_records[self]
+ local resource = record.highlights[identity]
+ if resource == nil then
+ return false
+ end
+ record.highlights[identity] = nil
+ record.runtime.fn.matchdelete(resource.match_id, resource.window)
+ return true
+end
+
local function escape_key(runtime)
if type(runtime.keycode) == "function" then
return runtime.keycode("<Esc>")