diff --git a/nvim/after/plugin/lualine.lua b/nvim/after/plugin/lualine.lua index a51040d..693b798 100644 --- a/nvim/after/plugin/lualine.lua +++ b/nvim/after/plugin/lualine.lua @@ -1,18 +1,8 @@ -- https://github.com/nvim-lualine/lualine.nvim -local theme = require("lualine.themes.auto") - -theme.normal.c.bg = "#1F2335" -theme.normal.b.bg = "#24283B" -theme.insert.b.bg = "#24283B" -theme.visual.b.bg = "#24283B" -theme.replace.b.bg = "#24283B" -theme.command.b.bg = "#24283B" -theme.inactive.b.bg = "#24283B" - require("lualine").setup({ options = { icons_enabled = true, - theme = theme, + theme = "transparent", component_separators = { left = "", right = "" }, section_separators = { left = "", right = "" }, disabled_filetypes = { "alpha", "dashboard", "NvimTree", "Outline " }, diff --git a/nvim/lua/lualine/themes/custom.lua b/nvim/lua/lualine/themes/custom.lua new file mode 100644 index 0000000..8323268 --- /dev/null +++ b/nvim/lua/lualine/themes/custom.lua @@ -0,0 +1,177 @@ +-- Copyright (c) 2020-2021 shadmansaleh +-- MIT license, see LICENSE for more details. +local utils = require("lualine.utils.utils") +local loader = require("lualine.utils.loader") + +local custom = { + A = "#1F2335", + B = "#24283B", +} + +local color_name = vim.g.colors_name +if color_name then + -- All base16 colorschemes share the same theme + if "base16" == color_name:sub(1, 6) then + color_name = "base16" + end + + -- Check if there's a theme for current colorscheme + -- If there is load that instead of generating a new one + local ok, theme = pcall(loader.load_theme, color_name) + if ok and theme then + return theme + end +end + +--------------- +-- Constants -- +--------------- +-- fg and bg must have this much contrast range 0 < contrast_threshold < 0.5 +local contrast_threshold = 0.3 +-- how much brightness is changed in percentage for light and dark themes +local brightness_modifier_parameter = 10 + +-- Turns #rrggbb -> { red, green, blue } +local function 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 +local function 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 +local function get_color_brightness(rgb_color) + local color = 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 +local function get_color_avg(rgb_color) + local color = rgb_str2num(rgb_color) + return (color.red + color.green + color.blue) / 3 / 256 +end + +-- Clamps the val between left and right +local function 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 +local function brightness_modifier(rgb_color, parcentage) + local color = rgb_str2num(rgb_color) + color.red = clamp(color.red + (color.red * parcentage / 100), 0, 255) + color.green = clamp(color.green + (color.green * parcentage / 100), 0, 255) + color.blue = clamp(color.blue + (color.blue * parcentage / 100), 0, 255) + return rgb_num2str(color) +end + +-- Changes contrast of rgb_color by amount +local function contrast_modifier(rgb_color, amount) + local color = rgb_str2num(rgb_color) + color.red = clamp(color.red + amount, 0, 255) + color.green = clamp(color.green + amount, 0, 255) + color.blue = clamp(color.blue + amount, 0, 255) + return rgb_num2str(color) +end + +-- Changes brightness of foreground color to achieve contrast +-- without changing the color +local function apply_contrast(highlight) + local hightlight_bg_avg = get_color_avg(highlight.bg) + local contrast_threshold_config = clamp(contrast_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(get_color_avg(highlight.fg) - hightlight_bg_avg) < contrast_threshold_config and iteration_count < 25 do + highlight.fg = contrast_modifier(highlight.fg, contranst_change_step) + iteration_count = iteration_count + 1 + end +end + +-- Get the colors to create theme +-- stylua: ignore +local colors = { + normal = utils.extract_color_from_hllist('bg', { 'PmenuSel', 'PmenuThumb', 'TabLineSel' }, '#000000'), + insert = utils.extract_color_from_hllist('fg', { 'String', 'MoreMsg' }, '#000000'), + replace = utils.extract_color_from_hllist('fg', { 'Number', 'Type' }, '#000000'), + visual = utils.extract_color_from_hllist('fg', { 'Special', 'Boolean', 'Constant' }, '#000000'), + command = utils.extract_color_from_hllist('fg', { 'Identifier' }, '#000000'), + back1 = utils.extract_color_from_hllist('bg', { 'Normal', 'StatusLineNC' }, '#000000'), + fore = utils.extract_color_from_hllist('fg', { 'Normal', 'StatusLine' }, '#000000'), + back2 = utils.extract_color_from_hllist('bg', { 'StatusLine' }, '#000000'), +} + +-- Change brightness of colors +-- Darken if light theme (or) Lighten if dark theme +local normal_color = utils.extract_highlight_colors("Normal", "bg") +if normal_color ~= nil then + if get_color_brightness(normal_color) > 0.5 then + brightness_modifier_parameter = -brightness_modifier_parameter + end + for name, color in pairs(colors) do + colors[name] = brightness_modifier(color, brightness_modifier_parameter) + end +end + +-- Basic theme definition +local M = { + normal = { + a = { bg = colors.normal, fg = colors.back1, gui = "bold" }, + b = { bg = custom.B, fg = colors.normal }, + c = { bg = custom.A, fg = colors.fore }, + }, + insert = { + a = { bg = colors.insert, fg = colors.back1, gui = "bold" }, + b = { bg = custom.B, fg = colors.insert }, + c = { bg = colors.back2, fg = colors.fore }, + }, + replace = { + a = { bg = colors.replace, fg = colors.back1, gui = "bold" }, + b = { bg = custom.B, fg = colors.replace }, + c = { bg = colors.back2, fg = colors.fore }, + }, + visual = { + a = { bg = colors.visual, fg = colors.back1, gui = "bold" }, + b = { bg = custom.B, fg = colors.visual }, + c = { bg = colors.back2, fg = colors.fore }, + }, + command = { + a = { bg = colors.command, fg = colors.back1, gui = "bold" }, + b = { bg = custom.B, fg = colors.command }, + c = { bg = colors.back2, fg = colors.fore }, + }, +} + +M.terminal = M.command +M.inactive = M.normal + +-- Apply proper contrast so text is readable +for _, section in pairs(M) do + for _, highlight in pairs(section) do + apply_contrast(highlight) + end +end + +return M diff --git a/nvim/lua/lualine/themes/transparent.lua b/nvim/lua/lualine/themes/transparent.lua new file mode 100644 index 0000000..98e357b --- /dev/null +++ b/nvim/lua/lualine/themes/transparent.lua @@ -0,0 +1,42 @@ +local colors = { + white = "#ffffff", + blue = "#88A1BB", + green = "#b7d670", + magenta = "#a889d2", + orange = "#fd9f4d", + yellow = "#f3fa9b", + transparent = "None", +} + +return { + normal = { + a = { bg = colors.transparent, fg = colors.blue, gui = "bold" }, + b = { bg = colors.transparent, fg = colors.white }, + c = { bg = colors.transparent, fg = colors.white }, + }, + insert = { + a = { bg = colors.transparent, fg = colors.green, gui = "bold" }, + b = { bg = colors.transparent, fg = colors.white }, + c = { bg = colors.transparent, fg = colors.white }, + }, + visual = { + a = { bg = colors.transparent, fg = colors.magenta, gui = "bold" }, + b = { bg = colors.transparent, fg = colors.white }, + c = { bg = colors.transparent, fg = colors.white }, + }, + replace = { + a = { bg = colors.transparent, fg = colors.orange, gui = "bold" }, + b = { bg = colors.transparent, fg = colors.white }, + c = { bg = colors.transparent, fg = colors.white }, + }, + command = { + a = { bg = colors.transparent, fg = colors.yellow, gui = "bold" }, + b = { bg = colors.transparent, fg = colors.white }, + c = { bg = colors.transparent, fg = colors.white }, + }, + inactive = { + a = { bg = colors.transparent, fg = colors.white, gui = "bold" }, + b = { bg = colors.transparent, fg = colors.white }, + c = { bg = colors.transparent, fg = colors.white }, + }, +}