diff options
author | akianonymus <anonymus.aki@gmail.com> | 2023-02-27 14:30:10 +0530 |
---|---|---|
committer | akianonymus <anonymus.aki@gmail.com> | 2023-02-27 16:01:48 +0530 |
commit | dde3084106a70b9a79d48f426f6d6fec6fd203f7 (patch) | |
tree | f1b06f0921e9eaf98bcc94f4d86d9f4d7226cb54 /lua/colorizer/parser/hsl.lua | |
parent | fix: virtualtext on nonfocused window update | #41 (diff) |
Separate parsers into individual files
Diffstat (limited to 'lua/colorizer/parser/hsl.lua')
-rw-r--r-- | lua/colorizer/parser/hsl.lua | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/lua/colorizer/parser/hsl.lua b/lua/colorizer/parser/hsl.lua new file mode 100644 index 0000000..cb6a19d --- /dev/null +++ b/lua/colorizer/parser/hsl.lua @@ -0,0 +1,110 @@ +---Helper function to parse argb +local count = require("colorizer.utils").count +local floor = math.floor + +local hsl_to_rgb = require("colorizer.color").hsl_to_rgb + +local parser = {} + +local CSS_HSLA_FN_MINIMUM_LENGTH = #"hsla(0,0%,0%)" - 1 +local CSS_HSL_FN_MINIMUM_LENGTH = #"hsl(0,0%,0%)" - 1 +---Parse for hsl() hsla() css function and return rgb hex. +-- For more info: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl +---@param line string: Line to parse +---@param i number: Index of line from where to start parsing +---@param opts table: Values passed from matchers like prefix +---@return number|nil: Index of line where the hsla/hsl function ended +---@return string|nil: rgb hex value +function parser.hsl_function_parser(line, i, opts) + local min_len = CSS_HSLA_FN_MINIMUM_LENGTH + local min_commas, min_spaces = 2, 2 + local pattern = "^" + .. opts.prefix + .. "%(%s*([.%d]+)([deg]*)([turn]*)(%s?)%s*(,?)%s*(%d+)%%(%s?)%s*(,?)%s*(%d+)%%%s*(/?,?)%s*([.%d]*)([%%]?)%s*%)()" + + if opts.prefix == "hsl" then + min_len = CSS_HSL_FN_MINIMUM_LENGTH + end + + if #line < i + min_len then + return + end + + local h, deg, turn, ssep1, csep1, s, ssep2, csep2, l, sep3, a, percent_sign, match_end = line:sub(i):match(pattern) + if not match_end then + return + end + if a == "" then + a = nil + else + min_commas = min_commas + 1 + end + + -- the text after hue should be either deg or empty + if not ((deg == "") or (deg == "deg") or (turn == "turn")) then + return + end + + local c_seps = ("%s%s%s"):format(csep1, csep2, sep3) + local s_seps = ("%s%s"):format(ssep1, ssep2) + -- comma separator syntax + if c_seps:match "," then + if not (count(c_seps, ",") == min_commas) then + return + end + -- space separator syntax with decimal or percentage alpha + elseif count(s_seps, "%s") >= min_spaces then + if a then + if not (c_seps == "/") then + return + end + end + else + return + end + + if not a then + a = 1 + else + a = tonumber(a) + -- if percentage, then convert to decimal + if percent_sign == "%" then + a = a / 100 + end + -- although alpha doesn't support larger values than 1, css anyways renders it at 1 + if a > 1 then + a = 1 + end + end + + h = tonumber(h) or 1 + -- single turn is 360 + if turn == "turn" then + h = 360 * h + end + + -- if hue angle if greater than 360, then calculate the hue within 360 + if h > 360 then + local turns = h / 360 + h = 360 * (turns - floor(turns)) + end + + -- if saturation or luminance percentage is greater than 100 then reset it to 100 + s = tonumber(s) + if s > 100 then + s = 100 + end + l = tonumber(l) + if l > 100 then + l = 100 + 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 + +return parser.hsl_function_parser |