From 6e59aeaa6c2d912adc9bfa6bc6e30ccf368b9b1b Mon Sep 17 00:00:00 2001 From: Tyler Miller Date: Mon, 5 Aug 2024 00:22:52 -0700 Subject: [PATCH] fix(autocmds): don't clobber `winhl` nvim option The user might have their own, custom hlgroup mappings in `winhl` that we shouldn't be clobbering when they don't conflict with ours. Also cleanup `autocmds.lua` and ensure that autocmds ALWAYS get defined/cleared when the colorscheme changes, and make it impossible for the same autocmd to get defined multiple times. --- CHANGELOG.md | 1 + lua/github-theme/autocmds.lua | 45 ++++++---------- lua/github-theme/util/init.lua | 57 +++++++++++++++++++-- test/github-theme/config/overrides_spec.lua | 2 +- 4 files changed, 73 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac95706f..c8af5128 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ The format is based on [Keep a Changelog], and this project adheres to [Semantic - Made `Color()` constructor idempotent (previously, passing a `Color` inst silently caused a bug) - Fixed unable to override/customize spec (#359) +- Fixed `winhl` gets clobbered when set ## [v1.1.0] - 23 July 2024 diff --git a/lua/github-theme/autocmds.lua b/lua/github-theme/autocmds.lua index 7c82794e..dd3235a6 100644 --- a/lua/github-theme/autocmds.lua +++ b/lua/github-theme/autocmds.lua @@ -1,54 +1,43 @@ -local config = require('github-theme.config') - -local M = { - checked_autocmds = false, -} +local api = vim.api +local M = {} M.set_autocmds = function() - if M.checked_deprecation then - return - end - - local group = vim.api.nvim_create_augroup(config.theme, { clear = false }) + local config = require('github-theme.config') + local util = require('github-theme.util') + local group = api.nvim_create_augroup(config.theme, { clear = true }) + local winhl = { Normal = 'NormalSB', SignColumn = 'SignColumnSB' } - -- Delete the github-theme autocmds when the theme changes to something else - vim.api.nvim_create_autocmd('ColorScheme', { + api.nvim_create_autocmd('ColorSchemePre', { + desc = 'Cleanup (autocmds, etc.)', pattern = '*', group = group, - callback = function() - if vim.g.colors_name ~= config.theme then - pcall(vim.api.nvim_del_augroup_by_id, group) - end + once = true, + callback = function(ev) + pcall(api.nvim_del_augroup_by_id, ev.group) end, }) - local func_winhightlight = function() - vim.wo.winhighlight = 'Normal:NormalSB,SignColumn:SignColumnSB' - end - for _, sidebar in ipairs(config.options.darken.sidebars.list) do if sidebar == 'terminal' then - -- Set dark color for terminal background., - vim.api.nvim_create_autocmd('TermOpen', { + api.nvim_create_autocmd('TermOpen', { + desc = 'Darken terminal bg', pattern = '*', group = group, callback = function() - func_winhightlight() + util.set_winhl(0, winhl) end, }) else - -- Set dark color for custom sidebars background. - vim.api.nvim_create_autocmd('FileType', { + api.nvim_create_autocmd('FileType', { + desc = 'Darken sidebar bg', pattern = sidebar, group = group, callback = function() - func_winhightlight() + util.set_winhl(0, winhl) end, }) end end - - M.checked_autocmds = true end return M diff --git a/lua/github-theme/util/init.lua b/lua/github-theme/util/init.lua index 1ba72161..9f59bdf5 100644 --- a/lua/github-theme/util/init.lua +++ b/lua/github-theme/util/init.lua @@ -1,13 +1,17 @@ +local api = vim.api + +---@class GhTheme.Util +---@field cache_home string local M = {} ----Round float to nearest int +---Rounds a float to the nearest integer. ---@param x number Float ---@return number function M.round(x) return x >= 0 and math.floor(x + 0.5) or math.ceil(x - 0.5) end ----Clamp value between the min and max values. +---Clamps `value` between the min and max values. ---@param value number ---@param min number ---@param max number @@ -61,6 +65,53 @@ function M.ensure_dir(path) end end -M.cache_home = vim.fn.stdpath('cache') +---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|false table of mappings to set (or clear if `false`) +function M.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 + +setmetatable(M, { + __index = function(_, k) + if k == 'cache_home' then + return vim.fn.stdpath('cache') + end + end, +}) return M diff --git a/test/github-theme/config/overrides_spec.lua b/test/github-theme/config/overrides_spec.lua index 8b7df932..ffd15f1f 100644 --- a/test/github-theme/config/overrides_spec.lua +++ b/test/github-theme/config/overrides_spec.lua @@ -131,6 +131,6 @@ describe('config > specs', function() assert.equals('#654321', spec.bg1) vim.cmd.colorscheme({ args = { 'github_dark_dimmed' } }) - assert.same(tonumber('654321', 16), t_util.get_hl('Normal').bg) + assert.equals(tonumber('654321', 16), t_util.get_hl('Normal').bg) end) end)