aboutsummaryrefslogtreecommitdiff
path: root/lua/colorizer/matcher_utils.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/colorizer/matcher_utils.lua')
-rw-r--r--lua/colorizer/matcher_utils.lua132
1 files changed, 132 insertions, 0 deletions
diff --git a/lua/colorizer/matcher_utils.lua b/lua/colorizer/matcher_utils.lua
new file mode 100644
index 0000000..84ddece
--- /dev/null
+++ b/lua/colorizer/matcher_utils.lua
@@ -0,0 +1,132 @@
+---Helper functions for colorizer to enable required parsers
+--@module colorizer.matcher_utils
+local Trie = require "colorizer.trie"
+local min, max = math.min, math.max
+
+local color_utils = require "colorizer.color_utils"
+local color_name_parser = color_utils.color_name_parser
+local rgba_hex_parser = color_utils.rgba_hex_parser
+
+local parser = {}
+parser["_0x"] = color_utils.argb_hex_parser
+parser["_rgb"] = color_utils.rgb_function_parser
+parser["_rgba"] = color_utils.rgba_function_parser
+parser["_hsl"] = color_utils.hsl_function_parser
+parser["_hsla"] = color_utils.hsla_function_parser
+
+---Form a trie stuct with the given prefixes
+---@param matchers table: List of prefixes, {"rgb", "hsl"}
+---@param matchers_trie table: Table containing information regarding non-trie based parsers
+---@return function: function which will just parse the line for enabled parsers
+local function compile_matcher(matchers, matchers_trie)
+ local trie = Trie(matchers_trie)
+
+ local b_hash = ("#"):byte()
+ local function parse_fn(line, i)
+ -- prefix #
+ if matchers.rgba_hex_parser then
+ if line:byte(i) == b_hash then
+ return rgba_hex_parser(line, i, matchers.rgba_hex_parser)
+ end
+ end
+
+ -- Prefix 0x, rgba, rgb, hsla, hsl
+ local prefix = trie:longest_prefix(line, i)
+ if prefix then
+ local fn = "_" .. prefix
+ return parser[fn](line, i, matchers[fn])
+ end
+
+ -- Colour names
+ if matchers.color_name_parser then
+ return color_name_parser(line, i)
+ end
+ end
+ return parse_fn
+end
+
+local MATCHER_CACHE = {}
+---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
+---@param options table: options created in `colorizer.setup`
+---@return function|boolean: function which will just parse the line for enabled parsers
+local function make_matcher(options)
+ local enable_names = options.css or options.names
+ local enable_RGB = options.css or options.RGB
+ local enable_RRGGBB = options.css or options.RRGGBB
+ local enable_RRGGBBAA = options.css or options.RRGGBBAA
+ local enable_AARRGGBB = options.AARRGGBB
+ local enable_rgb = options.css or options.css_fns or options.rgb_fn
+ local enable_hsl = options.css or options.css_fns or options.hsl_fn
+
+ local matcher_key = 0
+ + (enable_names and 1 or 0)
+ + (enable_RGB and 1 or 1)
+ + (enable_RRGGBB and 1 or 2)
+ + (enable_RRGGBBAA and 1 or 3)
+ + (enable_AARRGGBB and 1 or 4)
+ + (enable_rgb and 1 or 5)
+ + (enable_hsl and 1 or 6)
+
+ if matcher_key == 0 then
+ return false
+ end
+
+ local loop_parse_fn = MATCHER_CACHE[matcher_key]
+ if loop_parse_fn then
+ return loop_parse_fn
+ end
+
+ local matchers = {}
+ local matchers_prefix = {}
+ matchers.max_prefix_length = 0
+
+ if enable_names then
+ matchers.color_name_parser = true
+ end
+
+ local valid_lengths = { [3] = enable_RGB, [6] = enable_RRGGBB, [8] = enable_RRGGBBAA }
+ local minlen, maxlen
+ for k, v in pairs(valid_lengths) do
+ if v then
+ minlen = minlen and min(k, minlen) or k
+ maxlen = maxlen and max(k, maxlen) or k
+ end
+ end
+
+ if minlen then
+ matchers.rgba_hex_parser = {}
+ matchers.rgba_hex_parser.valid_lengths = valid_lengths
+ matchers.rgba_hex_parser.maxlen = maxlen
+ matchers.rgba_hex_parser.minlen = minlen
+ end
+
+ if enable_AARRGGBB then
+ table.insert(matchers_prefix, "0x")
+ end
+
+ -- do not mess with the sequence, hsla before hsl, etc
+ if enable_rgb and enable_hsl then
+ table.insert(matchers_prefix, "hsla")
+ table.insert(matchers_prefix, "rgba")
+ table.insert(matchers_prefix, "rgb")
+ table.insert(matchers_prefix, "hsl")
+ elseif enable_rgb then
+ table.insert(matchers_prefix, "rgba")
+ table.insert(matchers_prefix, "rgb")
+ elseif enable_hsl then
+ table.insert(matchers_prefix, "hsla")
+ table.insert(matchers_prefix, "hsl")
+ end
+
+ loop_parse_fn = compile_matcher(matchers, matchers_prefix)
+ MATCHER_CACHE[matcher_key] = loop_parse_fn
+
+ return loop_parse_fn
+end
+
+--- @export
+return {
+ make_matcher = make_matcher,
+}