From c237ab1dff5ec7bd7b80dc21535e4875b7194481 Mon Sep 17 00:00:00 2001 From: rootiest Date: Wed, 11 Dec 2024 14:43:06 -0500 Subject: [PATCH] feat: implement custom status column with gradient highlights --- lua/config/statuscolumn.lua | 106 ++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 lua/config/statuscolumn.lua diff --git a/lua/config/statuscolumn.lua b/lua/config/statuscolumn.lua new file mode 100644 index 0000000..1ceaf6a --- /dev/null +++ b/lua/config/statuscolumn.lua @@ -0,0 +1,106 @@ +-- Setup gradient line number column + +-- Table to hold hex color values for easy reference +local colors = { + statusLineNrCurrent = "#b3befe", + statusLineNrDefault = "#444659", + fallbackColor = "#808080" -- Fallback gray if the group doesn't exist +} + +--- Calculate a color gradient between two colors. +-- @param base_color (string) The starting color in hex format (e.g., '#RRGGBB'). +-- @param target_color (string) The ending color in hex format (e.g., '#RRGGBB'). +-- @param max_steps (number) The total number of steps in the gradient. +-- @param step (number) The current step in the gradient. +-- @return (string) The interpolated color in hex format. +local function calculate_gradient(base_color, target_color, max_steps, step) + -- Parse the base and target colors into RGB components + local br, bg, bb = + tonumber(base_color:sub(2, 3), 16), + tonumber(base_color:sub(4, 5), 16), + tonumber(base_color:sub(6, 7), 16) + + local tr, tg, tb = + tonumber(target_color:sub(2, 3), 16), + tonumber(target_color:sub(4, 5), 16), + tonumber(target_color:sub(6, 7), 16) + + -- Calculate the blending factor + local factor = step / max_steps + + -- Interpolate between the base and target colors based on the blending factor + local r = math.floor(br + (tr - br) * factor) + local g = math.floor(bg + (tg - bg) * factor) + local b = math.floor(bb + (tb - bb) * factor) + + return string.format('#%02X%02X%02X', r, g, b) -- Return the new color as a string +end + +--- Get the foreground color of a highlight group. +-- @param group (string) The name of the highlight group. +-- @return (string) The foreground color in hex format or a fallback gray color. +local function get_highlight_fg(group) + local hl = vim.api.nvim_get_hl(0, { name = group }) + if hl and hl.fg then + return string.format('#%06X', hl.fg) -- Convert the integer color to hex + else + return colors.fallbackColor -- Use fallback gray if the group doesn't exist + end +end + +--- Set up gradient highlights for a specified group. +-- @param base_color (string) The starting color for the gradient. +-- @param group_name_prefix (string) The prefix for the highlight group names. +-- @param max_steps (number) The total number of steps for the gradient. +local function setup_gradient_highlights(base_color, group_name_prefix, max_steps) + local target_color = get_highlight_fg('StatusLineNrDefault') -- Get the default color for interpolation + for step = 1, max_steps do + local color = calculate_gradient(base_color, target_color, max_steps, step) -- Get the gradient color + vim.api.nvim_set_hl( + 0, + group_name_prefix .. step, + { fg = color, bg = 'NONE' } -- Set the highlight with foreground color and no background + ) + end +end + +-- Define highlight groups for current and default status line numbers +vim.api.nvim_set_hl(0, 'StatusLineNrCurrent', { fg = colors.statusLineNrCurrent, bg = 'NONE', bold = true }) +vim.api.nvim_set_hl(0, 'StatusLineNrDefault', { fg = colors.statusLineNrDefault, bg = 'NONE' }) + +-- Set up gradient highlights for lines above and below the cursor +setup_gradient_highlights(colors.statusLineNrCurrent, 'StatusLineNrAbove', 10) +setup_gradient_highlights(colors.statusLineNrCurrent, 'StatusLineNrBelow', 10) + +-- Custom status column for displaying line number gradients +_G.CustomStatusColumn = function() + local lnum = vim.v.lnum -- Current line number + local cursor_lnum = vim.fn.line('.') -- Current cursor line number + local max_gradient_steps = 10 -- Maximum steps in gradient + + -- Use the plugin's original status column + local original_statuscolumn = require('snacks.statuscolumn').get() + + -- Highlight for the current line + if lnum == cursor_lnum then + return '%#StatusLineNrCurrent#' .. original_statuscolumn .. '%*' + end + + -- Highlight for lines above the cursor + if lnum < cursor_lnum and (cursor_lnum - lnum) <= max_gradient_steps then + local step = cursor_lnum - lnum + return '%#StatusLineNrAbove' .. step .. '#' .. original_statuscolumn .. '%*' + end + + -- Highlight for lines below the cursor + if lnum > cursor_lnum and (lnum - cursor_lnum) <= max_gradient_steps then + local step = lnum - cursor_lnum + return '%#StatusLineNrBelow' .. step .. '#' .. original_statuscolumn .. '%*' + end + + -- Default case for other lines + return '%#StatusLineNrDefault#' .. original_statuscolumn .. '%*' +end + +-- Set the custom status column to be used +vim.o.statuscolumn = [[%!v:lua.CustomStatusColumn()]]