示例#1
0
def ansi_color_escape_code_to_name(escape_code, style, reversed_style=None):
    """Converts an ASNI color code escape sequence to a tuple of color names
    in the provided style ('default' should almost be the style). For example,
    '0' becomes ('NO_COLOR',) and '32;41' becomes ('GREEN', 'BACKGROUND_RED').
    The style keyword may either be a string, in which the style is looked up,
    or an actual style dict.  You can also provide a reversed style mapping,
    too, which is just the keys/values of the style dict swapped. If reversed
    style is not provided, it is computed.
    """
    key = (escape_code, style)
    if key in _ANSI_COLOR_ESCAPE_CODE_TO_NAME_CACHE:
        return _ANSI_COLOR_ESCAPE_CODE_TO_NAME_CACHE[key]
    if reversed_style is None:
        style, reversed_style = ansi_reverse_style(style, return_style=True)
    # strip some actual escape codes, if needed.
    ec = ANSI_ESCAPE_CODE_RE.match(escape_code).group(2)
    names = []
    n_ints = 0
    seen_set_foreback = False
    for e in ec.split(";"):
        no_left_zero = e.lstrip("0") if len(e) > 1 else e
        if seen_set_foreback and n_ints > 0:
            names.append(e)
            n_ints -= 1
            if n_ints == 0:
                seen_set_foreback = False
            continue
        else:
            names.append(reversed_style.get(no_left_zero, no_left_zero))
        # set the flags for next time
        if "38" == e or "48" == e:
            seen_set_foreback = True
        elif "2" == e:
            n_ints = 3
        elif "5" == e:
            n_ints = 1
    # normalize names
    n = ""
    norm_names = []
    colors = set(reversed_style.values())
    for name in names:
        if name == "NO_COLOR":
            # skip most '0' entries
            continue
        n = n + name if n else name
        n = ANSI_REVERSE_COLOR_NAME_TRANSLATIONS.get(n, n)
        if n.endswith("_"):
            continue
        elif ANSI_COLOR_NAME_SET_SHORT_RE.match(n) is not None:
            pre, fore_back, short = ANSI_COLOR_NAME_SET_SHORT_RE.match(
                n).groups()
            n = _color_name_from_ints(short_to_ints(short),
                                      background=(fore_back == "BACK"),
                                      prefix=pre)
        elif ANSI_COLOR_NAME_SET_3INTS_RE.match(n) is not None:
            pre, fore_back, r, g, b = ANSI_COLOR_NAME_SET_3INTS_RE.match(
                n).groups()
            n = _color_name_from_ints((int(r), int(g), int(b)),
                                      background=(fore_back == "BACK"),
                                      prefix=pre)
        elif "GROUND_3INTS_" in n:
            # have 1 or 2, but not 3 ints
            n += "_"
            continue
        # error check
        if n not in colors:
            msg = (
                "Could not translate ANSI color code {escape_code!r} "
                "into a known color in the palette. Specifically, the {n!r} "
                "portion of {name!r} in {names!r} seems to missing.")
            raise ValueError(
                msg.format(escape_code=escape_code,
                           names=names,
                           name=name,
                           n=n))
        norm_names.append(n)
        n = ""
    # return
    if len(norm_names) == 0:
        return ("NO_COLOR", )
    else:
        return tuple(norm_names)
