141 lines
4.1 KiB
Lua
141 lines
4.1 KiB
Lua
-- Source: https://github.com/nvim-lualine/lualine.nvim/blob/master/lua/lualine/themes/auto.lua
|
|
-- Copyright (c) 2020-2021 shadmansaleh
|
|
-- MIT license, see LICENSE for more details.
|
|
local M = {}
|
|
|
|
-- Turns #rrggbb -> { red, green, blue }
|
|
function M.rgb_str2num(rgb_color_str)
|
|
if rgb_color_str:find('#') == 1 then
|
|
rgb_color_str = rgb_color_str:sub(2, #rgb_color_str)
|
|
end
|
|
local red = tonumber(rgb_color_str:sub(1, 2), 16)
|
|
local green = tonumber(rgb_color_str:sub(3, 4), 16)
|
|
local blue = tonumber(rgb_color_str:sub(5, 6), 16)
|
|
return { red = red, green = green, blue = blue }
|
|
end
|
|
|
|
-- Turns { red, green, blue } -> #rrggbb
|
|
function M.rgb_num2str(rgb_color_num)
|
|
local rgb_color_str = string.format(
|
|
'#%02x%02x%02x',
|
|
rgb_color_num.red,
|
|
rgb_color_num.green,
|
|
rgb_color_num.blue
|
|
)
|
|
return rgb_color_str
|
|
end
|
|
|
|
-- Returns brightness level of color in range 0 to 1
|
|
-- arbitrary value it's basically an weighted average
|
|
function M.get_color_brightness(rgb_color)
|
|
local color = M.rgb_str2num(rgb_color)
|
|
local brightness = (color.red * 2 + color.green * 3 + color.blue) / 6
|
|
return brightness / 256
|
|
end
|
|
|
|
-- returns average of colors in range 0 to 1
|
|
-- used to determine contrast level
|
|
function M.get_color_avg(rgb_color)
|
|
local color = M.rgb_str2num(rgb_color)
|
|
return (color.red + color.green + color.blue) / 3 / 256
|
|
end
|
|
|
|
-- Clamps the val between left and right
|
|
function M.clamp(val, left, right)
|
|
if val > right then
|
|
return right
|
|
end
|
|
if val < left then
|
|
return left
|
|
end
|
|
return val
|
|
end
|
|
|
|
-- Changes brightness of rgb_color by percentage
|
|
function M.brightness_modifier(rgb_color, parcentage)
|
|
local color = M.rgb_str2num(rgb_color)
|
|
color.red = M.clamp(color.red + (color.red * parcentage / 100), 0, 255)
|
|
color.green = M.clamp(color.green + (color.green * parcentage / 100), 0, 255)
|
|
color.blue = M.clamp(color.blue + (color.blue * parcentage / 100), 0, 255)
|
|
return M.rgb_num2str(color)
|
|
end
|
|
|
|
-- Changes contrast of rgb_color by amount
|
|
function M.contrast_modifier(rgb_color, amount)
|
|
local color = M.rgb_str2num(rgb_color)
|
|
color.red = M.clamp(color.red + amount, 0, 255)
|
|
color.green = M.clamp(color.green + amount, 0, 255)
|
|
color.blue = M.clamp(color.blue + amount, 0, 255)
|
|
return M.rgb_num2str(color)
|
|
end
|
|
|
|
-- Changes brightness of foreground color to achieve contrast
|
|
-- without changing the color
|
|
function M.apply_contrast(highlight, threshold)
|
|
local hightlight_bg_avg = M.get_color_avg(highlight.bg)
|
|
local contrast_threshold_config = M.clamp(threshold, 0, 0.5)
|
|
local contranst_change_step = 5
|
|
if hightlight_bg_avg > 0.5 then
|
|
contranst_change_step = -contranst_change_step
|
|
end
|
|
|
|
-- Don't waste too much time here max 25 iteration should be more than enough
|
|
local iteration_count = 1
|
|
while
|
|
math.abs(M.get_color_avg(highlight.fg) - hightlight_bg_avg)
|
|
< contrast_threshold_config
|
|
and iteration_count < 25
|
|
do
|
|
highlight.fg = M.contrast_modifier(highlight.fg, contranst_change_step)
|
|
iteration_count = iteration_count + 1
|
|
end
|
|
end
|
|
|
|
-- Change brightness of colors
|
|
-- Darken if light theme (or) Lighten if dark theme
|
|
function M.apply_brightness(color, base_color, brightness_modifier_parameter)
|
|
if base_color ~= nil then
|
|
if M.get_color_brightness(base_color) > 0.5 then
|
|
brightness_modifier_parameter = -brightness_modifier_parameter
|
|
end
|
|
return M.brightness_modifier(color, brightness_modifier_parameter)
|
|
end
|
|
end
|
|
|
|
-- Assorted highlight helpers
|
|
--
|
|
|
|
local has_nvim9 = vim.fn.has('nvim-0.9') == 1
|
|
|
|
-- Retrieves color value from highlight group names.
|
|
-- First present highlight is returned
|
|
---@param scope string
|
|
---@param highlights table
|
|
---@param default string?
|
|
---@return string|nil
|
|
function M.get_color(scope, highlights, default)
|
|
for _, hl_name in ipairs(highlights) do
|
|
local hl
|
|
if has_nvim9 then
|
|
hl = vim.api.nvim_get_hl(0, { name = hl_name })
|
|
else
|
|
---@diagnostic disable-next-line: deprecated
|
|
hl = vim.api.nvim_get_hl_by_name(hl_name, true)
|
|
hl.fg, hl.bg, hl.sp = hl.foreground, hl.background, hl.special
|
|
end
|
|
if hl.reverse then
|
|
if scope == 'bg' then
|
|
scope = 'fg'
|
|
elseif scope == 'fg' then
|
|
scope = 'bg'
|
|
end
|
|
end
|
|
if hl[scope] then
|
|
return string.format('#%06x', hl[scope])
|
|
end
|
|
end
|
|
return default
|
|
end
|
|
|
|
return M
|