最近我的hyprland主题一直在使用end-4做的dotfile:illogical-impulse(下面简称ii),基于Quickshell实现,虽然后台占用是大,但是我用起来非常流畅,内存不拿来用不就是浪费吗~
遇到的一个问题是, 当切换主题的日夜间模式时, neonvim的主题并不会切换,如果就用neonvim主题配置中的transparent_background = false,即背景透明,会导致在ii生成的颜色配置在直接反转颜色后很不好看,于是想着通过配置neovim的主题文件来实现自动切换。
实现的效果
🎨 自动切换
- 启动时检测:Neovim 启动时自动检测当前桌面环境的深浅色模式
- 匹配主题:
- 浅色模式 → 自动应用 Catppuccin Latte(浅色主题)
- 深色模式 → 自动应用 Catppuccin Mocha(深色主题)
- 视觉统一:编辑器主题与 Quickshell 生成的 Material Design 3 终端颜色相协调
🎯 手动切换
- 快捷键切换:
<leader>tl- 强制切换到浅色主题<leader>td- 强制切换到深色主题
- 命令行控制:
:ThemeLight- 切换到浅色主题:ThemeDark- 切换到深色主题
原理
🔍 检测
数据源:读取 Quickshell 生成的颜色配置文件
- 位置:
~/.local/state/quickshell/user/generated/colors.json
- 位置:
亮度计算:
LUA-- 提取背景色(如 #f6fafe 或 #101417) local r = tonumber(hex:sub(1, 2), 16) or 0 local g = tonumber(hex:sub(3, 4), 16) or 0 local b = tonumber(hex:sub(5, 6), 16) or 0 -- 使用 ITU-R BT.709 标准计算相对亮度 local brightness = (r * 299 + g * 587 + b * 114) / 1000判断逻辑:
brightness > 128→ 浅色环境 →vim.o.background = "light"brightness ≤ 128→ 深色环境 →vim.o.background = "dark"
⚙️ Neovim 内部
background 选项:
- Neovim 内置选项,用于告知主题当前环境类型
主题响应:
LUAbackground = { light = "latte", -- vim.o.background = "light" 时使用 dark = "mocha", -- vim.o.background = "dark" 时使用 },自动监听:使用
OptionSetautocmd 监听background选项变化,实时切换主题
🔄 工作流程
Quickshell 切换日夜模式
↓
更新 colors.json 文件
↓
Neovim 启动时读取文件
↓
计算背景色亮度
↓
设置 vim.o.background
↓
触发主题自动切换
以下是我的./.config/nvim/lua/plugins/catppuccin.lua主题文件的配置,可作参考:
LUA
return {
"catppuccin/nvim",
name = "catppuccin",
priority = 1000,
config = function()
require("catppuccin").setup({
background = {
light = "latte", -- 浅色环境使用 latte
dark = "mocha", -- 深色环境使用 mocha
},
transparent_background = false, -- 建议false
show_end_of_buffer = false,
term_colors = false,
dim_inactive = {
enabled = false,
shade = "dark",
percentage = 0.15,
},
styles = {
comments = { "italic" },
conditionals = { "italic" },
loops = {},
functions = {},
keywords = {},
strings = {},
variables = {},
},
integrations = {
cmp = true,
gitsigns = true,
nvimtree = true,
treesitter = true,
telescope = true,
-- 根据你的插件添加更多集成
},
})
-- 主题检测(可选 - 适配你的桌面环境)
local function detect_system_theme()
-- 示例:检查系统配置文件
local theme_file = vim.fn.expand("~/.local/state/quickshell/user/generated/colors.json")
if vim.fn.filereadable(theme_file) == 1 then
local success, content = pcall(vim.fn.readfile, theme_file)
if success then
local text = table.concat(content, "\n")
local bg_color = text:match('"background":%s*"(#[%w]+)"')
if bg_color then
-- 计算颜色亮度
local hex = bg_color:gsub("#", "")
local r = tonumber(hex:sub(1, 2), 16) or 0
local g = tonumber(hex:sub(3, 4), 16) or 0
local b = tonumber(hex:sub(5, 6), 16) or 0
local brightness = (r * 299 + g * 587 + b * 114) / 1000
vim.o.background = brightness > 128 and "light" or "dark"
return true
end
end
end
return false
end
-- 根据 background 选项应用对应主题
local function apply_theme()
if vim.o.background == "dark" then
vim.cmd.colorscheme("catppuccin-mocha")
else
vim.cmd.colorscheme("catppuccin-latte")
end
end
-- 初始化
if not detect_system_theme() then
-- 如果检测失败,使用默认设置
vim.o.background = "light" -- 或 "dark",根据个人偏好
end
apply_theme()
-- 监听 background
vim.api.nvim_create_autocmd("OptionSet", {
pattern = "background",
callback = apply_theme,
})
-- 手动切换
vim.api.nvim_create_user_command('ThemeLight', function()
vim.o.background = "light"
end, { desc = '切换到浅色主题' })
vim.api.nvim_create_user_command('ThemeDark', function()
vim.o.background = "dark"
end, { desc = '切换到深色主题' })
-- 快捷键(可选)
vim.keymap.set('n', '<leader>tl', ':ThemeLight<CR>', { desc = '浅色主题' })
vim.keymap.set('n', '<leader>td', ':ThemeDark<CR>', { desc = '深色主题' })
end,
}
注意事项
⚠️ 配置文件路径依赖
Quickshell 数据路径:
- 当前路径:
~/.local/state/quickshell/user/generated/colors.json - 如果 Quickshell 配置更改了数据生成路径,需要同步更新 Neovim 配置中的路径
### 🔧 配置维护
- 主题优先级:
- Catppuccin 设置为
priority = 1000,确保在其他主题之前加载 - Github-theme 设为
lazy = true,避免冲突
- 备用机制:
- 如果颜色文件读取失败,默认设置为浅色模式
- 保留手动切换功能作为备用选项
🐛 故障排除
主题不切换:
- 检查
colors.json文件是否存在和可读 - 在 Neovim 中运行
:echo vim.o.background查看检测结果 - 使用
:messages查看是否有错误信息
- 检查
颜色不协调:
- 检查透明背景设置:
transparent_background = false - 确认终端颜色序列正常:
cat ~/.local/state/quickshell/user/generated/terminal/sequences.txt
- 检查透明背景设置:
手动测试:
LUA-- 在 Neovim 中测试 :lua print(vim.fn.expand("~/.local/state/quickshell/user/generated/colors.json")) :lua print(vim.fn.filereadable(vim.fn.expand("~/.local/state/quickshell/user/generated/colors.json")))
📂 相关文件位置
- Neovim 主题配置:
~/.config/nvim/lua/plugins/catppuccin.lua - Quickshell 颜色数据:
~/.local/state/quickshell/user/generated/colors.json - 终端颜色序列:
~/.local/state/quickshell/user/generated/terminal/sequences.txt - Quickshell 主配置:
~/.config/illogical-impulse/config.json
我的环境:Arch Linux + Hyprland +illogical-impulse(dot-file) + Neovim + LazyVim