Skip to content

Commit

Permalink
feat(overrides): improve highlight-group overrides (#349)
Browse files Browse the repository at this point in the history
- 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 (like `reset()` but finer-grained)

- (internal) Use `false` instead of `link = ''` to mark groups which
  should be cleared when set

- Improve `github-theme.group`

- Improve/cleanup code and other minor improvements (code-sharing,
  simplification, etc.)
  • Loading branch information
tmillr committed Jul 15, 2024
1 parent 23484d2 commit 40b5489
Show file tree
Hide file tree
Showing 9 changed files with 178 additions and 49 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion lua/github-theme/_test/util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
36 changes: 13 additions & 23 deletions lua/github-theme/group.lua
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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
6 changes: 3 additions & 3 deletions lua/github-theme/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
41 changes: 31 additions & 10 deletions lua/github-theme/override.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, table|false>
---@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,
})
Expand Down
22 changes: 13 additions & 9 deletions lua/github-theme/util/reload.lua
Original file line number Diff line number Diff line change
@@ -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,
})
3 changes: 1 addition & 2 deletions test/github-theme/config/darken_spec.lua
Original file line number Diff line number Diff line change
@@ -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

Expand Down
108 changes: 108 additions & 0 deletions test/github-theme/config/overrides_spec.lua
Original file line number Diff line number Diff line change
@@ -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)
6 changes: 5 additions & 1 deletion test/minimal_init.vim
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 40b5489

Please sign in to comment.