Skip to content
This repository has been archived by the owner on Nov 7, 2024. It is now read-only.

feat: allow multiple colorschemes #54

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
79 changes: 69 additions & 10 deletions lua/tint.lua
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ end
---
---@param hl_group_name string
---@param hl_def table # highlight definition, see `:h nvim_set_hl`
local function set_tint_ns(hl_group_name, hl_def)
local function set_tint_ns(hl_group_name, hl_def, ns_hl_id)
local ignored = hl_group_is_ignored(hl_group_name)
local hl_group_info = { hl_group_name = hl_group_name }

Expand All @@ -151,15 +151,15 @@ local function set_tint_ns(hl_group_name, hl_def)
hl_def.bg = transforms.transform_color(hl_group_info, colors.get_hex(hl_def.bg), __.user_config.transforms)
end

vim.api.nvim_set_hl(__.tint_ns, hl_group_name, hl_def)
vim.api.nvim_set_hl(ns_hl_id, hl_group_name, hl_def)
end

--- Backwards compatibile (for now) method of getting highlights as nvim__get_hl_defs is removed in #22693
---
---@return table<string, any> # highlight definitions
local function get_global_highlights()
local function get_global_highlights(ns_id)
levouh marked this conversation as resolved.
Show resolved Hide resolved
---@diagnostic disable-next-line: undefined-field
return vim.api.nvim__get_hl_defs and vim.api.nvim__get_hl_defs(0) or vim.api.nvim_get_hl(0, {})
return vim.api.nvim__get_hl_defs and vim.api.nvim__get_hl_defs(ns_id) or vim.api.nvim_get_hl(ns_id, {})
end

--- Setup color namespaces such that they can be set per-window
Expand All @@ -169,14 +169,71 @@ local function setup_namespaces()
__.tint_ns = vim.api.nvim_create_namespace("_tint_dim")
end

for hl_group_name, hl_def in pairs(get_global_highlights()) do
for hl_group_name, hl_def in pairs(get_global_highlights(0)) do
-- Ensure we only have valid keys copied over
hl_def = ensure_valid_hl_keys(hl_def)
set_default_ns(hl_group_name, hl_def)
set_tint_ns(hl_group_name, hl_def)
set_tint_ns(hl_group_name, hl_def, __.tint_ns)
end
end

local function add_namespace(ns_id, suffix)
__["tint_ns_" .. suffix] = vim.api.nvim_create_namespace("_tint_dim_" .. suffix)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not see that we are ever deleting these. I haven't used this patch yet so I am not sure how often they will build up, but I can imagine a scenario where this might be an issue?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on tints init only the default tinted scheme will be built, and tint is not aware of any schemes that might be loaded by styler on opening a specific filetype.

so i test a window for having a different ns_id as the default 0, then test if there is already a tinted version (if not _["tint_ns" .. ns_suffix]) and only then add another tinted namespace.

It should add up only depending on the number of colorschemes a user adds e.g. by using styler :)
I dont do extra checks to prevent tinting of an already tinted colorscheme...maybe I should add that, since "tint.tint" can be executed by user on any window, already tinted or not...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I forgot I put the windows "untint_ns_id" to a window var, which prevents double tinting.

This window var gets deleted on restore_default_highlight_namespaces and untint, to allow switching of scheme if windows buffer and filetype change.

Copy link
Author

@sheimer sheimer Jun 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found a problem with neo-tree
It sets a namespace on the window, but anonymous with id only, and creates a new id on each focus. So you were right, many new tint-namespaces got created.

For now I changed to only create a new namespace, if a name can be found.
Maybe it would be better to only create additional namespaces if a function "add_tint_function" returns true? (similar to window_ignore_function).


for hl_group_name, hl_def in pairs(get_global_highlights(ns_id)) do
-- Ensure we only have valid keys copied over
hl_def = ensure_valid_hl_keys(hl_def)
set_tint_ns(hl_group_name, hl_def, __["tint_ns_" .. suffix])
end
end

---@param winid number
---@return number
local function get_untint_ns_id(winid)
local untint_ns_id = vim.w[winid].untint_ns_id
if untint_ns_id == nil then
untint_ns_id = vim.api.nvim_get_hl_ns and vim.api.nvim_get_hl_ns({ winid = winid })
if untint_ns_id == nil or untint_ns_id < 0 then
untint_ns_id = 0
end
vim.api.nvim_win_set_var(winid, "untint_ns_id", untint_ns_id)
end
return untint_ns_id
end

---@param winid number
---@return number
local function get_tint_ns_id(winid)
local untint_ns_id = get_untint_ns_id(winid)

local tint_ns_id
if untint_ns_id == 0 then
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Can simplify things here a bit by doing:

if untint_ns_id == 0 or not __.user_config.should_create_extra_tint(winid, untint_ns_id, ns_suffix) then

to make the function logic a bit more readable here - either we are just using the global namespace or we are using the user-enabled stuff.

Copy link
Author

@sheimer sheimer Jul 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you are right and it is better to make it more readable. For your suggestion I would need the ns_suffix always, so i decided to go a different way...to accomplish readability.
The result uses the "should_create_extra_tint" method only if no __.tint_ns_<originalid> exists already. To simplify a little more, i renamed the defaults tint_ns to __.tint_ns_0 - please let me know if you prefer the division to tint_ns and extra_namespaces

tint_ns_id = __.tint_ns
else
local ns_suffix
for ns_name, ns_id in pairs(vim.api.nvim_get_namespaces()) do
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this necessary? The docs for nvim_create_namespace say:

    Namespaces can be named or anonymous. If `name` matches an existing
    namespace, the associated id is returned. If `name` is an empty string a

which if the goal here is to try to find an existing namespace or not, we can likely just call this function to "create or get", right? I have not gone through the code thoroughly yet so my interpretation of what you are trying to do here might be wrong.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not necessary for the changes to work.

While debugging I found a lot of hl-namespaces, and all had pretty clear namespace names, so everyone can figure out where they are coming from. Thats why I decided to go with a specific name depending on found colorscheme :)

if ns_id == untint_ns_id then
ns_suffix = ns_name
break
end
end
if not ns_suffix then
ns_suffix = untint_ns_id
end

if not __["tint_ns_" .. ns_suffix] then
add_namespace(untint_ns_id, ns_suffix)
end
tint_ns_id = __["tint_ns_" .. ns_suffix]
end

if type(tint_ns_id) ~= "number" then
tint_ns_id = 0
end

return tint_ns_id
end

--- Create an `:h augroup` for autocommands used by this plugin
---
---@return number # handle for created augroup
Expand Down Expand Up @@ -368,7 +425,8 @@ end
--- Restore the global highlight namespace in all windows
local function restore_default_highlight_namespaces()
iterate_all_windows(function(winid, _)
vim.api.nvim_win_set_hl_ns(winid, 0)
vim.api.nvim_win_set_hl_ns(winid, get_untint_ns_id(winid))
vim.api.nvim_win_del_var(winid, "untint_ns_id")
end)
end

Expand Down Expand Up @@ -583,7 +641,7 @@ tint.tint = function(winid)
return
end

set_window_hl_ns(winid, __.tint_ns)
set_window_hl_ns(winid, get_tint_ns_id(winid))
end

--- Untint the specified window
Expand All @@ -595,7 +653,8 @@ tint.untint = function(winid)
return
end

set_window_hl_ns(winid, __.default_ns)
set_window_hl_ns(winid, get_untint_ns_id(winid))
vim.api.nvim_win_del_var(winid, "untint_ns_id")
end

return tint
return tint