mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-04 16:34:47 +01:00
initial translation from ANSI codes to xonsh color names
This commit is contained in:
parent
bf1fd1d284
commit
efea8f05dc
3 changed files with 104 additions and 6 deletions
34
tests/test_ansi_colors.py
Normal file
34
tests/test_ansi_colors.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
"""Tests ANSI color tools."""
|
||||
import pytest
|
||||
|
||||
from xonsh.ansi_colors import ansi_color_escape_code_to_name, ansi_reverse_style
|
||||
|
||||
RS = ansi_reverse_style(style='default')
|
||||
|
||||
|
||||
@pytest.mark.parametrize('key, value', [
|
||||
('', 'NO_COLOR'),
|
||||
('31', 'RED'),
|
||||
])
|
||||
def test_ansi_reverse_style(key, value):
|
||||
assert key in RS
|
||||
assert RS[key] == value
|
||||
|
||||
|
||||
@pytest.mark.parametrize('inp, exp', [
|
||||
('0', ('NO_COLOR',)),
|
||||
('\0010\002', ('NO_COLOR',)),
|
||||
('\033[0m', ('NO_COLOR',)),
|
||||
('\001\033[0m\002', ('NO_COLOR',)),
|
||||
('00;36', ('CYAN',)),
|
||||
('01;31', ('BOLD_RED',)),
|
||||
('04;31', ('UNDERLINE_RED',)),
|
||||
('1;4;31', ('BOLD_UNDERLINE_RED',)),
|
||||
('4;1;31', ('BOLD_UNDERLINE_RED',)),
|
||||
('31;42', ('RED', 'BACKGROUND_GREEN')),
|
||||
('42;31', ('BACKGROUND_GREEN', 'RED')),
|
||||
('40', ('BACKGROUND_BLACK',)),
|
||||
])
|
||||
def test_ansi_color_escape_code_to_name(inp, exp):
|
||||
obs = ansi_color_escape_code_to_name(inp, reversed_style=RS)
|
||||
assert obs == exp
|
|
@ -1,10 +1,11 @@
|
|||
"""Tools for helping with ANSI color codes."""
|
||||
import re
|
||||
import sys
|
||||
import warnings
|
||||
import builtins
|
||||
|
||||
from xonsh.platform import HAS_PYGMENTS
|
||||
from xonsh.lazyasd import LazyDict
|
||||
from xonsh.lazyasd import LazyDict, lazyobject
|
||||
from xonsh.color_tools import (
|
||||
RE_BACKGROUND,
|
||||
BASE_XONSH_COLORS,
|
||||
|
@ -114,6 +115,74 @@ def ansi_color_style(style="default"):
|
|||
return cmap
|
||||
|
||||
|
||||
def ansi_reverse_style(style='default', return_style=False):
|
||||
"""Reverses an ANSI color style mapping so that escape codes map to
|
||||
colors. Style may either be string or mapping. May also return
|
||||
the style it looked up.
|
||||
"""
|
||||
style = ansi_style_by_name(style) if isinstance(style, str) else style
|
||||
reversed_style = {v: k for k, v in style.items()}
|
||||
# add keys to make this more useful
|
||||
updates = {
|
||||
'1': 'BOLD_',
|
||||
'4': 'UNDERLINE_',
|
||||
'1;4': 'BOLD_UNDERLINE_',
|
||||
'4;1': 'BOLD_UNDERLINE_',
|
||||
}
|
||||
for ec, name in reversed_style.items():
|
||||
no_left_zero = ec.lstrip('0')
|
||||
if no_left_zero.startswith(';'):
|
||||
updates[no_left_zero[1:]] = name
|
||||
elif no_left_zero != ec:
|
||||
updates[no_left_zero] = name
|
||||
reversed_style.update(updates)
|
||||
# return results
|
||||
if return_style:
|
||||
return style, reversed_style
|
||||
else:
|
||||
return reversed_style
|
||||
|
||||
|
||||
@lazyobject
|
||||
def ANSI_ESCAPE_CODE_RE():
|
||||
return re.compile(r'\001?(\033\[)?([0-9;]+)m?\002?')
|
||||
|
||||
|
||||
def ansi_color_escape_code_to_name(escape_code, style='default', reversed_style=None):
|
||||
"""Converts an ASNI color code escape sequence to a tuple of color names
|
||||
in the provided style ('default', by default). 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.
|
||||
"""
|
||||
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 = [reversed_style[e.lstrip('0')] for e in ec.split(';')]
|
||||
# normalize names
|
||||
n = ''
|
||||
norm_names = []
|
||||
for name in names:
|
||||
if name == 'NO_COLOR':
|
||||
# skip '0' entries
|
||||
continue
|
||||
n = n + name if n else name
|
||||
if n == 'UNDERLINE_BOLD_':
|
||||
n = 'BOLD_UNDERLINE_'
|
||||
if n.endswith('_'):
|
||||
continue
|
||||
norm_names.append(n)
|
||||
n = ''
|
||||
# return
|
||||
if len(norm_names) == 0:
|
||||
return ('NO_COLOR',)
|
||||
else:
|
||||
return tuple(norm_names)
|
||||
|
||||
|
||||
def _ansi_expand_style(cmap):
|
||||
"""Expands a style in order to more quickly make color map changes."""
|
||||
for key, val in list(cmap.items()):
|
||||
|
|
|
@ -413,8 +413,3 @@ def make_palette(strings):
|
|||
t, _, s = t.partition(" ")
|
||||
palette[t] = rgb_to_ints(t)
|
||||
return palette
|
||||
|
||||
|
||||
@deprecated(deprecated_in="0.5.10", removed_in="0.6.0")
|
||||
def make_pallete(*args, **kwargs):
|
||||
make_palette(*args, **kwargs)
|
||||
|
|
Loading…
Add table
Reference in a new issue