diff options
Diffstat (limited to 'lua/clever_f')
| -rw-r--r-- | lua/clever_f/host_adapter.lua | 160 |
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>") |
