Add 256-color and truecolor SGR helpers

Extended ansi.py with fg_256, bg_256, fg_rgb, and bg_rgb functions
for generating 256-color and truecolor escape sequences. All functions
include value clamping to valid ranges (0-255).
This commit is contained in:
Jared Miller 2026-02-07 22:20:47 -05:00
parent 388e693f8c
commit 6549d09683
Signed by: shmup
GPG key ID: 22B5C6D66A38B06C
2 changed files with 129 additions and 1 deletions

View file

@ -51,3 +51,63 @@ def colorize_map(grid: list[list[str]]) -> str:
colored_row = "".join(colorize_terrain(char) for char in row)
lines.append(colored_row)
return "\n".join(lines)
def fg_256(n: int) -> str:
"""Generate 256-color foreground escape code.
Args:
n: Color index (0-255). Values outside range are clamped.
Returns:
ANSI escape sequence for 256-color foreground.
"""
clamped = max(0, min(255, n))
return f"\033[38;5;{clamped}m"
def bg_256(n: int) -> str:
"""Generate 256-color background escape code.
Args:
n: Color index (0-255). Values outside range are clamped.
Returns:
ANSI escape sequence for 256-color background.
"""
clamped = max(0, min(255, n))
return f"\033[48;5;{clamped}m"
def fg_rgb(r: int, g: int, b: int) -> str:
"""Generate truecolor foreground escape code.
Args:
r: Red component (0-255). Values outside range are clamped.
g: Green component (0-255). Values outside range are clamped.
b: Blue component (0-255). Values outside range are clamped.
Returns:
ANSI escape sequence for truecolor foreground.
"""
r_clamped = max(0, min(255, r))
g_clamped = max(0, min(255, g))
b_clamped = max(0, min(255, b))
return f"\033[38;2;{r_clamped};{g_clamped};{b_clamped}m"
def bg_rgb(r: int, g: int, b: int) -> str:
"""Generate truecolor background escape code.
Args:
r: Red component (0-255). Values outside range are clamped.
g: Green component (0-255). Values outside range are clamped.
b: Blue component (0-255). Values outside range are clamped.
Returns:
ANSI escape sequence for truecolor background.
"""
r_clamped = max(0, min(255, r))
g_clamped = max(0, min(255, g))
b_clamped = max(0, min(255, b))
return f"\033[48;2;{r_clamped};{g_clamped};{b_clamped}m"

View file

@ -1,4 +1,12 @@
from mudlib.render.ansi import RESET, colorize_map, colorize_terrain
from mudlib.render.ansi import (
RESET,
bg_256,
bg_rgb,
colorize_map,
colorize_terrain,
fg_256,
fg_rgb,
)
def test_colorize_terrain_grass():
@ -45,3 +53,63 @@ def test_colorize_map():
# should have ANSI codes
assert "\033[" in result
def test_fg_256_basic():
"""Generate 256-color foreground code."""
assert fg_256(0) == "\033[38;5;0m"
assert fg_256(15) == "\033[38;5;15m"
assert fg_256(42) == "\033[38;5;42m"
assert fg_256(255) == "\033[38;5;255m"
def test_bg_256_basic():
"""Generate 256-color background code."""
assert bg_256(0) == "\033[48;5;0m"
assert bg_256(15) == "\033[48;5;15m"
assert bg_256(42) == "\033[48;5;42m"
assert bg_256(255) == "\033[48;5;255m"
def test_fg_256_clamping():
"""Clamp 256-color values to valid range (0-255)."""
assert fg_256(-1) == "\033[38;5;0m"
assert fg_256(256) == "\033[38;5;255m"
assert fg_256(999) == "\033[38;5;255m"
def test_bg_256_clamping():
"""Clamp 256-color values to valid range (0-255)."""
assert bg_256(-1) == "\033[48;5;0m"
assert bg_256(256) == "\033[48;5;255m"
assert bg_256(999) == "\033[48;5;255m"
def test_fg_rgb_basic():
"""Generate truecolor foreground code."""
assert fg_rgb(0, 0, 0) == "\033[38;2;0;0;0m"
assert fg_rgb(255, 255, 255) == "\033[38;2;255;255;255m"
assert fg_rgb(128, 64, 192) == "\033[38;2;128;64;192m"
def test_bg_rgb_basic():
"""Generate truecolor background code."""
assert bg_rgb(0, 0, 0) == "\033[48;2;0;0;0m"
assert bg_rgb(255, 255, 255) == "\033[48;2;255;255;255m"
assert bg_rgb(128, 64, 192) == "\033[48;2;128;64;192m"
def test_fg_rgb_clamping():
"""Clamp RGB values to valid range (0-255)."""
assert fg_rgb(-1, 0, 0) == "\033[38;2;0;0;0m"
assert fg_rgb(0, 300, 0) == "\033[38;2;0;255;0m"
assert fg_rgb(0, 0, 999) == "\033[38;2;0;0;255m"
assert fg_rgb(-10, 300, 500) == "\033[38;2;0;255;255m"
def test_bg_rgb_clamping():
"""Clamp RGB values to valid range (0-255)."""
assert bg_rgb(-1, 0, 0) == "\033[48;2;0;0;0m"
assert bg_rgb(0, 300, 0) == "\033[48;2;0;255;0m"
assert bg_rgb(0, 0, 999) == "\033[48;2;0;0;255m"
assert bg_rgb(-10, 300, 500) == "\033[48;2;0;255;255m"