Skip to content

Commit c6154cb

Browse files
authored
feat(colors): allow custom color to be a number (#107)
1 parent 60ecf29 commit c6154cb

File tree

5 files changed

+72
-54
lines changed

5 files changed

+72
-54
lines changed

README.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@ require("one_monokai").setup({
5151

5252
### Available Options
5353

54-
| Option | Description | Type | Note |
55-
| ------------- | -------------------------------- | -------------------------- | ---------------- |
56-
| `transparent` | Enables a transparent background | `boolean` | N/A |
57-
| `colors` | Custom color definitions | `table<string, string>` | N/A |
58-
| `highlights` | Custom highlight groups | `function(colors): table` | `:h nvim_set_hl` |
59-
| `italics` | Enables italic | `boolean` | N/A |
54+
| Option | Description | Type | Note |
55+
| ------------- | -------------------------------- | ------------------------------- | ---------------- |
56+
| `transparent` | Enables a transparent background | `boolean` | N/A |
57+
| `colors` | Custom color definitions | `table<string, string\|number>` | N/A |
58+
| `highlights` | Custom highlight groups | `function(colors): table` | `:h nvim_set_hl` |
59+
| `italics` | Enables italic | `boolean` | N/A |
6060

6161
### Default Configuration
6262

@@ -91,8 +91,10 @@ colors["<color-name>"]:lighten(alpha)
9191
require("one_monokai").setup({
9292
transparent = true, -- Enable transparent background
9393
colors = {
94-
lmao = "#ffffff", -- Define a new color
9594
pink = "#ec6075", -- Override a default color
95+
lmao = "#ffffff", -- Define a new color as hexadecimal string
96+
human = 0xFFABCD, -- Define a new color as number
97+
alien = 16755661, -- Why not?
9698
},
9799
highlights = function(colors)
98100
-- Customize highlight groups
@@ -109,7 +111,7 @@ require("one_monokai").setup({
109111
```
110112

111113
> [!TIP]
112-
> To find the highlight group for an item, place the cursor inside it and run `:Inspect`. Refer to `:h :Inspect` for more information.
114+
> To find the highlight group for an item, place the cursor under it and run `:Inspect`. Refer to `:h :Inspect` for more information.
113115
114116
## :champagne: Plugin Support
115117

lua/one_monokai/colors.lua

Lines changed: 52 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,11 @@ local defaults = {
3030
---@type colors
3131
colors = vim.deepcopy(defaults)
3232

33-
---Convert hex value to rgb
34-
---@param color string
33+
---Converts a hex color to an RGB table
34+
---@param color string #Hex color
35+
---@return integer[] #RGB table {r, g, b}
3536
local function hex2rgb(color)
36-
color = string.lower(color)
37+
color = color:lower()
3738

3839
return {
3940
tonumber(color:sub(2, 3), 16),
@@ -42,69 +43,79 @@ local function hex2rgb(color)
4243
}
4344
end
4445

45-
---@param fg string #foreground color
46-
---@param bg string #background color
47-
---@param alpha number #number between 0 and 1.
48-
---@source: https://github.com/folke/tokyonight.nvim/blob/main/lua/tokyonight/util.lua#L9-L37
46+
---Blends two hex colors together based on the alpha value.
47+
---
48+
---[View source](https://github.com/folke/tokyonight.nvim/blob/main/lua/tokyonight/util.lua)
49+
---@param fg string #Foreground hex color
50+
---@param bg string #Background hex color
51+
---@param alpha number #Blend factor between 0 (only bg) and 1 (only fg)
52+
---@return string #Hex color of the resulting blended color
4953
local function blend(fg, bg, alpha)
5054
local bg_rgb = hex2rgb(bg)
5155
local fg_rgb = hex2rgb(fg)
5256

53-
local blend_channel = function(i)
54-
local ret = (alpha * fg_rgb[i] + ((1 - alpha) * bg_rgb[i]))
57+
local r = alpha * fg_rgb[1] + (1 - alpha) * bg_rgb[1] + 0.5
58+
local g = alpha * fg_rgb[2] + (1 - alpha) * bg_rgb[2] + 0.5
59+
local b = alpha * fg_rgb[3] + (1 - alpha) * bg_rgb[3] + 0.5
5560

56-
return math.floor(math.min(math.max(0, ret), 255) + 0.5)
57-
end
58-
59-
return ("#%02x%02x%02x"):format(blend_channel(1), blend_channel(2), blend_channel(3))
61+
return ("#%02x%02x%02x"):format(r, g, b)
6062
end
6163

62-
---@param alpha number #number between 0 and 1
63-
function string:darken(alpha)
64-
return blend(self, "#000000", alpha)
64+
---Darkens the current hex color
65+
---@param s string
66+
---@param alpha number #Value between 0 and 1
67+
function string.darken(s, alpha)
68+
return blend(s, "#000000", alpha)
6569
end
6670

67-
---@param alpha number #number between 0 and 1
68-
function string:lighten(alpha)
69-
return blend(self, "#ffffff", alpha)
71+
---Lightens the current hex color
72+
---@param s string
73+
---@param alpha number #Value between 0 and 1
74+
function string.lighten(s, alpha)
75+
return blend(s, "#ffffff", alpha)
7076
end
7177

72-
---Get the hex value of a color
73-
---@param name string #name of the color
74-
---@param value any #value of the color
75-
---@return string? #hex string or `nil` if invalid
76-
local function get_hex_value(name, value)
77-
local logs = require "one_monokai.logs"
78+
---Resolve and retrieve the value of a color
79+
---@param name string #Name of the color
80+
---@param value string|number #Value of the color
81+
---@return string|number? #Hex color or 24-bit RGB value, or default if invalid
82+
local function resolve_color(name, value)
83+
local color_type = type(value)
7884

79-
local type_ok, err = pcall(vim.validate, {
80-
["colors(" .. name .. ")"] = { value, "string" },
81-
})
85+
-- Resolve string first to optimize the common case
86+
if color_type == "string" then
87+
if value:lower() == "none" then
88+
return value
89+
end
8290

83-
if not type_ok then
84-
logs.error(err)
91+
local rgb = vim.api.nvim_get_color_by_name(value)
8592

86-
return defaults[name]
93+
if rgb ~= -1 then
94+
return value
95+
end
8796
end
8897

89-
if value:lower() == "none" then
98+
if color_type == "number" and value >= 0 and value <= 0xFFFFFF then
9099
return value
91100
end
92101

93-
local rgb = vim.api.nvim_get_color_by_name(value)
94-
95-
if rgb == -1 then
96-
logs.error("colors(%s): %q is not a valid color", name, value)
102+
local logs = require "one_monokai.logs"
103+
local default = defaults[name]
97104

98-
return defaults[name]
99-
end
105+
logs.error(
106+
"colors(%s): expected hex color (#rrggbb) or 24-bit RGB color, got %q. Fallback to %q.",
107+
name,
108+
value,
109+
default
110+
)
100111

101-
return ("#%06x"):format(rgb)
112+
return default
102113
end
103114

104115
local config = require "one_monokai.config"
105116

106-
for name, value in pairs(config.colors) do
107-
colors[name] = get_hex_value(name, value)
117+
for name, value in pairs(config.colors or {}) do
118+
colors[name] = resolve_color(name, value)
108119
end
109120

110121
return colors

lua/one_monokai/config.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ local config = {}
22

33
---@class options
44
---@field transparent boolean #Whether to enable transparent background
5-
---@field colors colors #Custom colors
5+
---@field colors? colors #Custom colors
66
---@field highlights? fun(colors:colors):groups #Custom highlight groups
77
---@field italics boolean #Whether to apply italics to certain highlight groups
88
local defaults = {
99
transparent = false,
10-
colors = {},
10+
colors = nil,
1111
---@deprecated
1212
themes = nil,
1313
highlights = nil,

tests/spec/color_spec.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ describe("Override config with color utility", function()
66
colors = {
77
lmao = "#812873",
88
},
9-
themes = function(c)
9+
highlights = function(c)
1010
return {
1111
Normal = { fg = c.lmao:darken(0.5) },
1212
}
@@ -25,7 +25,7 @@ describe("Override config with color utility", function()
2525
colors = {
2626
lmao = "#812873",
2727
},
28-
themes = function(c)
28+
highlights = function(c)
2929
return {
3030
Normal = { fg = c.lmao:lighten(0.5) },
3131
}

tests/spec/config_spec.lua

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ local one_monokai = require "one_monokai"
33

44
describe("Config options", function()
55
it("could be indexed without options field", function()
6-
assert.are.same({}, config.colors)
6+
assert.is_false(config.transparent)
7+
assert.is_nil(config.colors)
8+
assert.is_true(config.italics)
79
end)
810
end)
911

@@ -12,6 +14,7 @@ describe("Override config", function()
1214
colors = {
1315
pink = "#61afef",
1416
lmao = "#dedeff",
17+
alien = 0xABCDFF,
1518
},
1619
highlights = function(c)
1720
return {
@@ -35,6 +38,8 @@ describe("Override config", function()
3538
assert.equal(expected.colors.pink, colors.pink)
3639
---@diagnostic disable-next-line: undefined-field
3740
assert.equal(expected.colors.lmao, colors.lmao)
41+
---@diagnostic disable-next-line: undefined-field
42+
assert.equal(expected.colors.alien, colors.alien)
3843
end)
3944

4045
it("should change default highlights", function()

0 commit comments

Comments
 (0)