Skip to content

Commit b717d5d

Browse files
committed
add support for named colors
1 parent 56a0627 commit b717d5d

File tree

3 files changed

+37
-12
lines changed

3 files changed

+37
-12
lines changed

docs/source/configure.rst

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ Color and displayname
2828
---------------------
2929

3030
- You can set a color for each task list by creating a ``color`` file containing
31-
a color code in the hex format: ``#RRGGBB``.
31+
either a named ANSI color (such as ``red``, ``bright blue``, etc) or a color
32+
code in hex format: ``#RRGGBB`` (the latter requires 24-bit color support).
3233
- A file named ``displayname`` indicates how the task list should be named and
3334
is needed when there are multiple directories sharing a name, e.g.: when using
3435
multiple $CloudInstances. The default is the directory name.

tests/test_formatter.py

+9-7
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from tests.helpers import pyicu_sensitive
1111
from todoman.cli import cli
12-
from todoman.formatters import rgb_to_ansi
12+
from todoman.formatters import colour_to_ansi
1313

1414

1515
@pyicu_sensitive
@@ -155,12 +155,14 @@ def test_formatting_parsing_consitency(default_formatter):
155155
assert default_formatter.parse_datetime(formatted) == dt
156156

157157

158-
def test_rgb_to_ansi():
159-
assert rgb_to_ansi(None) is None
160-
assert rgb_to_ansi("#8ab6d") is None
161-
assert rgb_to_ansi("#8ab6d2f") == "\x1b[38;2;138;182;210m"
162-
assert rgb_to_ansi("red") is None
163-
assert rgb_to_ansi("#8ab6d2") == "\x1b[38;2;138;182;210m"
158+
def test_colour_to_ansi():
159+
assert colour_to_ansi(None) is None
160+
assert colour_to_ansi("#8ab6d") is None
161+
assert colour_to_ansi("#8ab6d2f") == "\x1b[38;2;138;182;210m"
162+
assert colour_to_ansi("#8ab6d2") == "\x1b[38;2;138;182;210m"
163+
assert colour_to_ansi("red") == "\x1b[31m"
164+
assert colour_to_ansi("bright cyan") == "\x1b[36;1m"
165+
assert colour_to_ansi("salmon") is None
164166

165167

166168
def test_format_multiple_with_list(default_formatter, todo_factory):

todoman/formatters.py

+26-4
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,10 @@
1919
from todoman.model import TodoList
2020

2121

22-
def rgb_to_ansi(colour: Optional[str]) -> Optional[str]:
22+
def rgb_to_ansi(colour: str) -> Optional[str]:
2323
"""
2424
Convert a string containing an RGB colour to ANSI escapes
2525
"""
26-
if not colour or not colour.startswith("#"):
27-
return None
2826

2927
r, g, b = colour[1:3], colour[3:5], colour[5:7]
3028

@@ -34,6 +32,30 @@ def rgb_to_ansi(colour: Optional[str]) -> Optional[str]:
3432
return f"\33[38;2;{int(r, 16)!s};{int(g, 16)!s};{int(b, 16)!s}m"
3533

3634

35+
def colour_to_ansi(colour: Optional[str]) -> Optional[str]:
36+
"""
37+
Convert a string containing a colour (either RGB or colour name) to ANSI escapes
38+
"""
39+
if not colour:
40+
return None
41+
if colour.startswith("#"):
42+
return rgb_to_ansi(colour)
43+
44+
bright = "bright" in colour
45+
46+
colour = colour.replace("bright ", "")
47+
48+
colours = ["black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"]
49+
50+
try:
51+
ansi_number = colours.index(colour)
52+
except ValueError:
53+
return None
54+
55+
suffix = ";1" if bright else ""
56+
return f"\33[3{ansi_number}{suffix}m"
57+
58+
3759
class DefaultFormatter:
3860
def __init__(
3961
self,
@@ -227,7 +249,7 @@ def _parse_datetime_naive(self, dt: str) -> date:
227249

228250
def format_database(self, database: TodoList):
229251
return "{}@{}".format(
230-
rgb_to_ansi(database.colour) or "", click.style(database.name)
252+
colour_to_ansi(database.colour) or "", click.style(database.name)
231253
)
232254

233255

0 commit comments

Comments
 (0)