Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(overrides): improve highlight-group overrides #349

Merged
merged 2 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading