farout.nvim/lua/tokyonight/util.lua

331 lines
9.0 KiB
Lua
Raw Normal View History

local hsluv = require("tokyonight.hsluv")
2021-04-17 19:22:55 +00:00
local util = {}
2021-04-19 12:39:35 +00:00
util.colorsUsed = {}
2021-04-24 20:24:40 +00:00
util.colorCache = {}
2021-04-19 12:39:35 +00:00
util.bg = "#000000"
util.fg = "#ffffff"
util.day_brightness = 0.3
2021-04-19 12:39:35 +00:00
local function hexToRgb(hex_str)
2021-04-17 19:22:55 +00:00
local hex = "[abcdef0-9][abcdef0-9]"
local pat = "^#(" .. hex .. ")(" .. hex .. ")(" .. hex .. ")$"
hex_str = string.lower(hex_str)
assert(string.find(hex_str, pat) ~= nil, "hex_to_rgb: invalid hex_str: " .. tostring(hex_str))
local r, g, b = string.match(hex_str, pat)
2021-04-19 12:39:35 +00:00
return { tonumber(r, 16), tonumber(g, 16), tonumber(b, 16) }
end
2021-04-20 09:58:45 +00:00
---@param fg string foreground color
---@param bg string background color
---@param alpha number number between 0 and 1. 0 results in bg, 1 results in fg
function util.blend(fg, bg, alpha)
2021-04-19 12:39:35 +00:00
bg = hexToRgb(bg)
2021-04-19 18:43:20 +00:00
fg = hexToRgb(fg)
2021-04-17 19:22:55 +00:00
2021-04-19 18:43:20 +00:00
local blendChannel = function(i)
2021-05-12 09:19:28 +00:00
local ret = (alpha * fg[i] + ((1 - alpha) * bg[i]))
return math.floor(math.min(math.max(0, ret), 255) + 0.5)
2021-04-17 19:22:55 +00:00
end
2021-04-19 18:43:20 +00:00
return string.format("#%02X%02X%02X", blendChannel(1), blendChannel(2), blendChannel(3))
2021-04-17 19:22:55 +00:00
end
2021-05-12 09:19:28 +00:00
function util.darken(hex, amount, bg)
return util.blend(hex, bg or util.bg, math.abs(amount))
end
function util.lighten(hex, amount, fg)
return util.blend(hex, fg or util.fg, math.abs(amount))
end
2021-04-17 19:22:55 +00:00
function util.brighten(color, percentage)
local hsl = hsluv.hex_to_hsluv(color)
local larpSpace = 100 - hsl[3]
2021-05-12 09:19:28 +00:00
if percentage < 0 then
larpSpace = hsl[3]
end
hsl[3] = hsl[3] + larpSpace * percentage
return hsluv.hsluv_to_hex(hsl)
end
function util.invertColor(color)
2021-04-24 20:24:40 +00:00
if color ~= "NONE" then
2021-05-09 15:45:05 +00:00
local hsl = hsluv.hex_to_hsluv(color)
hsl[3] = 100 - hsl[3]
2021-05-12 09:19:28 +00:00
if hsl[3] < 40 then
hsl[3] = hsl[3] + (100 - hsl[3]) * util.day_brightness
2021-05-12 09:19:28 +00:00
end
2021-05-09 15:45:05 +00:00
return hsluv.hsluv_to_hex(hsl)
end
return color
end
function util.randomColor(color)
if color ~= "NONE" then
local hsl = hsluv.hex_to_hsluv(color)
hsl[1] = math.random(1, 360)
return hsluv.hsluv_to_hex(hsl)
2021-04-24 20:24:40 +00:00
end
return color
end
function util.getColor(color)
2021-05-12 09:19:28 +00:00
if vim.o.background == "dark" then
return color
end
if not util.colorCache[color] then
util.colorCache[color] = util.invertColor(color)
end
2021-04-24 20:24:40 +00:00
return util.colorCache[color]
end
2021-05-09 15:45:05 +00:00
-- local ns = vim.api.nvim_create_namespace("tokyonight")
function util.highlight(group, color)
2021-05-12 09:19:28 +00:00
if color.fg then
util.colorsUsed[color.fg] = true
end
if color.bg then
util.colorsUsed[color.bg] = true
end
if color.sp then
util.colorsUsed[color.sp] = true
end
2021-04-19 12:39:35 +00:00
2021-04-17 19:22:55 +00:00
local style = color.style and "gui=" .. color.style or "gui=NONE"
local fg = color.fg and "guifg=" .. util.getColor(color.fg) or "guifg=NONE"
local bg = color.bg and "guibg=" .. util.getColor(color.bg) or "guibg=NONE"
local sp = color.sp and "guisp=" .. util.getColor(color.sp) or ""
2021-04-23 06:48:26 +00:00
local hl = "highlight " .. group .. " " .. style .. " " .. fg .. " " .. bg .. " " .. sp
2021-05-09 15:45:05 +00:00
if color.link then
vim.cmd("highlight! link " .. group .. " " .. color.link)
else
-- local data = {}
-- if color.fg then data.foreground = color.fg end
-- if color.bg then data.background = color.bg end
-- if color.sp then data.special = color.sp end
-- if color.style then data[color.style] = true end
-- vim.api.nvim_set_hl(ns, group, data)
vim.cmd(hl)
end
2021-04-19 12:39:35 +00:00
end
function util.debug(colors)
colors = colors or require("tokyonight.colors")
-- Dump unused colors
for name, color in pairs(colors) do
if type(color) == "table" then
util.debug(color)
else
2021-05-12 09:19:28 +00:00
if util.colorsUsed[color] == nil then
print("not used: " .. name .. " : " .. color)
end
2021-04-19 12:39:35 +00:00
end
end
2021-04-17 19:22:55 +00:00
end
--- Delete the autocmds when the theme changes to something else
function util.onColorScheme()
if vim.g.colors_name ~= "tokyonight" then
2021-05-12 09:19:28 +00:00
vim.cmd([[autocmd! TokyoNight]])
vim.cmd([[augroup! TokyoNight]])
end
end
2021-04-20 10:19:20 +00:00
---@param config Config
function util.autocmds(config)
2021-05-12 09:19:28 +00:00
vim.cmd([[augroup TokyoNight]])
vim.cmd([[ autocmd!]])
vim.cmd([[ autocmd ColorScheme * lua require("tokyonight.util").onColorScheme()]])
2021-04-20 10:19:20 +00:00
if config.dev then
2021-05-12 09:19:28 +00:00
vim.cmd([[ autocmd BufWritePost */lua/tokyonight/** nested colorscheme tokyonight]])
2021-04-20 10:19:20 +00:00
end
for _, sidebar in ipairs(config.sidebars) do
if sidebar == "terminal" then
2021-05-12 09:19:28 +00:00
vim.cmd([[ autocmd TermOpen * setlocal winhighlight=Normal:NormalSB,SignColumn:SignColumnSB]])
2021-04-20 10:19:20 +00:00
else
2021-05-12 09:19:28 +00:00
vim.cmd([[ autocmd FileType ]] .. sidebar .. [[ setlocal winhighlight=Normal:NormalSB,SignColumn:SignColumnSB]])
2021-04-20 10:19:20 +00:00
end
end
2021-05-12 09:19:28 +00:00
vim.cmd([[augroup end]])
2021-04-20 10:19:20 +00:00
end
-- Simple string interpolation.
--
-- Example template: "${name} is ${value}"
--
---@param str string template string
---@param table table key value pairs to replace in the string
function util.template(str, table)
2021-05-12 09:19:28 +00:00
return (str:gsub("($%b{})", function(w)
return table[w:sub(3, -2)] or w
end))
2021-04-20 10:19:20 +00:00
end
2021-05-12 09:19:28 +00:00
function util.syntax(syntax)
for group, colors in pairs(syntax) do
util.highlight(group, colors)
end
end
2021-04-17 19:22:55 +00:00
---@param colors ColorScheme
function util.terminal(colors)
2021-04-20 09:58:45 +00:00
-- dark
vim.g.terminal_color_0 = colors.black
2021-04-20 09:58:45 +00:00
vim.g.terminal_color_8 = colors.terminal_black
-- light
vim.g.terminal_color_7 = colors.fg_dark
vim.g.terminal_color_15 = colors.fg
-- colors
2021-04-17 19:22:55 +00:00
vim.g.terminal_color_1 = colors.red
vim.g.terminal_color_9 = colors.red
2021-04-20 09:58:45 +00:00
vim.g.terminal_color_2 = colors.green
2021-04-17 19:22:55 +00:00
vim.g.terminal_color_10 = colors.green
2021-04-20 09:58:45 +00:00
vim.g.terminal_color_3 = colors.yellow
vim.g.terminal_color_11 = colors.yellow
vim.g.terminal_color_4 = colors.blue
2021-04-17 19:22:55 +00:00
vim.g.terminal_color_12 = colors.blue
2021-04-20 09:58:45 +00:00
vim.g.terminal_color_5 = colors.magenta
2021-04-17 19:22:55 +00:00
vim.g.terminal_color_13 = colors.magenta
2021-04-20 09:58:45 +00:00
vim.g.terminal_color_6 = colors.cyan
2021-04-17 19:22:55 +00:00
vim.g.terminal_color_14 = colors.cyan
2021-04-25 13:53:20 +00:00
if vim.o.background == "light" then
for i = 0, 15, 1 do
vim.g["terminal_color_" .. i] = util.getColor(vim.g["terminal_color_" .. i])
end
end
2021-04-17 19:22:55 +00:00
end
2021-05-02 08:43:18 +00:00
function util.light_colors(colors)
2021-05-12 09:19:28 +00:00
if type(colors) == "string" then
return util.getColor(colors)
end
2021-05-02 08:43:18 +00:00
local ret = {}
2021-05-12 09:19:28 +00:00
for key, value in pairs(colors) do
ret[key] = util.light_colors(value)
end
2021-05-02 08:43:18 +00:00
return ret
end
2021-04-17 19:22:55 +00:00
---@param theme Theme
function util.load(theme)
-- only needed to clear when not the default colorscheme
if vim.g.colors_name then
vim.cmd("hi clear")
end
2021-06-19 16:55:40 +00:00
-- if vim.fn.exists("syntax_on") then
-- vim.cmd("syntax reset")
-- end
2021-04-17 19:22:55 +00:00
vim.o.termguicolors = true
vim.g.colors_name = "tokyonight"
2021-05-09 15:45:05 +00:00
-- vim.api.nvim__set_hl_ns(ns)
2021-04-17 19:22:55 +00:00
-- load base theme
util.syntax(theme.base)
2021-06-19 16:55:40 +00:00
util.syntax(theme.plugins)
if theme.config.terminalColors then
util.terminal(theme.colors)
end
2021-06-19 16:55:40 +00:00
util.autocmds(theme.config)
vim.defer_fn(function()
util.syntax(theme.defer)
end, 100)
2021-04-17 19:22:55 +00:00
end
2021-04-23 18:21:12 +00:00
---@param config Config
---@param colors ColorScheme
function util.color_overrides(colors, config)
if type(config.colors) == "table" then
for key, value in pairs(config.colors) do
if not colors[key] then
error("Color " .. key .. " does not exist")
end
-- Patch: https://github.com/ful1e5/onedark.nvim/issues/6
if type(colors[key]) == "table" then
util.color_overrides(colors[key], { colors = value })
2021-04-23 18:21:12 +00:00
else
if value:lower() == "none" then
-- set to none
colors[key] = "NONE"
elseif string.sub(value, 1, 1) == "#" then
-- hex override
colors[key] = value
else
-- another group
if not colors[value] then
error("Color " .. value .. " does not exist")
end
colors[key] = colors[value]
2021-05-12 09:19:28 +00:00
end
2021-04-23 18:21:12 +00:00
end
2021-04-23 06:48:26 +00:00
end
end
end
function util.light(brightness)
2021-04-24 20:24:40 +00:00
for hl_name, hl in pairs(vim.api.nvim__get_hl_defs(0)) do
local def = {}
for key, def_key in pairs({ foreground = "fg", background = "bg", special = "sp" }) do
if type(hl[key]) == "number" then
local hex = string.format("#%06x", hl[key])
local color = util.invertColor(hex)
2021-05-12 09:19:28 +00:00
if brightness then
color = util.brighten(hex, brightness)
end
2021-04-24 20:24:40 +00:00
table.insert(def, "gui" .. def_key .. "=" .. color)
end
end
if hl_name ~= "" and #def > 0 then
for _, style in pairs({ "bold", "italic", "underline", "undercurl", "reverse" }) do
2021-05-12 09:19:28 +00:00
if hl[style] then
table.insert(def, "gui=" .. style)
end
2021-04-24 20:24:40 +00:00
end
vim.cmd("highlight! " .. hl_name .. " " .. table.concat(def, " "))
end
end
end
2021-05-09 15:45:05 +00:00
function util.random()
local colors = {}
for hl_name, hl in pairs(vim.api.nvim__get_hl_defs(0)) do
local def = {}
for key, def_key in pairs({ foreground = "fg", background = "bg", special = "sp" }) do
if type(hl[key]) == "number" then
local hex = string.format("#%06x", hl[key])
local color = colors[hex] and colors[hex] or util.randomColor(hex)
colors[hex] = color
table.insert(def, "gui" .. def_key .. "=" .. color)
end
end
if hl_name ~= "" and #def > 0 then
for _, style in pairs({ "bold", "italic", "underline", "undercurl", "reverse" }) do
2021-05-12 09:19:28 +00:00
if hl[style] then
table.insert(def, "gui=" .. style)
end
2021-05-09 15:45:05 +00:00
end
vim.cmd("highlight! " .. hl_name .. " " .. table.concat(def, " "))
end
end
end
2021-04-17 19:22:55 +00:00
return util