aboutsummaryrefslogtreecommitdiff
path: root/lua/colorizer/color_utils.lua
diff options
context:
space:
mode:
authorAkianonymus <anonymus.aki@gmail.com>2022-09-15 10:00:00 +0530
committerAkianonymus <anonymus.aki@gmail.com>2022-09-15 13:51:38 +0530
commitcf4f33f5ea34f9c4e9975299b094f1a2b8b34aa0 (patch)
tree3f2558419b2643ac7af8f4abe8e67db478d64309 /lua/colorizer/color_utils.lua
parentfix(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.lua411
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,
-}