cpython/Lib/_colorize.py

164 lines
3.8 KiB
Python
Raw Normal View History

from __future__ import annotations
import io
import os
import sys
COLORIZE = True
# types
if False:
from typing import IO, Literal
type ColorTag = Literal[
"PROMPT",
"KEYWORD",
"BUILTIN",
"COMMENT",
"STRING",
"NUMBER",
"OP",
"DEFINITION",
"SOFT_KEYWORD",
"RESET",
]
theme: dict[ColorTag, str]
class ANSIColors:
RESET = "\x1b[0m"
BLACK = "\x1b[30m"
BLUE = "\x1b[34m"
CYAN = "\x1b[36m"
GREEN = "\x1b[32m"
GREY = "\x1b[90m"
MAGENTA = "\x1b[35m"
RED = "\x1b[31m"
WHITE = "\x1b[37m" # more like LIGHT GRAY
YELLOW = "\x1b[33m"
BOLD = "\x1b[1m"
BOLD_BLACK = "\x1b[1;30m" # DARK GRAY
BOLD_BLUE = "\x1b[1;34m"
BOLD_CYAN = "\x1b[1;36m"
BOLD_GREEN = "\x1b[1;32m"
BOLD_MAGENTA = "\x1b[1;35m"
BOLD_RED = "\x1b[1;31m"
BOLD_WHITE = "\x1b[1;37m" # actual WHITE
BOLD_YELLOW = "\x1b[1;33m"
# intense = like bold but without being bold
INTENSE_BLACK = "\x1b[90m"
INTENSE_BLUE = "\x1b[94m"
INTENSE_CYAN = "\x1b[96m"
INTENSE_GREEN = "\x1b[92m"
INTENSE_MAGENTA = "\x1b[95m"
INTENSE_RED = "\x1b[91m"
INTENSE_WHITE = "\x1b[97m"
INTENSE_YELLOW = "\x1b[93m"
BACKGROUND_BLACK = "\x1b[40m"
BACKGROUND_BLUE = "\x1b[44m"
BACKGROUND_CYAN = "\x1b[46m"
BACKGROUND_GREEN = "\x1b[42m"
BACKGROUND_MAGENTA = "\x1b[45m"
BACKGROUND_RED = "\x1b[41m"
BACKGROUND_WHITE = "\x1b[47m"
BACKGROUND_YELLOW = "\x1b[43m"
INTENSE_BACKGROUND_BLACK = "\x1b[100m"
INTENSE_BACKGROUND_BLUE = "\x1b[104m"
INTENSE_BACKGROUND_CYAN = "\x1b[106m"
INTENSE_BACKGROUND_GREEN = "\x1b[102m"
INTENSE_BACKGROUND_MAGENTA = "\x1b[105m"
INTENSE_BACKGROUND_RED = "\x1b[101m"
INTENSE_BACKGROUND_WHITE = "\x1b[107m"
INTENSE_BACKGROUND_YELLOW = "\x1b[103m"
ColorCodes = set()
NoColors = ANSIColors()
for attr, code in ANSIColors.__dict__.items():
if not attr.startswith("__"):
ColorCodes.add(code)
setattr(NoColors, attr, "")
def get_colors(
colorize: bool = False, *, file: IO[str] | IO[bytes] | None = None
) -> ANSIColors:
if colorize or can_colorize(file=file):
return ANSIColors()
else:
return NoColors
def decolor(text: str) -> str:
"""Remove ANSI color codes from a string."""
for code in ColorCodes:
text = text.replace(code, "")
return text
def can_colorize(*, file: IO[str] | IO[bytes] | None = None) -> bool:
if file is None:
file = sys.stdout
if not sys.flags.ignore_environment:
if os.environ.get("PYTHON_COLORS") == "0":
return False
if os.environ.get("PYTHON_COLORS") == "1":
return True
if os.environ.get("NO_COLOR"):
return False
if not COLORIZE:
return False
if os.environ.get("FORCE_COLOR"):
return True
if os.environ.get("TERM") == "dumb":
return False
if not hasattr(file, "fileno"):
return False
if sys.platform == "win32":
try:
import nt
if not nt._supports_virtual_terminal():
return False
except (ImportError, AttributeError):
return False
try:
return os.isatty(file.fileno())
except io.UnsupportedOperation:
return hasattr(file, "isatty") and file.isatty()
def set_theme(t: dict[ColorTag, str] | None = None) -> None:
global theme
if t:
theme = t
return
colors = get_colors()
theme = {
"PROMPT": colors.BOLD_MAGENTA,
"KEYWORD": colors.BOLD_BLUE,
"BUILTIN": colors.CYAN,
"COMMENT": colors.RED,
"STRING": colors.GREEN,
"NUMBER": colors.YELLOW,
"OP": colors.RESET,
"DEFINITION": colors.BOLD,
"SOFT_KEYWORD": colors.BOLD_BLUE,
"RESET": colors.RESET,
}
set_theme()