diff --git a/CHANGELOG.md b/CHANGELOG.md index 0536925..a778c68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### What's New? - Added new highlight groups for mini.nvim (#333 by @echasnovski) +- Improved highlight-group overrides (#349) +- Assigning `false` or an empty table to a highlight group clears it +- Assigning `false` to groups/specs/palettes clears previous settings from the config store ### Changes diff --git a/lua/github-theme/_test/util.lua b/lua/github-theme/_test/util.lua index 24a92fb..7bf1181 100644 --- a/lua/github-theme/_test/util.lua +++ b/lua/github-theme/_test/util.lua @@ -29,7 +29,7 @@ function M.get_hl(group, link) }) end -if vim.fn.has('nvim-0.10.0') == false or vim.fn.has('nvim-0.10.0') == 0 then +if vim.fn.has('nvim-0.10.0') == 0 or vim.fn.has('nvim-0.10.0') == false then function M.get_hl(group, link) return api.nvim_get_hl(0, { name = group, diff --git a/lua/github-theme/group.lua b/lua/github-theme/group.lua index aed77aa..529501d 100644 --- a/lua/github-theme/group.lua +++ b/lua/github-theme/group.lua @@ -1,23 +1,9 @@ local collect = require('github-theme.lib.collect') local template = require('github-theme.util.template') - +local override = require('github-theme.override') local M = {} -local function override(groups, spec, ovr) - ovr = template.parse(ovr, spec) - -- If `set = {}` in override, - -- the corresponding group is deleted. - -- https://github.com/projekt0n/github-nvim-theme/issues/249 - for k, v in pairs(ovr) do - if v.link == '' then - groups[k] = nil - end - end - return collect.deep_extend(groups, ovr) -end - function M.from(spec) - local ovr = require('github-theme.override').groups local config = require('github-theme.config').options if not spec then @@ -26,7 +12,7 @@ function M.from(spec) local editor = require('github-theme.group.editor').get(spec, config) local syntax = require('github-theme.group.syntax').get(spec, config) - local result = collect.deep_extend(editor, syntax) + local res = collect.deep_extend(editor, syntax) local default_enable_value = config.module_default local mod_names = require('github-theme.config').module_names @@ -38,25 +24,29 @@ function M.from(spec) opts.enable = opts.enable == nil and default_enable_value or opts.enable if opts.enable then - result = collect.deep_extend( - result, + res = collect.deep_extend( + res, require('github-theme.group.modules.' .. name).get(spec, config, opts) ) end end - local function apply_ovr(key, groups) - return ovr[key] and override(groups, spec, ovr[key]) or groups + local ovr = override.groups + + if ovr.all then + override.extend_groups(res, template.parse(ovr.all, spec), {}) end - result = apply_ovr('all', result) - result = apply_ovr(spec.palette.meta.name, result) + if ovr[spec.palette.meta.name] then + override.extend_groups(res, template.parse(ovr[spec.palette.meta.name], spec), {}) + end - return result + return res end function M.load(name) name = name or require('github-theme.config').theme return M.from(require('github-theme.spec').load(name)) end + return M diff --git a/lua/github-theme/init.lua b/lua/github-theme/init.lua index dc769bd..37e4208 100644 --- a/lua/github-theme/init.lua +++ b/lua/github-theme/init.lua @@ -82,15 +82,15 @@ M.setup = function(opts) config.set_options(opts.options) end - if opts.palettes then + if opts.palettes ~= nil then override.palettes = opts.palettes end - if opts.specs then + if opts.specs ~= nil then override.specs = opts.specs end - if opts.groups then + if opts.groups ~= nil then override.groups = opts.groups end diff --git a/lua/github-theme/override.lua b/lua/github-theme/override.lua index a47d678..a3fc15f 100644 --- a/lua/github-theme/override.lua +++ b/lua/github-theme/override.lua @@ -11,27 +11,48 @@ function M.hash() return require('github-theme.lib.hash')(getmetatable(M).__index) or 0 end -local function check_link(tbl) - for _, theme in pairs(tbl) do - for _, opts in pairs(theme) do - opts.link = opts.link or '' +---Extends `groups` with `overrides`. `groups` is modified in-place. +---@generic T: table +---@param groups T a table of highlight groups +---@param overrides T | nil +---@param nullval any the marker to use for cleared groups +---@return T groups +function M.extend_groups(groups, overrides, nullval) + for grp_name, grp in pairs(overrides or {}) do + if grp == false or next(grp) == nil then + -- clear the group + groups[grp_name] = nullval + else + -- `link` is not compatible with other settings + if grp.link then + groups[grp_name] = { link = grp.link } + else + groups[grp_name] = vim.tbl_deep_extend('force', groups[grp_name] or {}, grp) + + -- Clear previous `link`, or `grp.link = false` + groups[grp_name].link = nil + end end end + + return groups end setmetatable(M, { __newindex = function(self, k, v) local store = getmetatable(self).__index + if type(store[k]) == 'table' then if not v then store[k] = {} - return - end - if k == 'groups' then - check_link(v) + elseif k == 'groups' then + for theme, grps in pairs(v) do + store.groups[theme] = store.groups[theme] or {} + M.extend_groups(store.groups[theme], grps, false) + end + else + store[k] = vim.tbl_deep_extend('force', store[k], v) end - store[k] = collect.deep_extend(store[k], v) - store.has_override = true end end, }) diff --git a/lua/github-theme/util/reload.lua b/lua/github-theme/util/reload.lua index df496a5..19eb7df 100644 --- a/lua/github-theme/util/reload.lua +++ b/lua/github-theme/util/reload.lua @@ -1,19 +1,23 @@ -local function reload() - for name, _ in pairs(package.loaded) do - if name:match('^github-theme') then +---@param force? boolean +local function reload(force) + for name, _ in pairs(_G.package.loaded) do + if name:find('^github%-theme') then if - not name:match('config') - and not name:match('deprecation') - and not name:match('override') + force + or ( + not name:find('config') + and not name:find('deprecation') + and not name:find('override') + ) then - package.loaded[name] = nil + _G.package.loaded[name] = nil end end end end return setmetatable({}, { - __call = function(_) - reload() + __call = function(_, ...) + reload(...) end, }) diff --git a/test/github-theme/config/darken_spec.lua b/test/github-theme/config/darken_spec.lua index 063a328..c0502c1 100644 --- a/test/github-theme/config/darken_spec.lua +++ b/test/github-theme/config/darken_spec.lua @@ -1,9 +1,8 @@ local assert = require('luassert') local t_util = require('github-theme._test.util') local C = require('github-theme.lib.color') -local api = vim.api -if not api.nvim_get_hl then +if vim.fn.has('nvim-0.9.0') == 0 or vim.fn.has('nvim-0.9.0') == false then return end diff --git a/test/github-theme/config/overrides_spec.lua b/test/github-theme/config/overrides_spec.lua new file mode 100644 index 0000000..d9b7fb7 --- /dev/null +++ b/test/github-theme/config/overrides_spec.lua @@ -0,0 +1,108 @@ +local assert = require('luassert') +local t_util = require('github-theme._test.util') + +if vim.fn.has('nvim-0.9.0') == 0 or vim.fn.has('nvim-0.9.0') == false then + return +end + +describe('config > groups', function() + before_each(function() + require('github-theme.util.reload')(true) + end) + + it('should allow clearing a group via empty table (1)', function() + require('github-theme').setup({ groups = { all = { Normal = {} } } }) + vim.cmd.colorscheme({ args = { 'github_dark_dimmed' } }) + assert.same({}, t_util.get_hl('Normal')) + end) + + it('should allow clearing a group via empty table (2)', function() + require('github-theme').setup({ + groups = { + github_dark_dimmed = { Normal = {} }, + all = { Normal = { fg = '#123456', bg = '#654321' } }, + }, + }) + vim.cmd.colorscheme({ args = { 'github_dark_dimmed' } }) + assert.same({}, t_util.get_hl('Normal')) + end) + + it('clearing group combines properly with more-specific overrides', function() + require('github-theme').setup({ + groups = { + all = { Normal = {} }, + github_dark_dimmed = { Normal = { fg = '#123456', bg = '#654321' } }, + }, + }) + vim.cmd.colorscheme({ args = { 'github_dark_dimmed' } }) + assert.same( + { fg = tonumber('123456', 16), bg = tonumber('654321', 16) }, + t_util.get_hl('Normal') + ) + end) + + it('should allow overriding a group', function() + require('github-theme').setup({ + groups = { all = { Normal = { fg = '#123456', bg = '#654321' } } }, + }) + vim.cmd.colorscheme({ args = { 'github_dark_dimmed' } }) + assert.same( + { fg = tonumber('123456', 16), bg = tonumber('654321', 16) }, + t_util.get_hl('Normal') + ) + end) + + it('overriding group combines properly with more-specific overrides (1)', function() + require('github-theme').setup({ + groups = { + all = { Normal = { link = 'NormalNC' } }, + github_dark_dimmed = { Normal = { fg = '#123456', bg = '#654321' } }, + }, + }) + vim.cmd.colorscheme({ args = { 'github_dark_dimmed' } }) + assert.is_nil(t_util.get_hl('Normal', true).link) + end) + + it('overriding group combines properly with more-specific overrides (2)', function() + require('github-theme').setup({ + groups = { + all = { Normal = { fg = '#123456', bg = '#654321' } }, + github_dark_dimmed = { Normal = { link = 'NormalNC' } }, + }, + }) + vim.cmd.colorscheme({ args = { 'github_dark_dimmed' } }) + assert.same({ link = 'NormalNC' }, t_util.get_hl('Normal', true)) + end) + + it('should allow linking a group', function() + require('github-theme').setup({ + groups = { all = { Normal = { link = 'NormalNC' } } }, + }) + vim.cmd.colorscheme({ args = { 'github_dark_dimmed' } }) + assert.same({ link = 'NormalNC' }, t_util.get_hl('Normal', true)) + end) + + it('should not be affected by a previous override using `link`', function() + require('github-theme').setup({ + groups = { + all = { Normal = { link = 'NormalNC' } }, + }, + }) + require('github-theme').setup({ + groups = { + all = { Normal = { fg = '#123456', bg = '#654321' } }, + }, + }) + + vim.cmd.colorscheme({ args = { 'github_dark_dimmed' } }) + assert.same( + { fg = '#123456', bg = '#654321' }, + require('github-theme.override').groups.all.Normal + ) + assert.is_nil(t_util.get_hl('Normal', true).link) + assert.same( + { fg = tonumber('123456', 16), bg = tonumber('654321', 16) }, + t_util.get_hl('Normal') + ) + end) +end) diff --git a/test/minimal_init.vim b/test/minimal_init.vim index ec2c966..6aa2d4e 100644 --- a/test/minimal_init.vim +++ b/test/minimal_init.vim @@ -1,4 +1,8 @@ -lua vim.loader.disable() +lua << + if vim.fn.has('nvim-0.9.0') == 1 or vim.fn.has('nvim-0.9.0') == true then + vim.loader.disable() + end +. set rtp+=. set rtp+=./test/plenary runtime! plugin/plenary.vim