Skip to content

Commit 65113e6

Browse files
authored
feat: add hsl/hsla properties to colours (#21)
1 parent fbdac64 commit 65113e6

File tree

4 files changed

+77
-0
lines changed

4 files changed

+77
-0
lines changed

catppuccin/colour.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
from dataclasses import dataclass
88
from typing import Any, Tuple
99

10+
from catppuccin.hsl import rgb_to_hsl
11+
1012

1113
@dataclass(frozen=True)
1214
class Colour:
@@ -27,6 +29,16 @@ def rgba(self) -> Tuple[int, int, int, int]:
2729
"""Get the colour as a 4-tuple of red, green, blue, and alpha."""
2830
return self.red, self.green, self.blue, self.alpha
2931

32+
@property
33+
def hsl(self) -> Tuple[float, float, float]:
34+
"""Get the colour as a 3-tuple of hue, saturation, and lightness."""
35+
return rgb_to_hsl(*self.rgb)
36+
37+
@property
38+
def hsla(self) -> Tuple[float, float, float, float]:
39+
"""Get the colour as a 4-tuple of hue, saturation, lightness, and alpha."""
40+
return (*self.hsl, self.alpha)
41+
3042
@property
3143
def hex(self) -> str:
3244
"""Get the colour as a lowercase hex string."""

catppuccin/hsl.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""
2+
Utilities for working with HSL colours.
3+
"""
4+
from __future__ import annotations
5+
6+
from typing import Tuple
7+
8+
9+
# pylint: disable=invalid-name
10+
def rgb_to_hsl(r: int, g: int, b: int) -> Tuple[int, float, float]:
11+
"""Convert RGB to HSL."""
12+
r1 = r / 255
13+
g1 = g / 255
14+
b1 = b / 255
15+
16+
cmax = max(r1, g1, b1)
17+
cmin = min(r1, g1, b1)
18+
delta = cmax - cmin
19+
20+
if delta == 0:
21+
h = 0.0
22+
elif cmax == r1:
23+
h = ((g1 - b1) / delta) % 6
24+
elif cmax == g1:
25+
h = (b1 - r1) / delta + 2
26+
else:
27+
h = (r1 - g1) / delta + 4
28+
29+
h = round(h * 60)
30+
if h < 0:
31+
h += 360
32+
33+
l = (cmax + cmin) / 2
34+
35+
if delta == 0:
36+
s = 0.0
37+
else:
38+
s = delta / (1 - abs(2 * l - 1))
39+
40+
return h, round(s, 2), round(l, 2)

tests/test_colour.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,18 @@ def test_colour_to_rgba_default():
1515
assert Colour(12, 123, 234).rgba == (12, 123, 234, 255)
1616

1717

18+
def test_colour_to_hsl():
19+
assert Colour(12, 123, 234).hsl == (210, 0.90, 0.48)
20+
21+
22+
def test_colour_to_hsla():
23+
assert Colour(12, 123, 234, 35).hsla == (210, 0.90, 0.48, 35)
24+
25+
26+
def test_colour_to_hsla_default():
27+
assert Colour(12, 123, 234).hsla == (210, 0.90, 0.48, 255)
28+
29+
1830
def test_rgb_colour_to_hex():
1931
assert Colour(0x12, 0xEB, 0x77).hex == "12eb77"
2032

tests/test_hsl.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from catppuccin import Flavour
2+
from catppuccin.hsl import rgb_to_hsl
3+
4+
mocha = Flavour.mocha()
5+
latte = Flavour.latte()
6+
7+
8+
def test_rgb_to_hsl():
9+
hsl = rgb_to_hsl(*mocha.mauve.rgb)
10+
assert hsl == (267, 0.84, 0.81)
11+
12+
hsl = rgb_to_hsl(*latte.text.rgb)
13+
assert hsl == (234, 0.16, 0.35)

0 commit comments

Comments
 (0)