Files
omarchy-pkgs/pkgbuilds/omarchy-nvim/lua/plugins/omarchy-theme-hotreload.lua
T
David Heinemeier HanssonandClaude Fable 5 94ee311b25 Fix theme hot-reload when old and new theme share the same colorscheme plugin
lazy.nvim caches a plugin's resolved opts in plugin._.cache and carries
that state over on a spec reload, and Loader.colorscheme() no-ops for
already-loaded plugins. So switching between two themes driven by the
same colorscheme plugin (e.g. generic themes on aether.nvim) never
pushed the new palette into setup(), leaving stale colors until nvim
was restarted. Fully reload the theme plugin instead, which clears the
cached opts and reruns config with the new theme's colors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 20:34:27 -07:00

101 lines
3.2 KiB
Lua

return {
{
name = "theme-hotreload",
dir = vim.fn.stdpath("config"),
lazy = false,
priority = 1000,
config = function()
local transparency_file = vim.fn.stdpath("config") .. "/plugin/after/transparency.lua"
vim.api.nvim_create_autocmd("User", {
pattern = "LazyReload",
callback = function()
-- Unload the theme module
package.loaded["plugins.theme"] = nil
vim.schedule(function()
local ok, theme_spec = pcall(require, "plugins.theme")
if not ok then
return
end
-- Find the theme plugin and unload it
local theme_plugin_name = nil
for _, spec in ipairs(theme_spec) do
if spec[1] and spec[1] ~= "LazyVim/LazyVim" then
theme_plugin_name = spec.name or spec[1]
break
end
end
-- Clear all highlight groups before applying new theme
vim.cmd("highlight clear")
if vim.fn.exists("syntax_on") then
vim.cmd("syntax reset")
end
-- Reset background to default so colorscheme can set it properly (light themes will set to light)
vim.o.background = "dark"
-- Unload theme plugin modules to force full reload
if theme_plugin_name then
local plugin = require("lazy.core.config").plugins[theme_plugin_name]
if plugin then
-- Unload all lua modules from the plugin directory
local plugin_dir = plugin.dir .. "/lua"
require("lazy.core.util").walkmods(plugin_dir, function(modname)
package.loaded[modname] = nil
package.preload[modname] = nil
end)
end
end
-- Find and apply the new colorscheme
for _, spec in ipairs(theme_spec) do
if spec[1] == "LazyVim/LazyVim" and spec.opts and spec.opts.colorscheme then
local colorscheme = spec.opts.colorscheme
-- Load the colorscheme plugin. If it's already loaded (old and new
-- theme sharing the same plugin, e.g. generic themes on aether.nvim),
-- lazy won't rerun setup() on a spec reload and keeps the old
-- resolved opts in the plugin's property cache, so fully reload it
-- to reapply setup() with the new theme's opts.
local theme_plugin = theme_plugin_name and require("lazy.core.config").plugins[theme_plugin_name]
if theme_plugin and theme_plugin._.loaded then
require("lazy.core.loader").reload(theme_plugin)
else
require("lazy.core.loader").colorscheme(colorscheme)
end
vim.defer_fn(function()
-- Apply the colorscheme (it will set background itself)
pcall(vim.cmd.colorscheme, colorscheme)
-- Force redraw to update all UI elements
vim.cmd("redraw!")
-- Reload transparency settings
if vim.fn.filereadable(transparency_file) == 1 then
vim.defer_fn(function()
vim.cmd.source(transparency_file)
-- Trigger UI updates for various plugins
vim.api.nvim_exec_autocmds("ColorScheme", { modeline = false })
vim.api.nvim_exec_autocmds("VimEnter", { modeline = false })
-- Final redraw
vim.cmd("redraw!")
end, 5)
end
end, 5)
break
end
end
end)
end,
})
end,
},
}