示例#2
0
def ansi_color_escape_code_to_name(escape_code, style, reversed_style=None):
    """Converts an ANSI color code escape sequence to a tuple of color names
    in the provided style ('default' should almost be the style). For example,
    '0' becomes ('RESET',) and '32;41' becomes ('GREEN', 'BACKGROUND_RED').
    The style keyword may either be a string, in which the style is looked up,
    or an actual style dict.  You can also provide a reversed style mapping,
    too, which is just the keys/values of the style dict swapped. If reversed
    style is not provided, it is computed.
    """
    key = (escape_code, style)
    # todo: see the cache ever used?
    if key in _ANSI_COLOR_ESCAPE_CODE_TO_NAME_CACHE:
        return _ANSI_COLOR_ESCAPE_CODE_TO_NAME_CACHE[key]
    if reversed_style is None:
        style, reversed_style = ansi_reverse_style(style, return_style=True)
    # strip some actual escape codes, if needed.
    match = ANSI_ESCAPE_CODE_RE.match(escape_code)
    if not match:
        msg = 'Invalid ANSI color sequence "{0}", using "RESET" instead.'.format(
            escape_code)
        warnings.warn(msg, RuntimeWarning)
        return ("RESET", )
    ec = match.group(2)
    names = []
    n_ints = 0
    seen_set_foreback = False
    for e in ec.split(";"):
        no_left_zero = e.lstrip("0") if len(e) > 1 else e
        if seen_set_foreback and n_ints > 0:
            names.append(e)
            n_ints -= 1
            if n_ints == 0:
                seen_set_foreback = False
            continue
        else:
            names.append(reversed_style.get(no_left_zero, no_left_zero))
        # set the flags for next time
        if "38" == e or "48" == e:
            seen_set_foreback = True
        elif seen_set_foreback and "2" == e:
            n_ints = 3
        elif seen_set_foreback and "5" == e:
            n_ints = 1
    # normalize names
    n = ""
    norm_names = []
    prefixes = ""
    for name in names:
        if name in ("RESET", "NO_COLOR"):
            # skip most '0' entries
            continue
        elif "BACKGROUND_" in name and n:
            prefixes += n
            n = ""
        n = n + name if n else name
        if n.endswith("_"):
            continue
        elif ANSI_COLOR_NAME_SET_SHORT_RE.match(n) is not None:
            pre, fore_back, short = ANSI_COLOR_NAME_SET_SHORT_RE.match(
                n).groups()
            n = _color_name_from_ints(short_to_ints(short),
                                      background=(fore_back == "BACK"),
                                      prefix=pre)
        elif ANSI_COLOR_NAME_SET_3INTS_RE.match(n) is not None:
            pre, fore_back, r, g, b = ANSI_COLOR_NAME_SET_3INTS_RE.match(
                n).groups()
            n = _color_name_from_ints((int(r), int(g), int(b)),
                                      background=(fore_back == "BACK"),
                                      prefix=pre)
        elif "GROUND_FAINT_" in n:
            # have 1 or 2, but not 3 ints
            n += "_"
            continue
        # error check
        if not iscolor(n):
            msg = (
                "Could not translate ANSI color code {escape_code!r} "
                "into a known color in the palette. Specifically, the {n!r} "
                "portion of {name!r} in {names!r} seems to missing.")
            raise ValueError(
                msg.format(escape_code=escape_code,
                           names=names,
                           name=name,
                           n=n))
        norm_names.append(n)
        n = ""
    # check if we have pre- & post-fixes to apply to the last, non-background element
    prefixes += n
    if prefixes.endswith("_"):
        for i in range(-1, -len(norm_names) - 1, -1):
            if "BACKGROUND_" not in norm_names[i]:
                norm_names[i] = prefixes + norm_names[i]
                break
        else:
            # only have background colors, so select WHITE as default color
            norm_names.append(prefixes + "WHITE")
    # return
    if len(norm_names) == 0:
        return ("RESET", )
    else:
        return tuple(norm_names)
示例#3
0
def ansi_color_escape_code_to_name(escape_code, style, reversed_style=None):
    """Converts an ASNI color code escape sequence to a tuple of color names
    in the provided style ('default' should almost be the style). For example,
    '0' becomes ('NO_COLOR',) and '32;41' becomes ('GREEN', 'BACKGROUND_RED').
    The style keyword may either be a string, in which the style is looked up,
    or an actual style dict.  You can also provide a reversed style mapping,
    too, which is just the keys/values of the style dict swapped. If reversed
    style is not provided, it is computed.
    """
    key = (escape_code, style)
    if key in _ANSI_COLOR_ESCAPE_CODE_TO_NAME_CACHE:
        return _ANSI_COLOR_ESCAPE_CODE_TO_NAME_CACHE[key]
    if reversed_style is None:
        style, reversed_style = ansi_reverse_style(style, return_style=True)
    # strip some actual escape codes, if needed.
    ec = ANSI_ESCAPE_CODE_RE.match(escape_code).group(2)
    names = []
    n_ints = 0
    seen_set_foreback = False
    for e in ec.split(";"):
        no_left_zero = e.lstrip("0") if len(e) > 1 else e
        if seen_set_foreback and n_ints > 0:
            names.append(e)
            n_ints -= 1
            if n_ints == 0:
                seen_set_foreback = False
            continue
        else:
            names.append(reversed_style.get(no_left_zero, no_left_zero))
        # set the flags for next time
        if "38" == e or "48" == e:
            seen_set_foreback = True
        elif "2" == e:
            n_ints = 3
        elif "5" == e:
            n_ints = 1
    # normalize names
    n = ""
    norm_names = []
    colors = set(reversed_style.values())
    for name in names:
        if name == "NO_COLOR":
            # skip most '0' entries
            continue
        n = n + name if n else name
        n = ANSI_REVERSE_COLOR_NAME_TRANSLATIONS.get(n, n)
        if n.endswith("_"):
            continue
        elif ANSI_COLOR_NAME_SET_SHORT_RE.match(n) is not None:
            pre, fore_back, short = ANSI_COLOR_NAME_SET_SHORT_RE.match(n).groups()
            n = _color_name_from_ints(
                short_to_ints(short), background=(fore_back == "BACK"), prefix=pre
            )
        elif ANSI_COLOR_NAME_SET_3INTS_RE.match(n) is not None:
            pre, fore_back, r, g, b = ANSI_COLOR_NAME_SET_3INTS_RE.match(n).groups()
            n = _color_name_from_ints(
                (int(r), int(g), int(b)), background=(fore_back == "BACK"), prefix=pre
            )
        elif "GROUND_3INTS_" in n:
            # have 1 or 2, but not 3 ints
            n += "_"
            continue
        # error check
        if n not in colors:
            msg = (
                "Could not translate ANSI color code {escape_code!r} "
                "into a known color in the palette. Specifically, the {n!r} "
                "portion of {name!r} in {names!r} seems to missing."
            )
            raise ValueError(
                msg.format(escape_code=escape_code, names=names, name=name, n=n)
            )
        norm_names.append(n)
        n = ""
    # return
    if len(norm_names) == 0:
        return ("NO_COLOR",)
    else:
        return tuple(norm_names)