def parse_ansi(self, string, strip_ansi=False, xterm256=False, mxp=False):
        if hasattr(string, '_raw_string'):
            if strip_ansi:
                return string.clean()
            else:
                return string.raw()

        if not string:
            return ''

        # check cached parsings
        global _PARSE_CACHE
        cachekey = "%s-%s-%s-%s" % (string, strip_ansi, xterm256, mxp)
        if cachekey in _PARSE_CACHE:
            return _PARSE_CACHE[cachekey]

        # pre-convert bright colors to xterm256 color tags
        string = self.brightbg_sub.sub(self.sub_brightbg, string)

        def do_xterm256(part):
            return self.sub_xterm256(part, xterm256)

        in_string = utils.to_str(string)

        # do string replacement
        parsed_string =  ""
        parts = self.ansi_escapes.split(in_string) + [" "]
        for part, sep in zip(parts[::2], parts[1::2]):
            pstring = self.xterm256_sub.sub(do_xterm256, part)
            pstring = self.ansi_sub.sub(self.sub_ansi, pstring)
            parsed_string += "%s%s" % (pstring, sep[0].strip())

        if not mxp:
            parsed_string = self.strip_mxp(parsed_string)

        if strip_ansi:
            # remove all ansi codes (including those manually
            # inserted in string)
            return self.strip_raw_codes(parsed_string)

        # cache and crop old cache
        _PARSE_CACHE[cachekey] = parsed_string
        if len(_PARSE_CACHE) > _PARSE_CACHE_SIZE:
           _PARSE_CACHE.popitem(last=False)

        return parsed_string

    # Mapping using {r {n etc
Parses a string, subbing color codes according to the stored
dataset/ETHPy150Open evennia/evennia/evennia/utils/ansi.py/ANSIParser.parse_ansi