diff --git a/doc/colorizer.txt b/doc/colorizer.txt
index a7d21b5..491e5b5 100644
--- a/doc/colorizer.txt
+++ b/doc/colorizer.txt
@@ -412,34 +412,124 @@ default_namespace *colorizer.buffer.default_namespace*
==============================================================================
COLOR *colorizer.color-introduction*
-Helper functions to parse different colour formats
+Helper color functions
==============================================================================
LUA API *colorizer.color-lua-api*
Functions: ~
- |argb_hex_parser| - parse for 0xaarrggbb and return rgb hex.
-
|hsl_to_rgb| - Converts an HSL color value to RGB.
- |hsl_function_parser| - Parse for hsl() hsla() css function and return rgb
- hex.
-
|hue_to_rgb| - Convert hsl colour values to rgb.
|is_bright| - Determine whether to use black or white text.
- |name_parser| - Grab all the colour values from `vim.api.nvim_get_color_map`
- and create a lookup table.
- |rgb_function_parser| - Parse for rgb() rgba() css function and return rgb
- hex.
+hsl_to_rgb({h}, {s}, {l}) *colorizer.color.hsl_to_rgb*
+ Converts an HSL color value to RGB.
+
+ Parameters: ~
+ {h} - number: Hue
+ {s} - number: Saturation
+ {l} - number: Lightness
+
+ returns:~
+ number or nil,number or nil,number or nil
+
+
+
+hue_to_rgb({p}, {q}, {t}) *colorizer.color.hue_to_rgb*
+ Convert hsl colour values to rgb.
+
+ Source: https://gist.github.com/mjackson/5311256
+
+
+ Parameters: ~
+ {p} - number
+ {q} - number
+ {t} - number
+
+ returns:~
+ number
+
+
+
+is_bright({r}, {g}, {b}) *colorizer.color.is_bright*
+ 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
+
+
+ Parameters: ~
+ {r} - number: Red
+ {g} - number: Green
+ {b} - number: Blue
+
+
+
+==============================================================================
+MATCHER *colorizer.matcher-introduction*
+
+Helper functions for colorizer to enable required parsers
+
+
+==============================================================================
+LUA API *colorizer.matcher-lua-api*
+
+Functions: ~
+ |compile| - Form a trie stuct with the given prefixes
+
+ |make| - Parse the given options and return a function with enabled parsers.
+
+
+compile({matchers}, {matchers_trie}) *colorizer.matcher.compile*
+ Form a trie stuct with the given prefixes
+
+ Parameters: ~
+ {matchers} - table: List of prefixes, {"rgb", "hsl"}
+ {matchers_trie} - table: Table containing information regarding
+ non-trie based parsers
+
+ returns:~
+ function: function which will just parse the line for enabled parsers
+
+
+
+make({options}) *colorizer.matcher.make*
+ Parse the given options and return a function with enabled parsers.
+
+ if no parsers enabled then return false
+ Do not try make the function again if it is present in the cache
- |rgba_hex_parser| - parse for #rrggbbaa and return rgb hex.
+ Parameters: ~
+ {options} - table: options created in `colorizer.setup`
-argb_hex_parser({line}, {i}) *colorizer.color.argb_hex_parser*
+ returns:~
+ function or boolean: function which will just parse the line for enabled
+ parsers
+
+
+
+==============================================================================
+ARGB_HEX *colorizer.parser.argb_hex-introduction*
+
+Helper function to parse argb
+
+
+==============================================================================
+LUA API *colorizer.parser.argb_hex-lua-api*
+
+Functions: ~
+ |parser.argb_hex_parser| - parse for 0xaarrggbb and return rgb hex.
+
+
+
+ *colorizer.parser.argb_hex.parser.argb_hex_parser*
+parser.argb_hex_parser({line}, {i})
parse for 0xaarrggbb and return rgb hex.
a format used in android apps
@@ -455,20 +545,23 @@ argb_hex_parser({line}, {i}) *colorizer.color.argb_hex_parser*
-hsl_to_rgb({h}, {s}, {l}) *colorizer.color.hsl_to_rgb*
- Converts an HSL color value to RGB.
+==============================================================================
+HSL *colorizer.parser.hsl-introduction*
- Parameters: ~
- {h} - number: Hue
- {s} - number: Saturation
- {l} - number: Lightness
+Helper function to parse argb
- returns:~
- number or nil,number or nil,number or nil
+
+==============================================================================
+LUA API *colorizer.parser.hsl-lua-api*
+
+Functions: ~
+ |parser.hsl_function_parser| - Parse for hsl() hsla() css function and
+ return rgb hex.
-hsl_function_parser({line}, {i}, {opts}) *colorizer.color.hsl_function_parser*
+ *colorizer.parser.hsl.parser.hsl_function_parser*
+parser.hsl_function_parser({line}, {i}, {opts})
Parse for hsl() hsla() css function and return rgb hex.
For more info:
@@ -486,38 +579,23 @@ hsl_function_parser({line}, {i}, {opts}) *colorizer.color.hsl_function_parser*
-hue_to_rgb({p}, {q}, {t}) *colorizer.color.hue_to_rgb*
- Convert hsl colour values to rgb.
-
- Source: https://gist.github.com/mjackson/5311256
-
-
- Parameters: ~
- {p} - number
- {q} - number
- {t} - number
-
- returns:~
- number
-
-
-
-is_bright({r}, {g}, {b}) *colorizer.color.is_bright*
- Determine whether to use black or white text.
+==============================================================================
+NAMES *colorizer.parser.names-introduction*
+Helper function to parse argb
- ref: https://stackoverflow.com/a/1855903/837964
- https://stackoverflow.com/questions/596216/formula-to-determine-brightness-of-rgb-color
+==============================================================================
+LUA API *colorizer.parser.names-lua-api*
- Parameters: ~
- {r} - number: Red
- {g} - number: Green
- {b} - number: Blue
+Functions: ~
+ |parser.name_parser| - Grab all the colour values from
+ `vim.api.nvim_get_color_map` and create a lookup table.
-name_parser({line}, {i}, {opts}) *colorizer.color.name_parser*
+ *colorizer.parser.names.parser.name_parser*
+parser.name_parser({line}, {i}, {opts})
Grab all the colour values from `vim.api.nvim_get_color_map` and create a
lookup table.
@@ -531,25 +609,22 @@ name_parser({line}, {i}, {opts}) *colorizer.color.name_parser*
-rgb_function_parser({line}, {i}, {opts}) *colorizer.color.rgb_function_parser*
- Parse for rgb() rgba() css function and return rgb hex.
+==============================================================================
+RGBA_HEX *colorizer.parser.rgba_hex-introduction*
- For more info:
- https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/rgb
+Helper function to parse argb
- Parameters: ~
- {line} - string: Line to parse
- {i} - number: Index of line from where to start parsing
- {opts} - table: Values passed from matchers like prefix
+==============================================================================
+LUA API *colorizer.parser.rgba_hex-lua-api*
- returns:~
- number or nil: Index of line where the rgb/rgba function ended
- string or nil: rgb hex value
+Functions: ~
+ |parser.rgba_hex_parser| - parse for #rrggbbaa and return rgb hex.
-rgba_hex_parser({line}, {i}, {opts}) *colorizer.color.rgba_hex_parser*
+ *colorizer.parser.rgba_hex.parser.rgba_hex_parser*
+parser.rgba_hex_parser({line}, {i}, {opts})
parse for #rrggbbaa and return rgb hex.
a format used in android apps
@@ -567,46 +642,36 @@ rgba_hex_parser({line}, {i}, {opts}) *colorizer.color.rgba_hex_parser*
==============================================================================
-MATCHER *colorizer.matcher-introduction*
+RGB *colorizer.parser.rgb-introduction*
-Helper functions for colorizer to enable required parsers
+Helper function to parse argb
==============================================================================
-LUA API *colorizer.matcher-lua-api*
+LUA API *colorizer.parser.rgb-lua-api*
Functions: ~
- |compile| - Form a trie stuct with the given prefixes
+ |parser.rgb_function_parser| - Parse for rgb() rgba() css function and
+ return rgb hex.
- |make| - Parse the given options and return a function with enabled parsers.
-compile({matchers}, {matchers_trie}) *colorizer.matcher.compile*
- Form a trie stuct with the given prefixes
-
- Parameters: ~
- {matchers} - table: List of prefixes, {"rgb", "hsl"}
- {matchers_trie} - table: Table containing information regarding
- non-trie based parsers
-
- returns:~
- function: function which will just parse the line for enabled parsers
-
-
-
-make({options}) *colorizer.matcher.make*
- Parse the given options and return a function with enabled parsers.
+ *colorizer.parser.rgb.parser.rgb_function_parser*
+parser.rgb_function_parser({line}, {i}, {opts})
+ Parse for rgb() rgba() css function and return rgb hex.
- if no parsers enabled then return false
- Do not try make the function again if it is present in the cache
+ For more info:
+ https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/rgb
Parameters: ~
- {options} - table: options created in `colorizer.setup`
+ {line} - string: Line to parse
+ {i} - number: Index of line from where to start parsing
+ {opts} - table: Values passed from matchers like prefix
returns:~
- function or boolean: function which will just parse the line for enabled
- parsers
+ number or nil: Index of line where the rgb/rgba function ended
+ string or nil: rgb hex value
diff --git a/doc/index.html b/doc/index.html
index 7735382..3070ca2 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -35,6 +35,11 @@
diff --git a/lua/colorizer/color.lua b/lua/colorizer/color.lua
index 370131b..29af64d 100644
--- a/lua/colorizer/color.lua
+++ b/lua/colorizer/color.lua
@@ -1,66 +1,7 @@
----Helper functions to parse different colour formats
+---Helper color functions
--@module colorizer.color
-local api = vim.api
-
-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 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 byte_is_valid_colorchar = utils.byte_is_valid_colorchar
-local count = utils.count
-local parse_hex = utils.parse_hex
-
local color = {}
-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
-function color.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
-
--- Converts an HSL color value to RGB.
---@param h number: Hue
---@param s number: Saturation
@@ -86,107 +27,6 @@ function color.hsl_to_rgb(h, s, l)
255 * color.hue_to_rgb(p, q, h - 1 / 3)
end
-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 color.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 = color.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
-
---Convert hsl colour values to rgb.
-- Source: https://gist.github.com/mjackson/5311256
---@param p number
@@ -229,236 +69,4 @@ function color.is_bright(r, g, b)
end
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
-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_valid_colorchar(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_valid_colorchar(line:byte(next_byte_index)) then
- return
- end
- return #prefix, COLOR_MAP[prefix]
- end
-end
-
-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 color.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
-
----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
-function color.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
-
return color
diff --git a/lua/colorizer/matcher.lua b/lua/colorizer/matcher.lua
index ccd72a2..1f3eede 100644
--- a/lua/colorizer/matcher.lua
+++ b/lua/colorizer/matcher.lua
@@ -3,21 +3,24 @@
local Trie = require "colorizer.trie"
local min, max = math.min, math.max
-local color = require "colorizer.color"
-local color_name_parser = color.name_parser
-local rgba_hex_parser = color.rgba_hex_parser
+local color_name_parser = require "colorizer.parser.names"
-local sass = require "colorizer.sass"
-local sass_name_parser = sass.name_parser
+local rgb_function_parser = require "colorizer.parser.rgb"
+local hsl_function_parser = require "colorizer.parser.hsl"
+
+local argb_hex_parser = require "colorizer.parser.argb_hex"
+local rgba_hex_parser = require "colorizer.parser.rgba_hex"
+
+local sass_name_parser = require("colorizer.sass").name_parser
local B_HASH, DOLLAR_HASH = ("#"):byte(), ("$"):byte()
local parser = {
- ["_0x"] = color.argb_hex_parser,
- ["_rgb"] = color.rgb_function_parser,
- ["_rgba"] = color.rgb_function_parser,
- ["_hsl"] = color.hsl_function_parser,
- ["_hsla"] = color.hsl_function_parser,
+ ["_0x"] = argb_hex_parser,
+ ["_rgb"] = rgb_function_parser,
+ ["_rgba"] = rgb_function_parser,
+ ["_hsl"] = hsl_function_parser,
+ ["_hsla"] = hsl_function_parser,
}
local matcher = {}
diff --git a/lua/colorizer/parser/argb_hex.lua b/lua/colorizer/parser/argb_hex.lua
new file mode 100644
index 0000000..f664dc3
--- /dev/null
+++ b/lua/colorizer/parser/argb_hex.lua
@@ -0,0 +1,58 @@
+---Helper function to parse argb
+
+local bit = require "bit"
+local floor, min = math.floor, math.min
+local band, rshift, lshift = bit.band, bit.rshift, bit.lshift
+
+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 parser = {}
+
+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
+function parser.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
+
+return parser.argb_hex_parser
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
diff --git a/lua/colorizer/parser/names.lua b/lua/colorizer/parser/names.lua
new file mode 100644
index 0000000..6fc7043
--- /dev/null
+++ b/lua/colorizer/parser/names.lua
@@ -0,0 +1,84 @@
+---Helper function to parse argb
+local api = vim.api
+
+local bit = require "bit"
+local tohex = bit.tohex
+
+local min, max = math.min, math.max
+
+local Trie = require "colorizer.trie"
+
+local utils = require "colorizer.utils"
+local byte_is_valid_colorchar = utils.byte_is_valid_colorchar
+
+local parser = {}
+
+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
+function parser.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_valid_colorchar(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_valid_colorchar(line:byte(next_byte_index)) then
+ return
+ end
+ return #prefix, COLOR_MAP[prefix]
+ end
+end
+
+return parser.name_parser
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
diff --git a/lua/colorizer/parser/rgba_hex.lua b/lua/colorizer/parser/rgba_hex.lua
new file mode 100644
index 0000000..0f16fbe
--- /dev/null
+++ b/lua/colorizer/parser/rgba_hex.lua
@@ -0,0 +1,68 @@
+---Helper function to parse argb
+local bit = require "bit"
+local floor, min = math.floor, math.min
+local band, rshift, lshift = bit.band, bit.rshift, bit.lshift
+
+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 parser = {}
+
+---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
+function parser.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
+
+return parser.rgba_hex_parser