aboutsummaryrefslogtreecommitdiff
path: root/lua/colorizer/parser/rgb.lua
diff options
context:
space:
mode:
authorakianonymus <anonymus.aki@gmail.com>2023-02-27 14:30:10 +0530
committerakianonymus <anonymus.aki@gmail.com>2023-02-27 16:01:48 +0530
commitdde3084106a70b9a79d48f426f6d6fec6fd203f7 (patch)
treef1b06f0921e9eaf98bcc94f4d86d9f4d7226cb54 /lua/colorizer/parser/rgb.lua
parentfix: virtualtext on nonfocused window update | #41 (diff)
Separate parsers into individual files
Diffstat (limited to 'lua/colorizer/parser/rgb.lua')
-rw-r--r--lua/colorizer/parser/rgb.lua114
1 files changed, 114 insertions, 0 deletions
diff --git a/lua/colorizer/parser/rgb.lua b/lua/colorizer/parser/rgb.lua
new file mode 100644
index 0000000..2786a60
--- /dev/null
+++ b/lua/colorizer/parser/rgb.lua
@@ -0,0 +1,114 @@
+---Helper function to parse argb
+local count = require("colorizer.utils").count
+
+local parser = {}
+local CSS_RGBA_FN_MINIMUM_LENGTH = #"rgba(0,0,0)" - 1
+local CSS_RGB_FN_MINIMUM_LENGTH = #"rgb(0,0,0)" - 1
+---Parse for rgb() rgba() css function and return rgb hex.
+-- For more info: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/rgb
+---@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 rgb/rgba function ended
+---@return string|nil: rgb hex value
+function parser.rgb_function_parser(line, i, opts)
+ local min_len = CSS_RGBA_FN_MINIMUM_LENGTH
+ local min_commas, min_spaces, min_percent = 2, 2, 3
+ local pattern = "^"
+ .. opts.prefix
+ .. "%(%s*([.%d]+)([%%]?)(%s?)%s*(,?)%s*([.%d]+)([%%]?)(%s?)%s*(,?)%s*([.%d]+)([%%]?)%s*(/?,?)%s*([.%d]*)([%%]?)%s*%)()"
+
+ if opts.prefix == "rgb" then
+ min_len = CSS_RGB_FN_MINIMUM_LENGTH
+ end
+
+ if #line < i + min_len then
+ return
+ end
+
+ local r, unit1, ssep1, csep1, g, unit2, ssep2, csep2, b, unit3, sep3, a, unit_a, 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
+
+ local units = ("%s%s%s"):format(unit1, unit2, unit3)
+ if units:match "%%" then
+ if not ((count(units, "%%")) == min_percent) then
+ return
+ end
+ 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 unit_a == "%" 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
+
+ r = tonumber(r)
+ if not r then
+ return
+ end
+ g = tonumber(g)
+ if not g then
+ return
+ end
+ b = tonumber(b)
+ if not b then
+ return
+ end
+
+ if unit1 == "%" then
+ r = r / 100 * 255
+ g = g / 100 * 255
+ b = b / 100 * 255
+ else
+ -- although r,g,b doesn't support larger values than 255, css anyways renders it at 255
+ if r > 255 then
+ r = 255
+ end
+ if g > 255 then
+ g = 255
+ end
+ if b > 255 then
+ b = 255
+ end
+ end
+
+ local rgb_hex = string.format("%02x%02x%02x", r * a, g * a, b * a)
+ return match_end - 1, rgb_hex
+end
+
+return parser.rgb_function_parser