116 lines
3.5 KiB
Python
116 lines
3.5 KiB
Python
"""Color markup engine for prompt templates."""
|
|
|
|
import re
|
|
|
|
from mudlib.render import ansi
|
|
|
|
# Tag to ANSI code mapping for 16-color mode
|
|
COLOR_TAGS_16 = {
|
|
"red": ansi.RED,
|
|
"green": ansi.GREEN,
|
|
"yellow": ansi.YELLOW,
|
|
"blue": ansi.BLUE,
|
|
"magenta": ansi.MAGENTA,
|
|
"cyan": ansi.CYAN,
|
|
"white": ansi.WHITE,
|
|
"black": ansi.BLACK,
|
|
"RED": "\033[91m",
|
|
"GREEN": "\033[92m",
|
|
"YELLOW": "\033[93m",
|
|
"BLUE": "\033[94m",
|
|
"MAGENTA": "\033[95m",
|
|
"CYAN": "\033[96m",
|
|
"WHITE": "\033[97m",
|
|
"BLACK": "\033[90m",
|
|
"bold": ansi.BOLD,
|
|
"dim": "\033[2m",
|
|
"/": ansi.RESET,
|
|
"reset": ansi.RESET,
|
|
}
|
|
|
|
# Tag to ANSI code mapping for 256-color mode
|
|
COLOR_TAGS_256 = {
|
|
"red": ansi.fg_256(196),
|
|
"green": ansi.fg_256(46),
|
|
"yellow": ansi.fg_256(226),
|
|
"blue": ansi.fg_256(33),
|
|
"magenta": ansi.fg_256(201),
|
|
"cyan": ansi.fg_256(51),
|
|
"white": ansi.fg_256(231),
|
|
"black": ansi.fg_256(16),
|
|
"RED": ansi.fg_256(9),
|
|
"GREEN": ansi.fg_256(10),
|
|
"YELLOW": ansi.fg_256(11),
|
|
"BLUE": ansi.fg_256(12),
|
|
"MAGENTA": ansi.fg_256(13),
|
|
"CYAN": ansi.fg_256(14),
|
|
"WHITE": ansi.fg_256(15),
|
|
"BLACK": ansi.fg_256(8),
|
|
"bold": ansi.BOLD,
|
|
"dim": "\033[2m",
|
|
"/": ansi.RESET,
|
|
"reset": ansi.RESET,
|
|
}
|
|
|
|
# Tag to ANSI code mapping for truecolor mode
|
|
COLOR_TAGS_TRUECOLOR = {
|
|
"red": ansi.fg_rgb(244, 67, 54),
|
|
"green": ansi.fg_rgb(76, 175, 80),
|
|
"yellow": ansi.fg_rgb(255, 235, 59),
|
|
"blue": ansi.fg_rgb(33, 150, 243),
|
|
"magenta": ansi.fg_rgb(156, 39, 176),
|
|
"cyan": ansi.fg_rgb(0, 188, 212),
|
|
"white": ansi.fg_rgb(255, 255, 255),
|
|
"black": ansi.fg_rgb(0, 0, 0),
|
|
"RED": ansi.fg_rgb(255, 82, 82),
|
|
"GREEN": ansi.fg_rgb(105, 240, 174),
|
|
"YELLOW": ansi.fg_rgb(255, 255, 130),
|
|
"BLUE": ansi.fg_rgb(68, 138, 255),
|
|
"MAGENTA": ansi.fg_rgb(224, 64, 251),
|
|
"CYAN": ansi.fg_rgb(0, 229, 255),
|
|
"WHITE": ansi.fg_rgb(255, 255, 255),
|
|
"BLACK": ansi.fg_rgb(96, 96, 96),
|
|
"bold": ansi.BOLD,
|
|
"dim": "\033[2m",
|
|
"/": ansi.RESET,
|
|
"reset": ansi.RESET,
|
|
}
|
|
|
|
|
|
def colorize(text: str, color_depth: str | None) -> str:
|
|
"""Convert color markup tags to ANSI codes based on client color depth.
|
|
|
|
Processes markup tags like {red}, {bold}, {/} in template strings and
|
|
converts them to ANSI escape codes. Unknown tags that don't match known
|
|
color tags are preserved (assumed to be template variables like {hp}).
|
|
|
|
Args:
|
|
text: String with color markup tags
|
|
color_depth: Color mode - "16", "256", "truecolor", or None/empty to strip
|
|
|
|
Returns:
|
|
Text with markup tags replaced by ANSI codes (or stripped if no color support)
|
|
"""
|
|
# If no color support, strip all known color tags
|
|
if not color_depth:
|
|
# Build pattern of all known tag names
|
|
known_tags = set(COLOR_TAGS_16.keys())
|
|
pattern = r"\{(" + "|".join(re.escape(tag) for tag in known_tags) + r")\}"
|
|
return re.sub(pattern, "", text)
|
|
|
|
# Select tag mapping based on color depth
|
|
if color_depth == "truecolor":
|
|
tag_map = COLOR_TAGS_TRUECOLOR
|
|
elif color_depth == "256":
|
|
tag_map = COLOR_TAGS_256
|
|
else: # default to 16-color
|
|
tag_map = COLOR_TAGS_16
|
|
|
|
# Replace known color tags with ANSI codes
|
|
def replace_tag(match):
|
|
return tag_map[match.group(1)]
|
|
|
|
# Pattern matches {tagname} where tagname is in our known tags
|
|
known_tags = "|".join(re.escape(tag) for tag in tag_map)
|
|
pattern = r"\{(" + known_tags + r")\}"
|
|
return re.sub(pattern, replace_tag, text)
|