diff --git a/README.md b/README.md index f18d725..1685f21 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# colorizer.lua ( NOT MAINTAINED, Looking for maintainers ) +# colorizer.lua diff --git a/lua/colorizer.lua b/lua/colorizer.lua index c6fa124..d440433 100644 --- a/lua/colorizer.lua +++ b/lua/colorizer.lua @@ -67,7 +67,7 @@ local merge = utils.merge local api = vim.api local augroup = api.nvim_create_augroup local autocmd = api.nvim_create_autocmd -local buf_get_option = api.nvim_get_option_value +local get_option_value = api.nvim_get_option_value local clear_namespace = api.nvim_buf_clear_namespace local current_buf = api.nvim_get_current_buf @@ -84,8 +84,7 @@ colorizer.DEFAULT_NAMESPACE = buffer_utils.default_namespace colorizer.highlight_buffer = buffer_utils.highlight -- USER FACING FUNCTIONALITY -- -local AUGROUP_ID -local AUGROUP_NAME = "ColorizerSetup" +local AU_GROUP = augroup("ColorizerSetup", {}) -- buffer specific options given in setup local BUFFER_OPTIONS = {} -- buffer local options created after setup @@ -186,16 +185,16 @@ local SETUP_SETTINGS = { } --- Make new buffer Configuration ----@param bufnr number: buffer number (0 for current) +---@param bufnr number: Buffer number ---@param bo_type 'buftype'|'filetype': The type of buffer option ---@return table local function new_buffer_options(bufnr, bo_type) - local value = buf_get_option(bo_type, { buf = bufnr }) + local value = get_option_value(bo_type, { buf = bufnr }) return OPTIONS.filetype[value] or SETUP_SETTINGS.default_options end --- Parse buffer Configuration and convert aliases to normal values ----@param options table: options table +---@param options table: Buffer options table ---@return table local function parse_buffer_options(options) local includes = { @@ -240,8 +239,8 @@ local function parse_buffer_options(options) end --- Check if attached to a buffer. ----@param bufnr number|nil: A value of 0 implies the current buffer. ----@return number|nil: if attached to the buffer, false otherwise. +---@param bufnr number|nil: Buffer number (0 for current) +---@return number|nil: Attached buffer number, nil otherwise. ---@see colorizer.buffer.highlight function colorizer.is_buffer_attached(bufnr) if bufnr == 0 or not bufnr then @@ -254,7 +253,7 @@ function colorizer.is_buffer_attached(bufnr) end local au = api.nvim_get_autocmds { - group = AUGROUP_ID, + group = AU_GROUP, event = { "WinScrolled", "TextChanged", "TextChangedI", "TextChangedP" }, buffer = bufnr, } @@ -312,14 +311,10 @@ function colorizer.attach_to_buffer(bufnr, options, bo_type) -- set options by grabbing existing or creating new options, then parsing options = parse_buffer_options(options or colorizer.get_buffer_options(bufnr) or new_buffer_options(bufnr, bo_type)) - if not buffer_utils.highlight_mode_names[options.mode] then - if options.mode ~= nil then - local mode = options.mode - vim.defer_fn(function() - -- just notify the user once - vim.notify_once(string.format("Warning: Invalid mode given to colorizer setup [ %s ]", mode)) - end, 0) - end + if options.mode and not buffer_utils.highlight_mode_names[options.mode] then + vim.defer_fn(function() + vim.notify_once(string.format("Warning: Invalid mode given to colorizer setup [ %s ]", options.mode)) + end, 0) options.mode = "background" end @@ -341,7 +336,7 @@ function colorizer.attach_to_buffer(bufnr, options, bo_type) end local autocmds = {} - local au_group_id = AUGROUP_ID + local au_group_id = AU_GROUP local text_changed_au = { "TextChanged", "TextChangedI", "TextChangedP" } -- only enable InsertLeave in sass, rest don't require it @@ -349,9 +344,7 @@ function colorizer.attach_to_buffer(bufnr, options, bo_type) table.insert(text_changed_au, "InsertLeave") end - if CURRENT_BUF == 0 then - CURRENT_BUF = bufnr - end + CURRENT_BUF = CURRENT_BUF == 0 and bufnr or CURRENT_BUF if options.always_update then -- attach using lua api so buffer gets updated even when not the current buffer @@ -359,7 +352,7 @@ function colorizer.attach_to_buffer(bufnr, options, bo_type) vim.api.nvim_buf_attach(bufnr, false, { on_lines = function(_, buffer) -- only reload if the buffer is not the current one - if not (CURRENT_BUF == buffer) then + if CURRENT_BUF ~= buffer then -- only reload if it was not disabled using detach_from_buffer if BUFFER_OPTIONS[bufnr] then rehighlight_buffer(bufnr, options, BUFFER_LOCAL[bufnr]) @@ -368,7 +361,7 @@ function colorizer.attach_to_buffer(bufnr, options, bo_type) end, on_reload = function(_, buffer) -- only reload if the buffer is not the current one - if not (CURRENT_BUF == buffer) then + if CURRENT_BUF ~= buffer then -- only reload if it was not disabled using detach_from_buffer if BUFFER_OPTIONS[bufnr] then rehighlight_buffer(bufnr, options, BUFFER_LOCAL[bufnr]) @@ -509,8 +502,6 @@ function colorizer.setup(config) end end - AUGROUP_ID = augroup(AUGROUP_NAME, {}) - local aucmd = { buftype = "BufWinEnter", filetype = "FileType" } local function parse_opts(bo_type, tbl) if type(tbl) == "table" then @@ -542,7 +533,7 @@ function colorizer.setup(config) end end autocmd({ aucmd[bo_type] }, { - group = AUGROUP_ID, + group = AU_GROUP, pattern = bo_type == "filetype" and (SETUP_SETTINGS.all[bo_type] and "*" or list) or nil, callback = function() COLORIZER_SETUP_HOOK(bo_type) @@ -557,7 +548,7 @@ function colorizer.setup(config) parse_opts("buftype", buftypes) autocmd("ColorScheme", { - group = AUGROUP_ID, + group = AU_GROUP, callback = function() require("colorizer").clear_highlight_cache() end, @@ -569,9 +560,7 @@ end ---@return table|nil function colorizer.get_buffer_options(bufnr) local buffer = colorizer.is_buffer_attached(bufnr) - if buffer then - return BUFFER_OPTIONS[buffer] - end + return BUFFER_OPTIONS[buffer] end --- Reload all of the currently active highlighted buffers. diff --git a/lua/colorizer/buffer.lua b/lua/colorizer/buffer.lua index 717e9fd..ab93051 100644 --- a/lua/colorizer/buffer.lua +++ b/lua/colorizer/buffer.lua @@ -89,8 +89,8 @@ local function create_highlight(rgb_hex, mode) end --- Create highlight and set highlights ----@param bufnr number: buffer number (0 for current) ----@param ns_id number +---@param bufnr number: Buffer number (0 for current) +---@param ns_id number: Namespace id, default is "colorizer" created with vim.api.nvim_create_namespace ---@param line_start number ---@param line_end number ---@param data table: table output of `parse_lines` @@ -135,23 +135,20 @@ end --- Highlight the buffer region. -- Highlight starting from `line_start` (0-indexed) for each line described by `lines` in the -- buffer id `bufnr` and attach it to the namespace id `ns_id`. ----@param bufnr number: buffer number (0 for current) ----@param ns_id number: namespace id. default is "colorizer", created with vim.api.nvim_create_namespace +---@param bufnr number: Buffer number, 0 for current +---@param ns_id number: Namespace id, default is "colorizer" created with vim.api.nvim_create_namespace ---@param line_start number: line_start should be 0-indexed ---@param line_end number: Last line to highlight ---@param options table: Configuration options as described in `setup` ---@param options_local table: Buffer local variables ----@return nil|boolean|number,table +---@return boolean,table function buffer.highlight(bufnr, ns_id, line_start, line_end, options, options_local) - local returns = { detach = { ns_id = {}, functions = {} } } - if bufnr == 0 or bufnr == nil then - bufnr = api.nvim_get_current_buf() - end + bufnr = (bufnr == 0 or not bufnr) and current_buf() or bufnr + ns_id = ns_id or buffer.default_namespace + local returns = { detach = { ns_id = {}, functions = {} } } local lines = buf_get_lines(bufnr, line_start, line_end, false) - ns_id = ns_id or buffer.default_namespace - -- only update sass varibles when text is changed if options_local.__event ~= "WinScrolled" and options.sass and options.sass.enable then table.insert(returns.detach.functions, sass_cleanup) @@ -171,8 +168,8 @@ end --- Parse the given lines for colors and return a table containing -- rgb_hex and range per line ----@param bufnr number: buffer number (0 for current) ----@param lines table: table of lines to parse +---@param bufnr number: Buffer number (0 for current) +---@param lines table: Table of lines to parse ---@param line_start number: This is the buffer line number, from where to start highlighting ---@param options table: Passed in `colorizer.setup`, Only uses `user_default_options` ---@return table|nil @@ -248,19 +245,19 @@ local function getrow(bufnr) end --- Rehighlight the buffer if colorizer is active ----@param bufnr number: buffer number (0 for current) +---@param bufnr number: Buffer number, (0 for current) ---@param options table: Buffer options ---@param options_local table|nil: Buffer local variables ---@param use_local_lines boolean|nil Whether to use lines num range from options_local ---@return nil|boolean|number,table function buffer.rehighlight(bufnr, options, options_local, use_local_lines) - bufnr = (bufnr == 0 or not bufnr) and current_buf() or bufnr - local ns_id = buffer.default_namespace - local min, max + local min = 0 + local max = -1 if use_local_lines and options_local then - min, max = options_local.__startline or 0, options_local.__endline or -1 + min = options_local.__startline or min + max = options_local.__endline or max else min, max = getrow(bufnr) end diff --git a/lua/colorizer/matcher.lua b/lua/colorizer/matcher.lua index e7ed656..241fc10 100644 --- a/lua/colorizer/matcher.lua +++ b/lua/colorizer/matcher.lua @@ -15,6 +15,9 @@ local sass_name_parser = require("colorizer.sass").name_parser local B_HASH, DOLLAR_HASH = ("#"):byte(), ("$"):byte() +-- TODO: 2024-11-05 - Instead of AARRGGBB vs RRGGBBAA parsers, should we have +-- 0x, # prefix parsers for 0xAARRGGBB, 0xRRGGBB, 0xRGB and #RRGGBBAA, #RRGGBB, +-- #RGB? local parser = { ["_0x"] = argb_hex_parser, ["_rgb"] = rgb_function_parser, @@ -32,19 +35,15 @@ local matcher = {} function matcher.compile(matchers, matchers_trie) local trie = Trie(matchers_trie) - local function parse_fn(line, i, buf) + local function parse_fn(line, i, bufnr) -- 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 + if matchers.rgba_hex_parser and line:byte(i) == B_HASH then + return rgba_hex_parser(line, i, matchers.rgba_hex_parser) end -- prefix $, SASS Colour names - if matchers.sass_name_parser then - if line:byte(i) == DOLLAR_HASH then - return sass_name_parser(line, i, buf) - end + if matchers.sass_name_parser and line:byte(i) == DOLLAR_HASH then + return sass_name_parser(line, i, bufnr) end -- Prefix 0x, rgba, rgb, hsla, hsl @@ -112,7 +111,6 @@ function matcher.make(options) local matchers = {} local matchers_prefix = {} - matchers.max_prefix_length = 0 if enable_names then matchers.color_name_parser = { tailwind = options.tailwind } @@ -138,6 +136,7 @@ function matcher.make(options) matchers.rgba_hex_parser.minlen = minlen end + -- TODO: 2024-11-05 - Add custom prefixes if enable_AARRGGBB then table.insert(matchers_prefix, "0x") end diff --git a/lua/colorizer/parser/argb_hex.lua b/lua/colorizer/parser/argb_hex.lua index f664dc3..ad9df13 100644 --- a/lua/colorizer/parser/argb_hex.lua +++ b/lua/colorizer/parser/argb_hex.lua @@ -1,5 +1,3 @@ ----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 @@ -11,46 +9,55 @@ 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 +---parse for 0xAARRGGBB, 0xRRGGBB, or 0xRGB and return rgb hex. ---@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 + local minlen = #"0xRGB" - 1 + local maxlen = #"0xAARRGGBB" - 1 + if #line < i + minlen then return end local j = i + 2 - - local n = j + 8 - local alpha + local n = j + maxlen + local alpha, r, g, b local v = 0 + while j <= min(n, #line) do - local b = line:byte(j) - if not byte_is_hex(b) then + local byte = line:byte(j) -- Renamed to `byte` to avoid conflict with `b` + if not byte_is_hex(byte) 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 + v = parse_hex(byte) + lshift(v, 4) 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 + + if length == 10 then -- 0xAARRGGBB + alpha = band(rshift(v, 24), 0xFF) / 255 + r = floor(band(rshift(v, 16), 0xFF) * alpha) + g = floor(band(rshift(v, 8), 0xFF) * alpha) + b = floor(band(v, 0xFF) * alpha) + elseif length == 8 then -- 0xRRGGBB + r = band(rshift(v, 16), 0xFF) + g = band(rshift(v, 8), 0xFF) + b = band(v, 0xFF) + elseif length == 5 then -- 0xRGB + r = band(rshift(v, 8), 0xF) * 17 + g = band(rshift(v, 4), 0xF) * 17 + b = band(v, 0xF) * 17 + else 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 diff --git a/lua/colorizer/parser/hsl.lua b/lua/colorizer/parser/hsl.lua index cb6a19d..bc95a60 100644 --- a/lua/colorizer/parser/hsl.lua +++ b/lua/colorizer/parser/hsl.lua @@ -1,4 +1,3 @@ ----Helper function to parse argb local count = require("colorizer.utils").count local floor = math.floor @@ -100,7 +99,7 @@ function parser.hsl_function_parser(line, i, opts) end local r, g, b = hsl_to_rgb(h / 360, s / 100, l / 100) - if r == nil or g == nil or b == nil then + if not r or not g or not b then return end local rgb_hex = string.format("%02x%02x%02x", r * a, g * a, b * a) diff --git a/lua/colorizer/parser/names.lua b/lua/colorizer/parser/names.lua index 5261d70..6f76929 100644 --- a/lua/colorizer/parser/names.lua +++ b/lua/colorizer/parser/names.lua @@ -1,4 +1,3 @@ ----Helper function to parse argb local api = vim.api local bit = require "bit" diff --git a/lua/colorizer/parser/rgb.lua b/lua/colorizer/parser/rgb.lua index 2786a60..b6c9fa4 100644 --- a/lua/colorizer/parser/rgb.lua +++ b/lua/colorizer/parser/rgb.lua @@ -1,4 +1,3 @@ ----Helper function to parse argb local count = require("colorizer.utils").count local parser = {} diff --git a/lua/colorizer/parser/rgba_hex.lua b/lua/colorizer/parser/rgba_hex.lua index 0f16fbe..7699878 100644 --- a/lua/colorizer/parser/rgba_hex.lua +++ b/lua/colorizer/parser/rgba_hex.lua @@ -1,4 +1,3 @@ ----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 @@ -11,7 +10,6 @@ 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 diff --git a/lua/colorizer/sass.lua b/lua/colorizer/sass.lua index f4afc2c..d212526 100644 --- a/lua/colorizer/sass.lua +++ b/lua/colorizer/sass.lua @@ -30,7 +30,7 @@ local function remove_unused_imports(bufnr, import_name) end --- Cleanup sass variables and watch handlers ----@param bufnr number +---@param bufnr number: Buffer number function sass.cleanup(bufnr) remove_unused_imports(bufnr, api.nvim_buf_get_name(bufnr)) SASS[bufnr] = nil @@ -40,7 +40,7 @@ end -- check for value in SASS[buf].DEFINITIONS_ALL ---@param line string: Line to parse ---@param i number: Index of line from where to start parsing ----@param bufnr number +---@param bufnr number: Buffer number ---@return number|nil, string|nil function sass.name_parser(line, i, bufnr) local variable_name = line:match("^%$([%w_-]+)", i) @@ -235,7 +235,7 @@ end -- sass_parse_lines end --- Parse the given lines for sass variabled and add to `SASS[buf].DEFINITIONS_ALL`. -- which is then used in |sass_name_parser| -- If lines are not given, then fetch the lines with line_start and line_end ----@param bufnr number: buffer number (0 for current) +---@param bufnr number: Buffer number ---@param line_start number ---@param line_end number ---@param lines table|nil diff --git a/lua/colorizer/tailwind.lua b/lua/colorizer/tailwind.lua index f08e31c..57bf019 100644 --- a/lua/colorizer/tailwind.lua +++ b/lua/colorizer/tailwind.lua @@ -10,7 +10,7 @@ local DEFAULT_NAMESPACE_TAILWIND = api.nvim_create_namespace "colorizer_tailwind local TAILWIND = {} --- Cleanup tailwind variables and autocmd ----@param bufnr number: buffer number (0 for current) +---@param bufnr number: Buffer number (0 for current) function tailwind.cleanup(bufnr) if TAILWIND[bufnr] and TAILWIND[bufnr].AU_ID and TAILWIND[bufnr].AU_ID[1] then pcall(api.nvim_del_autocmd, TAILWIND[bufnr].AU_ID[1]) @@ -30,7 +30,7 @@ local function highlight_tailwind(bufnr, ns, options, add_highlight) local opts = { textDocument = vim.lsp.util.make_text_document_params() } TAILWIND[bufnr].CLIENT.request("textDocument/documentColor", opts, function(err, results, _, _) - if err == nil and results ~= nil then + if not err and results then local data, line_start, line_end = {}, nil, nil for _, color in pairs(results) do local cur_line = color.range.start.line @@ -67,7 +67,7 @@ end --- highlight buffer using values returned by tailwindcss -- To see these table information, see |colorizer.buffer| ----@param bufnr number: buffer number (0 for current) +---@param bufnr number: Buffer number (0 for current) ---@param options table ---@param options_local table ---@param add_highlight function diff --git a/test/expectation.txt b/test/expectation.txt index 24a17bf..ee828a2 100644 --- a/test/expectation.txt +++ b/test/expectation.txt @@ -1,8 +1,16 @@ -- vim:ft=lua require("colorizer").detach_from_buffer() -require("colorizer").attach_to_buffer(0, { AARRGGBB = true, css = true, mode = "foreground" }) +require("colorizer").attach_to_buffer(0, { + AARRGGBB = true, + css = true, + mode = "foreground", +}) --[[ SUCCESS -0xFf32A14B 0xFf32A14B +0xFf32A14B 0xFf32A14B +0x1B29FB 0x1B29FB +0xF0F 0xF0F +0xA3B67CDE 0x7F12D9A5 0x7E43F2 0x34E8D3 0xB3A 0x1CD + #32a14b #F0F #FF00FF #FFF00F8F #F0F #FF00FF @@ -31,6 +39,10 @@ hsla(360 , 50% , 50% , 1.0000000000000001) ]] --[[ FAIL +0xf32A14B 0xf32A14B +0xB29FB 0xB29FB +0x0F 0x0F +0x3B67CDE 0xF12D9A5 0xE43F2 0x4E8D3 0x3A 0xCD #--- #F0FF #F0FFF