""" ANSI - Gives colour to text. Use the codes defined in ANSIPARSER in your text to apply colour to text according to the ANSI standard. Examples: This is %crRed text%cn and this is normal again. This is {rRed text{n and this is normal again. Mostly you should not need to call parse_ansi() explicitly; it is run by Evennia just before returning data to/from the user. """ import re from src.utils import utils # ANSI definitions ANSI_BEEP = "\07" ANSI_ESCAPE = "\033" ANSI_NORMAL = "\033[0m" ANSI_UNDERLINE = "\033[4m" ANSI_HILITE = "\033[1m" ANSI_BLINK = "\033[5m" ANSI_INVERSE = "\033[7m" ANSI_INV_HILITE = "\033[1;7m" ANSI_INV_BLINK = "\033[7;5m" ANSI_BLINK_HILITE = "\033[1;5m" ANSI_INV_BLINK_HILITE = "\033[1;5;7m" # Foreground colors ANSI_BLACK = "\033[30m" ANSI_RED = "\033[31m" ANSI_GREEN = "\033[32m" ANSI_YELLOW = "\033[33m" ANSI_BLUE = "\033[34m" ANSI_MAGENTA = "\033[35m" ANSI_CYAN = "\033[36m" ANSI_WHITE = "\033[37m" # Background colors ANSI_BACK_BLACK = "\033[40m" ANSI_BACK_RED = "\033[41m" ANSI_BACK_GREEN = "\033[42m" ANSI_BACK_YELLOW = "\033[43m" ANSI_BACK_BLUE = "\033[44m" ANSI_BACK_MAGENTA = "\033[45m" ANSI_BACK_CYAN = "\033[46m" ANSI_BACK_WHITE = "\033[47m" # Formatting Characters ANSI_RETURN = "\r\n" ANSI_TAB = "\t" ANSI_SPACE = " " class ANSIParser(object): """ A class that parses ansi markup to ANSI command sequences We also allow to escape colour codes by prepending with a \. """ def __init__(self): "Sets the mappings" # MUX-style mappings %cr %cn etc self.mux_ansi_map = [ (r'(?= 1: return ANSI_HILITE + ANSI_BLACK else: return ANSI_NORMAL + ANSI_BLACK elif red == green and red == blue: if background: return ANSI_BACK_WHITE elif red >= 4: return ANSI_HILITE + ANSI_WHITE else: return ANSI_NORMAL + ANSI_WHITE elif red > green and red > blue: if background: return ANSI_BACK_RED elif red >= 3: return ANSI_HILITE + ANSI_RED else: return ANSI_NORMAL + ANSI_RED elif red == green and red > blue: if background: return ANSI_BACK_YELLOW elif red >= 3: return ANSI_HILITE + ANSI_YELLOW else: return ANSI_NORMAL + ANSI_YELLOW elif red == blue and red > green: if background: return ANSI_BACK_MAGENTA elif red >= 3: return ANSI_HILITE + ANSI_MAGENTA else: return ANSI_NORMAL + ANSI_MAGENTA elif green > blue: if background: return ANSI_BACK_GREEN elif green >= 3: return ANSI_HILITE + ANSI_GREEN else: return ANSI_NORMAL + ANSI_GREEN elif green == blue: if background: return ANSI_BACK_CYAN elif green >= 3: return ANSI_HILITE + ANSI_CYAN else: return ANSI_NORMAL + ANSI_CYAN else: # mostly blue if background: return ANSI_BACK_BLUE elif blue >= 3: return ANSI_HILITE + ANSI_BLUE else: return ANSI_NORMAL + ANSI_BLUE def parse_ansi(self, string, strip_ansi=False, xterm256=False): """ Parses a string, subbing color codes according to the stored mapping. strip_ansi flag instead removes all ansi markup. """ if not string: return '' string = utils.to_str(string) self.do_xterm256 = xterm256 # handle all subs for sub in self.ansi_sub: # go through all available mappings and translate them string = sub[0].sub(sub[1], string) if strip_ansi: # remove all ANSI escape codes string = self.ansi_regex.sub("", string) # strip the \ in front of escaped colour codes, like \{r. string = re.sub(r"\\{", "{", string) string = re.sub(r"\\%r", "%r", string) string = re.sub(r"\\%b", "%b", string) string = re.sub(r"\\%c", "%c", string) return string ANSI_PARSER = ANSIParser() # # Access function # def parse_ansi(string, strip_ansi=False, parser=ANSI_PARSER, xterm256=False): """ Parses a string, subbing color codes as needed. """ return parser.parse_ansi(string, strip_ansi=strip_ansi, xterm256=xterm256)