-- -- Color scheme, custom highlights & per-window highlight namespaces -- local solarized_colors = { base03 = "#002b36", base02 = "#073642", base01 = "#586e75", base00 = "#657b83", base0 = "#839496", base1 = "#93a1a1", base2 = "#eee8d5", base3 = "#fdf6e3", yellow = "#b58900", orange = "#cb4b16", red = "#dc322f", magenta = "#d33682", violet = "#6c71c4", blue = "#268bd2", cyan = "#2aa198", green = "#859900", -- solarized.nvim "mix" tints: subtle highlight backgrounds, theme-specific mix_base1 = "#2c4e56", -- dark (active cursor line) mix_blue_light = "#e7ebe1", -- light (active cursor line) mix_green = "#274c25", -- dark (inactive cursor line: muted green) mix_magenta_light = "#f8e2d9", -- light (inactive cursor line: muted pink) } -- Per-window highlight namespaces: one for the focused window, one for the -- unfocused windows. A window's active namespace decides its CursorLine color, -- which is how the focused window is made obvious. Both namespaces must define -- `dotfiles.Todo`: an extmark's hl_group is resolved against the window's -- active namespace and does NOT fall back to the global namespace, so the TODO -- highlight (placed in 50-extmarks.lua) only renders if the group exists in -- whichever namespace the window currently uses. local ns_active = vim.api.nvim_create_namespace("extmarks") local ns_inactive = vim.api.nvim_create_namespace("extmarks.inactive") local todo_hl = { bg = "Yellow", fg = "Black", bold = true } vim.api.nvim_set_hl(ns_active, "dotfiles.Todo", todo_hl) vim.api.nvim_set_hl(ns_inactive, "dotfiles.Todo", todo_hl) -- Publish the extmark storage namespace and TODO group name for 50-extmarks.lua. -- This file is named 40- (not 50-) so it is sourced before 50-extmarks.lua and -- the contract below exists when that file reads it. Preserve the existing -- `dotfiles` table (augroup). local dotfiles = vim.g.dotfiles dotfiles.todo_ns = ns_active dotfiles.todo_hl = "dotfiles.Todo" vim.g.dotfiles = dotfiles -- Custom highlights in the global namespace, independent of the per-window ones local function adjust_highlight() if vim.g.colors_name == "solarized" then vim.api.nvim_set_hl(0, "EndOfBuffer", { fg = solarized_colors.base0, update = true }) vim.api.nvim_set_hl(0, "MatchParen", { link = "CurSearch" }) vim.api.nvim_set_hl(0, "WinBarCwd", { fg = solarized_colors.blue, italic = true }) vim.api.nvim_set_hl(0, "WinBarFile", { italic = true }) local float = vim.o.background == "light" and { fg = solarized_colors.base01, bg = "#e0d2a8" } or { fg = solarized_colors.base2, bg = "#0d4f63" } vim.api.nvim_set_hl(0, "NormalFloat", float) local normal_bg = vim.api.nvim_get_hl(0, { name = "Normal", link = false }).bg local border_fg = vim.api.nvim_get_hl(0, { name = "FloatBorder", link = false }).fg vim.api.nvim_set_hl(0, "FloatBorder", { fg = border_fg, bg = normal_bg }) -- Popup menu (completion, etc.): match the editor background like floats do. vim.api.nvim_set_hl(0, "Pmenu", { fg = solarized_colors.base0, bg = normal_bg }) vim.api.nvim_set_hl(0, "PmenuSbar", { bg = normal_bg }) vim.api.nvim_set_hl(0, "TabLine", { fg = solarized_colors.yellow, bold = true }) if vim.o.background == "light" then vim.api.nvim_set_hl(0, "TabLineSel", { bg = "#edffd5", fg = solarized_colors.yellow, bold = true }) elseif vim.o.background == "dark" then vim.api.nvim_set_hl(0, "TabLineSel", { bg = "#043624" }) end end end -- Active and inactive cursorline highlight local function set_cursorline_hl() local accent = vim.o.background == "light" and solarized_colors.mix_blue_light or solarized_colors.mix_base1 vim.api.nvim_set_hl(ns_active, "CursorLine", { bg = accent }) vim.api.nvim_set_hl(ns_active, "CursorLineNr", { bg = accent }) vim.api.nvim_set_hl(ns_inactive, "CursorLine", { bg = accent, underline = true }) vim.api.nvim_set_hl(ns_inactive, "CursorLineNr", { bg = accent, underline = true }) end local function apply_highlights() adjust_highlight() set_cursorline_hl() end local function is_normal_win(win) return vim.api.nvim_win_is_valid(win) and vim.api.nvim_win_get_config(win).relative == "" end local function update_focus_ns() local cur = vim.api.nvim_get_current_win() -- Focus in a floating window (completion, hover, ...) must not recolor the split underneath; leave every window as -- it is. if not is_normal_win(cur) then return end for _, win in ipairs(vim.api.nvim_list_wins()) do if is_normal_win(win) then vim.api.nvim_win_set_hl_ns(win, (win == cur) and ns_active or ns_inactive) end end end local function next_colorscheme() local colorschemes = vim.fn.getcompletion("", "color") vim.g.colors_name = vim.g.colors_name or "default" for i = 1, #colorschemes do if colorschemes[i] == vim.g.colors_name then vim.cmd.colorscheme(colorschemes[(i % #colorschemes) + 1]) vim.notify("Color scheme set to " .. vim.g.colors_name) return end end end local function random_colorscheme() local colorschemes = vim.fn.getcompletion("", "color") vim.cmd.colorscheme(colorschemes[math.random(#colorschemes)]) vim.notify("Color scheme set to " .. vim.g.colors_name) end local function toggle_theme() vim.opt.background = vim.o.background == "light" and "dark" or "light" vim.notify("Color theme set to " .. vim.o.background) end -- Reapply custom highlights after the colorscheme loads and on theme change vim.api.nvim_create_autocmd("ColorScheme", { desc = "Reapply custom highlights", group = vim.g.dotfiles.augroup, callback = apply_highlights, }) vim.api.nvim_create_autocmd("OptionSet", { desc = "Reapply custom highlights on theme change", pattern = "background", group = vim.g.dotfiles.augroup, callback = apply_highlights, }) -- Keep the focused/unfocused cursor line correct as windows and focus change vim.api.nvim_create_autocmd( { "VimEnter", "WinEnter", "WinNew", "WinClosed", "TabEnter", "SessionLoadPost", "FileType" }, { desc = "Track the focused window for the cursor line", group = vim.g.dotfiles.augroup, callback = function() -- Defer so the window list and current window have settled. vim.schedule(update_focus_ns) end, } ) vim.cmd.colorscheme("solarized") -- Default colorscheme vim.opt.background = "dark" -- Default theme apply_highlights() vim.api.nvim_create_user_command("ColorsNext", next_colorscheme, { desc = "Load next color scheme" }) vim.api.nvim_create_user_command("ColorsRandom", random_colorscheme, { desc = "Load random color scheme" }) vim.api.nvim_create_user_command("ColorsToggle", toggle_theme, { desc = "Toggle light/dark theme" })