Skip to content

Instantly share code, notes, and snippets.

@tmillr
Last active August 5, 2024 07:15
Show Gist options
  • Save tmillr/0836583db4273067aa7193a6d4251b27 to your computer and use it in GitHub Desktop.
Save tmillr/0836583db4273067aa7193a6d4251b27 to your computer and use it in GitHub Desktop.
How to set or update the `winhl` option in Neovim (properly)
---Sets `winhl` without clobbering any existing mappings (i.e. of highlight groups not
---in `mappings`). Currently only supports setting `winhl` locally (which is likely what
---you want if the mappings are buffer-specific).
---@param win integer window to set the mappings on; use `0` for the current window
---@param mappings table<string, string|false>|false table of mappings to set (or clear if `false`)
local function set_winhl(win, mappings)
api.nvim_win_call(win == 0 and api.nvim_get_current_win() or win, function()
if not mappings then
-- Clear local mappings and use global values.
vim.opt_local.winhl = nil
return
end
local res = {}
do
-- NOTE: `lower()` is used here because highlight groups are case-insensitive and
-- nvim does not account for this (e.g. when doing `vim.opt_local.winhl:append()`)
local mappings_lower = {}
for from, to in pairs(mappings) do
local from_lower = from:lower()
if mappings_lower[from_lower] then
error('duplicate mapping: ' .. from)
end
-- Coerce false to `nil` (`false` clears a mapping).
res[from], mappings_lower[from_lower] = to or nil, true
end
for old_from, old_to in pairs(vim.opt_local.winhl:get()) do
if mappings_lower[old_from:lower()] == nil then
res[old_from] = old_to
end
end
end
vim.opt_local.winhl = res
end)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment