Skip to main content

text: add a coloured function to print text with ANSI escape codes

ID
a318488
date
2026-05-14 18:24:54+00:00
author
Alex Chan <alex@alexwlchan.net>
parent
37bd7f6
message
text: add a `coloured` function to print text with ANSI escape codes
changed files
4 files, 57 additions, 2 deletions

Changed files

CHANGELOG.md (4771) → CHANGELOG.md (4868)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e9ba370..6d3d191 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # CHANGELOG
 
+## v40 - 2026-05-14
+
+Add a function `text.coloured()` for printing text with ANSI escape codes.
+
 ## v39 - 2026-05-09
 
 Remove some debugging code that was left in v38.

src/chives/__init__.py (391) → src/chives/__init__.py (391)

diff --git a/src/chives/__init__.py b/src/chives/__init__.py
index e42c280..ee2ecdb 100644
--- a/src/chives/__init__.py
+++ b/src/chives/__init__.py
@@ -11,4 +11,4 @@ I share across multiple sites.
 
 """
 
-__version__ = "39"
+__version__ = "40"

src/chives/text.py (215) → src/chives/text.py (789)

diff --git a/src/chives/text.py b/src/chives/text.py
index 8b461a7..532c5ec 100644
--- a/src/chives/text.py
+++ b/src/chives/text.py
@@ -2,11 +2,38 @@
 Functions for dealing with text.
 """
 
+from typing import Literal
+
 from chives.smartypants import smartypants
 
 
+__all__ = ["smartify", "coloured"]
+
+
 def smartify(text: str) -> str:
     """
     Add curly quotes and smart dashes to a string.
     """
     return smartypants(text)
+
+
+TextColour = Literal["red", "yellow", "green", "blue"]
+
+
+def coloured(text: str, colour: TextColour) -> str:
+    """
+    Add ANSI escape codes to print text in a colour.
+    """
+    try:
+        start_code = {
+            "red": "\033[91m",
+            "yellow": "\033[93m",
+            "green": "\033[92m",
+            "blue": "\033[94m",
+        }[colour]
+    except KeyError:
+        raise ValueError(f"unrecognised colour: {colour!r}")
+
+    end_code = "\033[0m"
+
+    return start_code + text + end_code

tests/test_text.py (1535) → tests/test_text.py (2299)

diff --git a/tests/test_text.py b/tests/test_text.py
index 1f561b0..da9a1e1 100644
--- a/tests/test_text.py
+++ b/tests/test_text.py
@@ -4,7 +4,7 @@ Tests for `chives.text`.
 
 import pytest
 
-from chives.text import smartify
+from chives.text import coloured, smartify, TextColour
 
 
 @pytest.mark.parametrize(
@@ -55,3 +55,27 @@ def test_is_unchanged_by_smartify(text: str) -> None:
     Test these strings are unaffected by "smart" punctuation.
     """
     assert smartify(text) == text
+
+
+@pytest.mark.parametrize(
+    "text, colour, expected",
+    [
+        ("hello world", "red", "\033[91mhello world\033[0m"),
+        ("hello world", "yellow", "\033[93mhello world\033[0m"),
+        ("hello world", "green", "\033[92mhello world\033[0m"),
+        ("hello world", "blue", "\033[94mhello world\033[0m"),
+    ],
+)
+def test_coloured(text: str, colour: TextColour, expected: str) -> None:
+    """
+    Tests for `coloured`.
+    """
+    assert coloured(text, colour) == expected
+
+
+def test_unrecognised_colour() -> None:
+    """
+    Calling `coloured` with an unrecognised colour is a ValueError.
+    """
+    with pytest.raises(ValueError, match="unrecognised colour"):
+        coloured("hello world", colour="gray")  # type: ignore