diff options
author | Akianonymus <anonymus.aki@gmail.com> | 2022-09-15 10:00:00 +0530 |
---|---|---|
committer | Akianonymus <anonymus.aki@gmail.com> | 2022-09-15 13:51:38 +0530 |
commit | cf4f33f5ea34f9c4e9975299b094f1a2b8b34aa0 (patch) | |
tree | 3f2558419b2643ac7af8f4abe8e67db478d64309 /lua/colorizer/color_utils.lua | |
parent | fix(gitignore) Add doc/tags to .gitignore (diff) |
Better structure and naming | Misc improvements
Diffstat (limited to 'lua/colorizer/color_utils.lua')
-rw-r--r-- | lua/colorizer/color_utils.lua | 411 |
1 files changed, 0 insertions, 411 deletions
diff --git a/lua/colorizer/color_utils.lua b/lua/colorizer/color_utils.lua deleted file mode 100644 index 2a7e7ab..0000000 --- a/lua/colorizer/color_utils.lua +++ /dev/null @@ -1,411 +0,0 @@ ----Helper functions to parse different colour formats ---@module colorizer.color_utils -local Trie = require "colorizer.trie" - -local utils = require "colorizer.utils" -local byte_is_alphanumeric = utils.byte_is_alphanumeric -local byte_is_hex = utils.byte_is_hex -local parse_hex = utils.parse_hex -local percent_or_hex = utils.percent_or_hex - -local bit = require "bit" -local floor, min, max = math.floor, math.min, math.max -local band, rshift, lshift, tohex = bit.band, bit.rshift, bit.lshift, bit.tohex - -local api = vim.api - ----Determine whether to use black or white text. --- --- ref: https://stackoverflow.com/a/1855903/837964 --- https://stackoverflow.com/questions/596216/formula-to-determine-brightness-of-rgb-color ----@param r number: Red ----@param g number: Green ----@param b number: Blue -local function color_is_bright(r, g, b) - -- counting the perceptive luminance - human eye favors green color - local luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255 - if luminance > 0.5 then - return true -- bright colors, black font - else - return false -- dark colors, white font - end -end - ----Convert hsl colour values to rgb. --- Source: https://gist.github.com/mjackson/5311256 ----@param p number ----@param q number ----@param t number ----@return number -local function hue_to_rgb(p, q, t) - if t < 0 then - t = t + 1 - end - if t > 1 then - t = t - 1 - end - if t < 1 / 6 then - return p + (q - p) * 6 * t - end - if t < 1 / 2 then - return q - end - if t < 2 / 3 then - return p + (q - p) * (2 / 3 - t) * 6 - end - return p -end - -local COLOR_MAP -local COLOR_TRIE -local COLOR_NAME_MINLEN, COLOR_NAME_MAXLEN -local COLOR_NAME_SETTINGS = { lowercase = true, strip_digits = false } -local TAILWIND_ENABLED = false ---- Grab all the colour values from `vim.api.nvim_get_color_map` and create a lookup table. --- COLOR_MAP is used to store the colour values ----@param line string: Line to parse ----@param i number: Index of line from where to start parsing ----@param opts table: Currently contains whether tailwind is enabled or not -local function color_name_parser(line, i, opts) - --- Setup the COLOR_MAP and COLOR_TRIE - if not COLOR_TRIE or opts.tailwind ~= TAILWIND_ENABLED then - COLOR_MAP = {} - COLOR_TRIE = Trie() - for k, v in pairs(api.nvim_get_color_map()) do - if not (COLOR_NAME_SETTINGS.strip_digits and k:match "%d+$") then - COLOR_NAME_MINLEN = COLOR_NAME_MINLEN and min(#k, COLOR_NAME_MINLEN) or #k - COLOR_NAME_MAXLEN = COLOR_NAME_MAXLEN and max(#k, COLOR_NAME_MAXLEN) or #k - local rgb_hex = tohex(v, 6) - COLOR_MAP[k] = rgb_hex - COLOR_TRIE:insert(k) - if COLOR_NAME_SETTINGS.lowercase then - local lowercase = k:lower() - COLOR_MAP[lowercase] = rgb_hex - COLOR_TRIE:insert(lowercase) - end - end - end - if opts and opts.tailwind then - if opts.tailwind == true or opts.tailwind == "normal" or opts.tailwind == "both" then - local tailwind = require "colorizer.tailwind_colors" - -- setup tailwind colors - for k, v in pairs(tailwind.colors) do - for _, pre in ipairs(tailwind.prefixes) do - local name = pre .. "-" .. k - COLOR_NAME_MINLEN = COLOR_NAME_MINLEN and min(#name, COLOR_NAME_MINLEN) or #name - COLOR_NAME_MAXLEN = COLOR_NAME_MAXLEN and max(#name, COLOR_NAME_MAXLEN) or #name - COLOR_MAP[name] = v - COLOR_TRIE:insert(name) - end - end - end - end - TAILWIND_ENABLED = opts.tailwind - end - - if #line < i + COLOR_NAME_MINLEN - 1 then - return - end - - if i > 1 and byte_is_alphanumeric(line:byte(i - 1)) then - return - end - - local prefix = COLOR_TRIE:longest_prefix(line, i) - if prefix then - -- Check if there is a letter here so as to disallow matching here. - -- Take the Blue out of Blueberry - -- Line end or non-letter. - local next_byte_index = i + #prefix - if #line >= next_byte_index and byte_is_alphanumeric(line:byte(next_byte_index)) then - return - end - return #prefix, COLOR_MAP[prefix] - end -end - ---- Converts an HSL color value to RGB. ----@param h number: Hue ----@param s number: Saturation ----@param l number: Lightness ----@return number|nil,number|nil,number|nil -local function hsl_to_rgb(h, s, l) - if h > 1 or s > 1 or l > 1 then - return - end - if s == 0 then - local r = l * 255 - return r, r, r - end - local q - if l < 0.5 then - q = l * (1 + s) - else - q = l + s - l * s - end - local p = 2 * l - q - return 255 * hue_to_rgb(p, q, h + 1 / 3), 255 * hue_to_rgb(p, q, h), 255 * hue_to_rgb(p, q, h - 1 / 3) -end - -local CSS_RGB_FN_MINIMUM_LENGTH = #"rgb(0,0,0)" - 1 ----Parse for rgb() css function and return rgb hex. ----@param line string: Line to parse ----@param i number: Index of line from where to start parsing ----@return number|nil: Index of line where the rgb function ended ----@return string|nil: rgb hex value -local function rgb_function_parser(line, i) - if #line < i + CSS_RGB_FN_MINIMUM_LENGTH then - return - end - local r, g, b, match_end = line:sub(i):match "^rgb%(%s*(%d+%%?)%s*,%s*(%d+%%?)%s*,%s*(%d+%%?)%s*%)()" - if not match_end then - r, g, b, match_end = line:sub(i):match "^rgb%(%s*(%d+%%?)%s+(%d+%%?)%s+(%d+%%?)%s*%)()" - if not match_end then - return - end - end - r = percent_or_hex(r) - if not r then - return - end - g = percent_or_hex(g) - if not g then - return - end - b = percent_or_hex(b) - if not b then - return - end - local rgb_hex = string.format("%02x%02x%02x", r, g, b) - return match_end - 1, rgb_hex -end - -local CSS_RGBA_FN_MINIMUM_LENGTH = #"rgba(0,0,0,0)" - 1 ----Parse for rgba() css function and return rgb hex. --- Todo consider removing the regexes here --- Todo this might not be the best approach to alpha channel. --- Things like pumblend might be useful here. ----@param line string: Line to parse ----@param i number: Index of line from where to start parsing ----@return number|nil: Index of line where the rgba function ended ----@return string|nil: rgb hex value -local function rgba_function_parser(line, i) - if #line < i + CSS_RGBA_FN_MINIMUM_LENGTH then - return - end - local r, g, b, a, match_end = - line:sub(i):match "^rgba%(%s*(%d+%%?)%s*,%s*(%d+%%?)%s*,%s*(%d+%%?)%s*,%s*([.%d]+)%s*%)()" - if not match_end then - r, g, b, a, match_end = line:sub(i):match "^rgba%(%s*(%d+%%?)%s+(%d+%%?)%s+(%d+%%?)%s+([.%d]+)%s*%)()" - if not match_end then - return - end - end - a = tonumber(a) - if not a or a > 1 then - return - end - r = percent_or_hex(r) - if not r then - return - end - g = percent_or_hex(g) - if not g then - return - end - b = percent_or_hex(b) - if not b then - return - end - local rgb_hex = string.format("%02x%02x%02x", r * a, g * a, b * a) - return match_end - 1, rgb_hex -end - -local CSS_HSL_FN_MINIMUM_LENGTH = #"hsl(0,0%,0%)" - 1 ----Parse for hsl() css function and return rgb hex. ----@param line string: Line to parse ----@param i number: Index of line from where to start parsing ----@return number|nil: Index of line where the hsl function ended ----@return string|nil: rgb hex value -local function hsl_function_parser(line, i) - if #line < i + CSS_HSL_FN_MINIMUM_LENGTH then - return - end - local h, s, l, match_end = line:sub(i):match "^hsl%(%s*(%d+)%s*,%s*(%d+)%%%s*,%s*(%d+)%%%s*%)()" - if not match_end then - h, s, l, match_end = line:sub(i):match "^hsl%(%s*(%d+)%s+(%d+)%%%s+(%d+)%%%s*%)()" - if not match_end then - return - end - end - h = tonumber(h) - if h > 360 then - return - end - s = tonumber(s) - if s > 100 then - return - end - l = tonumber(l) - if l > 100 then - return - end - local r, g, b = hsl_to_rgb(h / 360, s / 100, l / 100) - if r == nil or g == nil or b == nil then - return - end - local rgb_hex = string.format("%02x%02x%02x", r, g, b) - return match_end - 1, rgb_hex -end - -local CSS_HSLA_FN_MINIMUM_LENGTH = #"hsla(0,0%,0%,0)" - 1 ----Parse for hsl() css function and return rgb hex. ----@param line string: Line to parse ----@param i number: Index of line from where to start parsing ----@return number|nil: Index of line where the hsla function ended ----@return string|nil: rgb hex value -local function hsla_function_parser(line, i) - if #line < i + CSS_HSLA_FN_MINIMUM_LENGTH then - return - end - local h, s, l, a, match_end = line:sub(i):match "^hsla%(%s*(%d+)%s*,%s*(%d+)%%%s*,%s*(%d+)%%%s*,%s*([.%d]+)%s*%)()" - if not match_end then - h, s, l, a, match_end = line:sub(i):match "^hsla%(%s*(%d+)%s+(%d+)%%%s+(%d+)%%%s+([.%d]+)%s*%)()" - if not match_end then - return - end - end - a = tonumber(a) - if not a or a > 1 then - return - end - h = tonumber(h) - if h > 360 then - return - end - s = tonumber(s) - if s > 100 then - return - end - l = tonumber(l) - if l > 100 then - return - end - local r, g, b = hsl_to_rgb(h / 360, s / 100, l / 100) - if r == nil or g == nil or b == nil then - return - end - local rgb_hex = string.format("%02x%02x%02x", r * a, g * a, b * a) - return match_end - 1, rgb_hex -end - -local ARGB_MINIMUM_LENGTH = #"0xAARRGGBB" - 1 ----parse for 0xaarrggbb and return rgb hex. --- a format used in android apps ----@param line string: line to parse ----@param i number: index of line from where to start parsing ----@return number|nil: index of line where the hex value ended ----@return string|nil: rgb hex value -local function argb_hex_parser(line, i) - if #line < i + ARGB_MINIMUM_LENGTH then - return - end - - local j = i + 2 - - local n = j + 8 - local alpha - local v = 0 - while j <= min(n, #line) do - local b = line:byte(j) - if not byte_is_hex(b) then - break - end - if j - i <= 3 then - alpha = parse_hex(b) + lshift(alpha or 0, 4) - else - v = parse_hex(b) + lshift(v, 4) - end - j = j + 1 - end - if #line >= j and byte_is_alphanumeric(line:byte(j)) then - return - end - local length = j - i - if length ~= 10 then - return - end - alpha = tonumber(alpha) / 255 - local r = floor(band(rshift(v, 16), 0xFF) * alpha) - local g = floor(band(rshift(v, 8), 0xFF) * alpha) - local b = floor(band(v, 0xFF) * alpha) - local rgb_hex = string.format("%02x%02x%02x", r, g, b) - return length, rgb_hex -end - ----parse for #rrggbbaa and return rgb hex. --- a format used in android apps ----@param line string: line to parse ----@param i number: index of line from where to start parsing ----@param opts table: Containing minlen, maxlen, valid_lengths ----@return number|nil: index of line where the hex value ended ----@return string|nil: rgb hex value -local function rgba_hex_parser(line, i, opts) - local minlen, maxlen, valid_lengths = opts.minlen, opts.maxlen, opts.valid_lengths - local j = i + 1 - if #line < j + minlen - 1 then - return - end - - if i > 1 and byte_is_alphanumeric(line:byte(i - 1)) then - return - end - - local n = j + maxlen - local alpha - local v = 0 - - while j <= min(n, #line) do - local b = line:byte(j) - if not byte_is_hex(b) then - break - end - if j - i >= 7 then - alpha = parse_hex(b) + lshift(alpha or 0, 4) - else - v = parse_hex(b) + lshift(v, 4) - end - j = j + 1 - end - - if #line >= j and byte_is_alphanumeric(line:byte(j)) then - return - end - - local length = j - i - if length ~= 4 and length ~= 7 and length ~= 9 then - return - end - - if alpha then - alpha = tonumber(alpha) / 255 - local r = floor(band(rshift(v, 16), 0xFF) * alpha) - local g = floor(band(rshift(v, 8), 0xFF) * alpha) - local b = floor(band(v, 0xFF) * alpha) - local rgb_hex = string.format("%02x%02x%02x", r, g, b) - return 9, rgb_hex - end - return (valid_lengths[length - 1] and length), line:sub(i + 1, i + length - 1) -end - ---- @export -return { - color_is_bright = color_is_bright, - color_name_parser = color_name_parser, - rgba_hex_parser = rgba_hex_parser, - argb_hex_parser = argb_hex_parser, - rgb_function_parser = rgb_function_parser, - rgba_function_parser = rgba_function_parser, - hsl_function_parser = hsl_function_parser, - hsla_function_parser = hsla_function_parser, -} |