diff options
Diffstat (limited to 'lua/colorizer/matcher_utils.lua')
-rw-r--r-- | lua/colorizer/matcher_utils.lua | 132 |
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, +} |