Created
October 3, 2023 07:24
-
-
Save craftzdog/8012c78715414de7b5608bda08c77105 to your computer and use it in GitHub Desktop.
How to highlight HSL colors with `mini.hipatterns`
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- plugins/editor.lua | |
return { | |
{ | |
"echasnovski/mini.hipatterns", | |
event = "BufReadPre", | |
opts = { | |
highlighters = { | |
hsl_color = { | |
pattern = "hsl%(%d+,? %d+,? %d+%)", | |
group = function(_, match) | |
local utils = require("craftzdog.utils") | |
local h, s, l = match:match("hsl%((%d+),? (%d+),? (%d+)%)") | |
h, s, l = tonumber(h), tonumber(s), tonumber(l) | |
local hex_color = utils.hslToHex(h, s, l) | |
return MiniHipatterns.compute_hex_color_group(hex_color, "bg") | |
end, | |
}, | |
}, | |
}, | |
}, | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- craftzdog/utils.lua | |
-- https://github.com/EmmanuelOga/columns/blob/master/utils/color.lua | |
local M = {} | |
local hexChars = "0123456789abcdef" | |
function M.hex_to_rgb(hex) | |
hex = string.lower(hex) | |
local ret = {} | |
for i = 0, 2 do | |
local char1 = string.sub(hex, i * 2 + 2, i * 2 + 2) | |
local char2 = string.sub(hex, i * 2 + 3, i * 2 + 3) | |
local digit1 = string.find(hexChars, char1) - 1 | |
local digit2 = string.find(hexChars, char2) - 1 | |
ret[i + 1] = (digit1 * 16 + digit2) / 255.0 | |
end | |
return ret | |
end | |
--[[ | |
* Converts an RGB color value to HSL. Conversion formula | |
* adapted from http://en.wikipedia.org/wiki/HSL_color_space. | |
* Assumes r, g, and b are contained in the set [0, 255] and | |
* returns h, s, and l in the set [0, 1]. | |
* | |
* @param Number r The red color value | |
* @param Number g The green color value | |
* @param Number b The blue color value | |
* @return Array The HSL representation | |
]] | |
function M.rgbToHsl(r, g, b) | |
local max, min = math.max(r, g, b), math.min(r, g, b) | |
local h = 0 | |
local s = 0 | |
local l = 0 | |
l = (max + min) / 2 | |
if max == min then | |
h, s = 0, 0 -- achromatic | |
else | |
local d = max - min | |
if l > 0.5 then | |
s = d / (2 - max - min) | |
else | |
s = d / (max + min) | |
end | |
if max == r then | |
h = (g - b) / d | |
if g < b then | |
h = h + 6 | |
end | |
elseif max == g then | |
h = (b - r) / d + 2 | |
elseif max == b then | |
h = (r - g) / d + 4 | |
end | |
h = h / 6 | |
end | |
return h * 360, s * 100, l * 100 | |
end | |
--[[ | |
* Converts an HSL color value to RGB. Conversion formula | |
* adapted from http://en.wikipedia.org/wiki/HSL_color_space. | |
* Assumes h, s, and l are contained in the set [0, 1] and | |
* returns r, g, and b in the set [0, 255]. | |
* | |
* @param Number h The hue | |
* @param Number s The saturation | |
* @param Number l The lightness | |
* @return Array The RGB representation | |
]] | |
function M.hslToRgb(h, s, l) | |
local r, g, b | |
if s == 0 then | |
r, g, b = l, l, l -- achromatic | |
else | |
function hue2rgb(p, q, t) | |
if t < 0 then | |
t = t + 1 | |
end | |
if t > 1 then | |
t = t - 1 | |
end | |
if t < 1 / 6 then | |
return p + (q - p) * 6 * t | |
end | |
if t < 1 / 2 then | |
return q | |
end | |
if t < 2 / 3 then | |
return p + (q - p) * (2 / 3 - t) * 6 | |
end | |
return p | |
end | |
local q | |
if l < 0.5 then | |
q = l * (1 + s) | |
else | |
q = l + s - l * s | |
end | |
local p = 2 * l - q | |
r = hue2rgb(p, q, h + 1 / 3) | |
g = hue2rgb(p, q, h) | |
b = hue2rgb(p, q, h - 1 / 3) | |
end | |
return r * 255, g * 255, b * 255 | |
end | |
function M.hexToHSL(hex) | |
local hsluv = require("solarized-osaka.hsluv") | |
local rgb = M.hex_to_rgb(hex) | |
local h, s, l = M.rgbToHsl(rgb[1], rgb[2], rgb[3]) | |
return string.format("hsl(%d, %d, %d)", math.floor(h + 0.5), math.floor(s + 0.5), math.floor(l + 0.5)) | |
end | |
--[[ | |
* Converts an HSL color value to RGB in Hex representation. | |
* @param Number h The hue | |
* @param Number s The saturation | |
* @param Number l The lightness | |
* @return String The hex representation | |
]] | |
function M.hslToHex(h, s, l) | |
local r, g, b = M.hslToRgb(h / 360, s / 100, l / 100) | |
return string.format("#%02x%02x%02x", r, g, b) | |
end | |
function M.replaceHexWithHSL() | |
-- Get the current line number | |
local line_number = vim.api.nvim_win_get_cursor(0)[1] | |
-- Get the line content | |
local line_content = vim.api.nvim_buf_get_lines(0, line_number - 1, line_number, false)[1] | |
-- Find hex code patterns and replace them | |
for hex in line_content:gmatch("#[0-9a-fA-F]+") do | |
local hsl = M.hexToHSL(hex) | |
line_content = line_content:gsub(hex, hsl) | |
end | |
-- Set the line content back | |
vim.api.nvim_buf_set_lines(0, line_number - 1, line_number, false, { line_content }) | |
end | |
return M |
[...] On the
return MiniHipatterns.compute_hex_color_group(hex_color, "bg")
I have a warningUndefined global 'MiniHiPatterns'.
. I can't understand how is this line working, maybe that could be the source of my problem ?
In the original snippet, MiniHiPatterns
is the plugin mini.patterns
assigned to a variable.
Its definition isn't in the gist, which is why you're seeing an error.
You should define it yourself in the group
function (or wherever else you need it):
group = function(_, match)
local MiniHiPatterns = require('mini.hipatterns')`
-- ...rest of function
end
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi !
Sorry to bother you, I'm also interested in this feature and can't make it work.
I've used your code
mini.hipatterns
config as it is (I've only just put the used functionshslToRgb
andhslToHex
inside the same lua file, in order to not used autils
module).With
vim.inspect
, I manage to print the HEX color computed from each line with the HSL pattern, and that is correct (more or less, but I think there are only rounding approx, which is fine for me).Nevertheless, I can't get any higlighting working.
On the
return MiniHipatterns.compute_hex_color_group(hex_color, "bg")
I have a warning
Undefined global 'MiniHiPatterns'.
. I can't understand how is this line working, maybe that could be the source of my problem ?Is this gist working as it is ?
After that, I want to update the pattern to make it work for string such as
"100 15.1% 10%"
(without anyhsl()
) that you can find in nextjs/shadcn themes for example.Thanks a lot !