def test_substyles(): style = Style([ ('a.b', '#ff0000 bold'), ('a', '#0000ff'), ('b', '#00ff00'), ('b.c', '#0000ff italic'), ]) # Starting with a.* expected = Attrs(color='0000ff', bgcolor='', bold=False, underline=False, italic=False, blink=False, reverse=False, hidden=False) assert style.get_attrs_for_style_str('class:a') == expected expected = Attrs(color='ff0000', bgcolor='', bold=True, underline=False, italic=False, blink=False, reverse=False, hidden=False) assert style.get_attrs_for_style_str('class:a.b') == expected assert style.get_attrs_for_style_str('class:a.b.c') == expected # Starting with b.* expected = Attrs(color='00ff00', bgcolor='', bold=False, underline=False, italic=False, blink=False, reverse=False, hidden=False) assert style.get_attrs_for_style_str('class:b') == expected assert style.get_attrs_for_style_str('class:b.a') == expected expected = Attrs(color='0000ff', bgcolor='', bold=False, underline=False, italic=True, blink=False, reverse=False, hidden=False) assert style.get_attrs_for_style_str('class:b.c') == expected assert style.get_attrs_for_style_str('class:b.c.d') == expected
def test_substyles(): style = Style([ ("a.b", "#ff0000 bold"), ("a", "#0000ff"), ("b", "#00ff00"), ("b.c", "#0000ff italic"), ]) # Starting with a.* expected = Attrs( color="0000ff", bgcolor="", bold=False, underline=False, italic=False, blink=False, reverse=False, hidden=False, ) assert style.get_attrs_for_style_str("class:a") == expected expected = Attrs( color="ff0000", bgcolor="", bold=True, underline=False, italic=False, blink=False, reverse=False, hidden=False, ) assert style.get_attrs_for_style_str("class:a.b") == expected assert style.get_attrs_for_style_str("class:a.b.c") == expected # Starting with b.* expected = Attrs( color="00ff00", bgcolor="", bold=False, underline=False, italic=False, blink=False, reverse=False, hidden=False, ) assert style.get_attrs_for_style_str("class:b") == expected assert style.get_attrs_for_style_str("class:b.a") == expected expected = Attrs( color="0000ff", bgcolor="", bold=False, underline=False, italic=True, blink=False, reverse=False, hidden=False, ) assert style.get_attrs_for_style_str("class:b.c") == expected assert style.get_attrs_for_style_str("class:b.c.d") == expected
def test_style_from_dict(): style = Style.from_dict({ 'a': '#ff0000 bold underline italic', 'b': 'bg:#00ff00 blink reverse', }) # Lookup of class:a. expected = Attrs(color='ff0000', bgcolor='', bold=True, underline=True, italic=True, blink=False, reverse=False, hidden=False) assert style.get_attrs_for_style_str('class:a') == expected # Lookup of class:b. expected = Attrs(color='', bgcolor='00ff00', bold=False, underline=False, italic=False, blink=True, reverse=True, hidden=False) assert style.get_attrs_for_style_str('class:b') == expected # Test inline style. expected = Attrs(color='ff0000', bgcolor='', bold=False, underline=False, italic=False, blink=False, reverse=False, hidden=False) assert style.get_attrs_for_style_str('#ff0000') == expected # Combine class name and inline style (Whatever is defined later gets priority.) expected = Attrs(color='00ff00', bgcolor='', bold=True, underline=True, italic=True, blink=False, reverse=False, hidden=False) assert style.get_attrs_for_style_str('class:a #00ff00') == expected expected = Attrs(color='ff0000', bgcolor='', bold=True, underline=True, italic=True, blink=False, reverse=False, hidden=False) assert style.get_attrs_for_style_str('#00ff00 class:a') == expected
def test_style_inheritance(self): style = style_from_dict({ Token: '#ff0000', Token.A.B.C: 'bold', Token.A.B.C.D: '#ansired', Token.A.B.C.D.E: 'noinherit blink' }) expected = Attrs(color='ff0000', bgcolor=None, bold=True, underline=False, italic=False, blink=False, reverse=False) self.assertEqual(style.get_attrs_for_token(Token.A.B.C), expected) expected = Attrs(color='ansired', bgcolor=None, bold=True, underline=False, italic=False, blink=False, reverse=False) self.assertEqual(style.get_attrs_for_token(Token.A.B.C.D), expected) expected = Attrs(color=None, bgcolor=None, bold=False, underline=False, italic=False, blink=True, reverse=False) self.assertEqual(style.get_attrs_for_token(Token.A.B.C.D.E), expected)
def test_class_combinations_2(): # In this case, our style has both class 'a' and 'b'. # The style that is defined the latest get priority. style = Style([ ('a b', '#ff0000'), ('b', '#00ff00'), ('a', '#0000ff'), ]) expected = Attrs(color='00ff00', bgcolor='', bold=False, underline=False, italic=False, blink=False, reverse=False, hidden=False) assert style.get_attrs_for_style_str('class:a class:b') == expected assert style.get_attrs_for_style_str('class:a,b') == expected assert style.get_attrs_for_style_str('class:a,b,c') == expected # Defining 'a' latest should give priority to 'a'. expected = Attrs(color='0000ff', bgcolor='', bold=False, underline=False, italic=False, blink=False, reverse=False, hidden=False) assert style.get_attrs_for_style_str('class:b class:a') == expected assert style.get_attrs_for_style_str('class:b,a') == expected
def test_class_combinations_2(): # In this case, our style has both class 'a' and 'b'. # The style that is defined the latest get priority. style = Style([ ("a b", "#ff0000"), ("b", "#00ff00"), ("a", "#0000ff"), ]) expected = Attrs( color="00ff00", bgcolor="", bold=False, underline=False, italic=False, blink=False, reverse=False, hidden=False, ) assert style.get_attrs_for_style_str("class:a class:b") == expected assert style.get_attrs_for_style_str("class:a,b") == expected assert style.get_attrs_for_style_str("class:a,b,c") == expected # Defining 'a' latest should give priority to 'a'. expected = Attrs( color="0000ff", bgcolor="", bold=False, underline=False, italic=False, blink=False, reverse=False, hidden=False, ) assert style.get_attrs_for_style_str("class:b class:a") == expected assert style.get_attrs_for_style_str("class:b,a") == expected
def test_swap_light_and_dark_style_transformation(): transformation = SwapLightAndDarkStyleTransformation() # Test with 6 digit hex colors. before = Attrs( color="440000", bgcolor="888844", bold=True, underline=True, strike=True, italic=True, blink=False, reverse=False, hidden=False, ) after = Attrs( color="ffbbbb", bgcolor="bbbb76", bold=True, underline=True, strike=True, italic=True, blink=False, reverse=False, hidden=False, ) assert transformation.transform_attrs(before) == after # Test with ANSI colors. before = Attrs( color="ansired", bgcolor="ansiblack", bold=True, underline=True, strike=True, italic=True, blink=False, reverse=False, hidden=False, ) after = Attrs( color="ansibrightred", bgcolor="ansiwhite", bold=True, underline=True, strike=True, italic=True, blink=False, reverse=False, hidden=False, ) assert transformation.transform_attrs(before) == after
def test_style_from_dict(): style = style_from_dict({ Token.A: '#ff0000 bold underline italic', Token.B: 'bg:#00ff00 blink reverse', }) expected = Attrs(color='ff0000', bgcolor=None, bold=True, underline=True, italic=True, blink=False, reverse=False) assert style.get_attrs_for_token(Token.A) == expected expected = Attrs(color=None, bgcolor='00ff00', bold=False, underline=False, italic=False, blink=True, reverse=True) assert style.get_attrs_for_token(Token.B) == expected
def get_attrs_for_token(self, token): if ( token not in PowerlinePromptToken or len(token) != len(PowerlinePromptToken) + 1 or not token[-1].startswith('Pl') or token[-1] == 'Pl' ): return super(PowerlinePromptStyle, self).get_attrs_for_token(token) ret = { 'color': None, 'bgcolor': None, 'bold': None, 'underline': None, 'italic': None, 'reverse': False, 'blink': False, } for prop in token[-1][3:].split('_'): if prop[0] == 'a': ret[prop[1:]] = True elif prop[0] == 'f': ret['color'] = prop[1:] elif prop[0] == 'b': ret['bgcolor'] = prop[1:] return Attrs(**ret)
def _reset_screen(self): """ Reset the Screen content. (also called when switching from/to alternate buffer. """ self.pt_screen = Screen(default_char=Char( ' ', '')) # TODO: maybe stop using this Screen class. self.pt_screen.cursor_position = CursorPosition(0, 0) self.pt_screen.show_cursor = True self.data_buffer = self.pt_screen.data_buffer self.pt_cursor_position = self.pt_screen.cursor_position self.wrapped_lines = [] # List of line indexes that were wrapped. self._attrs = Attrs(color=None, bgcolor=None, bold=False, underline=False, italic=False, blink=False, reverse=False, hidden=False) self._style_str = '' self.margins = None self.max_y = 0 # Max 'y' position to which is written.
def _get_attrs_for_token(self, token): if token and token[0] == 'C': # Token starts with ('C',). Token describes its own style. return Attrs(*token[1:]) else: # Take styles from UI style. return self._style.get_attrs_for_token(token)
def __init__(self, fileno, lexer=None, name='<stdin>'): assert isinstance(fileno, int) assert lexer is None or isinstance(lexer, Lexer) assert isinstance(name, six.text_type) self.fileno = fileno self.lexer = lexer self.name = name self._line_tokens = [] self._eof = False # Default style attributes. self._attrs = Attrs(color=None, bgcolor=None, bold=False, underline=False, italic=False, blink=False, reverse=False, hidden=False) # Start input parser. self._parser = self._parse_corot() next(self._parser) self._stdin_reader = PosixStdinReader(fileno)
def test_class_combinations_1(): # In this case, our style has both class 'a' and 'b'. # Given that the style for 'a b' is defined at the end, that one is used. style = Style([ ("a", "#0000ff"), ("b", "#00ff00"), ("a b", "#ff0000"), ]) expected = Attrs( color="ff0000", bgcolor="", bold=False, underline=False, strike=False, italic=False, blink=False, reverse=False, hidden=False, ) assert style.get_attrs_for_style_str("class:a class:b") == expected assert style.get_attrs_for_style_str("class:a,b") == expected assert style.get_attrs_for_style_str("class:a,b,c") == expected # Changing the order shouldn't matter. assert style.get_attrs_for_style_str("class:b class:a") == expected assert style.get_attrs_for_style_str("class:b,a") == expected
def get_attrs_for_token(self, token): if token and token[0] == 'C': # Token starts with ('C',). Token describes its own style. c, fg, bg, bold, underline, italic, blink, reverse = token return Attrs(fg, bg, bold, underline, italic, blink, reverse) else: # Take styles from UI style. return self.ui_style.get_attrs_for_token(token)
def test_swap_light_and_dark_style_transformation(): transformation = SwapLightAndDarkStyleTransformation() # Test with 6 digit hex colors. before = Attrs(color='440000', bgcolor='888844', bold=True, underline=True, italic=True, blink=False, reverse=False, hidden=False) after = Attrs(color='ffbbbb', bgcolor='bbbb76', bold=True, underline=True, italic=True, blink=False, reverse=False, hidden=False) assert transformation.transform_attrs(before) == after # Test with ANSI colors. before = Attrs(color='ansired', bgcolor='ansiblack', bold=True, underline=True, italic=True, blink=False, reverse=False, hidden=False) after = Attrs(color='ansibrightred', bgcolor='ansiwhite', bold=True, underline=True, italic=True, blink=False, reverse=False, hidden=False) assert transformation.transform_attrs(before) == after
def default_attrs(): return Attrs(color='', bgcolor='', bold=False, underline=False, italic=False, blink=False, reverse=False, hidden=False)
def get_attrs_for_token(self, token): """(PymuxStyle, type(token)) -> Attributes *Desciption* """ if token and token[0] == 'C': # Token starts with ('C',). Token describes its own style. c, fg, bg, bold, underline, italic, blink, reverse = token return Attrs(fg, bg, bold, underline, italic, blink, reverse) else: # Take styles from Pygments style. return self.pygments_style.get_attrs_for_token(token)
def _get_attributes(output, color: str): attr = Attrs(color=color, bgcolor='', bold=False, underline=False, italic=False, blink=False, reverse=False) if output.true_color() and not output.ansi_colors_only(): return output._escape_code_cache_true_color[attr] else: return output._escape_code_cache[attr]
def _get_attributes(output, color: str): attr = Attrs(color=color, bgcolor='', bold=False, underline=False, italic=False, blink=False, reverse=False, hidden=False) # if output.true_color() and not output.ansi_colors_only(): # return output._escape_code_cache_true_color[attr] # else: # FIXME: probably want this to be configurable escape_code_caches = output._escape_code_caches[ColorDepth.default()] return escape_code_caches[attr]
def test_class_combinations_1(): # In this case, our style has both class 'a' and 'b'. # Given that the style for 'a b' is defined at the end, that one is used. style = Style([ ('a', '#0000ff'), ('b', '#00ff00'), ('a b', '#ff0000'), ]) expected = Attrs(color='ff0000', bgcolor='', bold=False, underline=False, italic=False, blink=False, reverse=False, hidden=False) assert style.get_attrs_for_style_str('class:a class:b') == expected assert style.get_attrs_for_style_str('class:a,b') == expected assert style.get_attrs_for_style_str('class:a,b,c') == expected # Changing the order shouldn't matter. assert style.get_attrs_for_style_str('class:b class:a') == expected assert style.get_attrs_for_style_str('class:b,a') == expected
def _reset_screen(self): """ Reset the Screen content. (also called when switching from/to alternate buffer. """ self.pt_screen = Screen(default_char=Char(' ', DEFAULT_TOKEN)) self.pt_screen.cursor_position = CursorPosition(0, 0) self.pt_screen.show_cursor = True self.data_buffer = self.pt_screen.data_buffer self.pt_cursor_position = self.pt_screen.cursor_position self._attrs = Attrs(color=None, bgcolor=None, bold=False, underline=False, italic=False, blink=False, reverse=False) self.margins = None self.max_y = 0 # Max 'y' position to which is written.
def _reset_screen(self): """(BetterScreen) -> NoneType Reset the Screen content. (also called when switching from/to alternate buffer. """ self.pt_screen = Screen(default_char=Char(' ', DEFAULT_TOKEN)) self.pt_screen.cursor_position = CursorPosition(0, 0) self.pt_screen.show_cursor = True self.data_buffer = self.pt_screen.data_buffer self._attrs = Attrs(color=None, bgcolor=None, bold=False, underline=False, italic=False, blink=False, reverse=False) self.margins = Margins(0, self.lines - 1) self.line_offset = 0 # Index of the line that's currently displayed on top. self.max_y = 0 # Max 'y' position to which is written.
def test_print_with_style(monkeypatch): mock = Mock(return_value=None) monkeypatch.setattr(DummyOutput, "write", mock.write) monkeypatch.setattr(DummyOutput, "set_attributes", mock.set_attributes) print_formatted_text("Hello World", style="bold italic fg:darkred", output=DummyOutput()) assert len(mock.method_calls) == 4 assert mock.method_calls[0][0] == "set_attributes" assert mock.method_calls[0][1][0] == Attrs( color="8b0000", bgcolor="", bold=True, underline=False, italic=True, blink=False, reverse=False, hidden=False, ) assert mock.method_calls[1][0] == "write" assert mock.method_calls[1][1][0] == "Hello World"
def __init__( self, fileno: int, lexer: Optional[Lexer] = None, name: str = "<stdin>", encoding: str = "utf-8", ) -> None: self.fileno = fileno self.lexer = lexer self.name = name self._line_tokens: StyleAndTextTuples = [] self._eof = False # Default style attributes. self._attrs = Attrs( color=None, bgcolor=None, bold=False, underline=False, italic=False, blink=False, reverse=False, hidden=False, ) # Start input parser. self._parser = self._parse_corot() next(self._parser) # Create incremental decoder for decoding stdin. # We can not just do `os.read(stdin.fileno(), 1024).decode('utf-8')`, # because it could be that we are in the middle of a utf-8 byte # sequence. self._stdin_decoder_cls = getincrementaldecoder(encoding) self._stdin_decoder = self._stdin_decoder_cls(errors="ignore")
from pyte.screens import Margins from six.moves import range from prompt_toolkit.cache import FastDictCache from prompt_toolkit.layout.screen import Screen, Char from prompt_toolkit.styles import Attrs from prompt_toolkit.terminal.vt100_output import FG_ANSI_COLORS, BG_ANSI_COLORS from prompt_toolkit.terminal.vt100_output import _256_colors as _256_colors_table from collections import namedtuple __all__ = ( 'BetterScreen', 'DEFAULT_TOKEN', ) DEFAULT_TOKEN = ('C', ) + Attrs(color=None, bgcolor=None, bold=False, underline=False, italic=False, blink=False, reverse=False) class CursorPosition(object): " Mutable CursorPosition. " def __init__(self, x=0, y=0): self.x = x self.y = y def __repr__(self): return 'pymux.CursorPosition(x=%r, y=%r)' % (self.x, self.y) _CHAR_CACHE = FastDictCache(Char, size=1000 * 1000)
def test_style_from_dict(): style = Style.from_dict({ "a": "#ff0000 bold underline strike italic", "b": "bg:#00ff00 blink reverse", }) # Lookup of class:a. expected = Attrs( color="ff0000", bgcolor="", bold=True, underline=True, strike=True, italic=True, blink=False, reverse=False, hidden=False, ) assert style.get_attrs_for_style_str("class:a") == expected # Lookup of class:b. expected = Attrs( color="", bgcolor="00ff00", bold=False, underline=False, strike=False, italic=False, blink=True, reverse=True, hidden=False, ) assert style.get_attrs_for_style_str("class:b") == expected # Test inline style. expected = Attrs( color="ff0000", bgcolor="", bold=False, underline=False, strike=False, italic=False, blink=False, reverse=False, hidden=False, ) assert style.get_attrs_for_style_str("#ff0000") == expected # Combine class name and inline style (Whatever is defined later gets priority.) expected = Attrs( color="00ff00", bgcolor="", bold=True, underline=True, strike=True, italic=True, blink=False, reverse=False, hidden=False, ) assert style.get_attrs_for_style_str("class:a #00ff00") == expected expected = Attrs( color="ff0000", bgcolor="", bold=True, underline=True, strike=True, italic=True, blink=False, reverse=False, hidden=False, ) assert style.get_attrs_for_style_str("#00ff00 class:a") == expected
def select_graphic_rendition(self, *attrs): """ Support 256 colours """ replace = {} if not attrs: attrs = [0] else: attrs = list(attrs[::-1]) while attrs: attr = attrs.pop() if attr in self._fg_colors: replace["color"] = self._fg_colors[attr] elif attr in self._bg_colors: replace["bgcolor"] = self._bg_colors[attr] elif attr == 1: replace["bold"] = True elif attr == 3: replace["italic"] = True elif attr == 4: replace["underline"] = True elif attr == 5: replace["blink"] = True elif attr == 6: replace["blink"] = True # Fast blink. elif attr == 7: replace["reverse"] = True elif attr == 8: replace["hidden"] = True elif attr == 22: replace["bold"] = False elif attr == 23: replace["italic"] = False elif attr == 24: replace["underline"] = False elif attr == 25: replace["blink"] = False elif attr == 27: replace["reverse"] = False elif not attr: replace = {} self._attrs = Attrs(color=None, bgcolor=None, bold=False, underline=False, italic=False, blink=False, reverse=False, hidden=False) elif attr in (38, 48): n = attrs.pop() # 256 colors. if n == 5: if attr == 38: m = attrs.pop() replace["color"] = self._256_colors.get(1024 + m) elif attr == 48: m = attrs.pop() replace["bgcolor"] = self._256_colors.get(1024 + m) # True colors. if n == 2: try: color_str = '#%02x%02x%02x' % ( attrs.pop(), attrs.pop(), attrs.pop()) except IndexError: pass else: if attr == 38: replace["color"] = color_str elif attr == 48: replace["bgcolor"] = color_str attrs = self._attrs._replace(**replace) # Build style string. style_str = '' if attrs.color: style_str += '%s ' % attrs.color if attrs.bgcolor: style_str += 'bg:%s ' % attrs.bgcolor if attrs.bold: style_str += 'bold ' if attrs.italic: style_str += 'italic ' if attrs.underline: style_str += 'underline ' if attrs.blink: style_str += 'blink ' if attrs.reverse: style_str += 'reverse ' if attrs.hidden: style_str += 'hidden ' self._style_str = unicode_intern(style_str) self._attrs = attrs
def _select_graphic_rendition(self, attrs: Sequence[int]) -> None: """ Taken a list of graphics attributes and apply changes to Attrs. """ # NOTE: This function is almost literally taken from Pymux. # if something is wrong, please report there as well! # https://github.com/jonathanslenders/pymux replace: Dict[str, Union[bool, str, None]] = {} if not attrs: attrs = [0] else: attrs = list(attrs[::-1]) while attrs: attr = attrs.pop() if attr in _fg_colors: replace["color"] = _fg_colors[attr] elif attr in _bg_colors: replace["bgcolor"] = _bg_colors[attr] elif attr == 1: replace["bold"] = True elif attr == 3: replace["italic"] = True elif attr == 4: replace["underline"] = True elif attr == 5: replace["blink"] = True elif attr == 6: replace["blink"] = True # Fast blink. elif attr == 7: replace["reverse"] = True elif attr == 22: replace["bold"] = False elif attr == 23: replace["italic"] = False elif attr == 24: replace["underline"] = False elif attr == 25: replace["blink"] = False elif attr == 27: replace["reverse"] = False elif not attr: replace = {} self._attrs = Attrs( color=None, bgcolor=None, bold=False, underline=False, italic=False, blink=False, reverse=False, hidden=False, ) elif attr in (38, 48): n = attrs.pop() # 256 colors. if n == 5: if attr == 38: m = attrs.pop() replace["color"] = _256_colors.get(1024 + m) elif attr == 48: m = attrs.pop() replace["bgcolor"] = _256_colors.get(1024 + m) # True colors. if n == 2: try: color_str = "%02x%02x%02x" % ( attrs.pop(), attrs.pop(), attrs.pop(), ) except IndexError: pass else: if attr == 38: replace["color"] = color_str elif attr == 48: replace["bgcolor"] = color_str self._attrs = self._attrs._replace(**replace) # type: ignore
def select_graphic_rendition(self, *attrs): """ Support 256 colours """ replace = {} if not attrs: attrs = [0] else: attrs = list(attrs[::-1]) while attrs: attr = attrs.pop() if attr in self._fg_colors: replace["color"] = self._fg_colors[attr] elif attr in self._bg_colors: replace["bgcolor"] = self._bg_colors[attr] elif attr == 1: replace["bold"] = True elif attr == 3: replace["italic"] = True elif attr == 4: replace["underline"] = True elif attr == 5: replace["blink"] = True elif attr == 6: replace["blink"] = True # Fast blink. elif attr == 7: replace["reverse"] = True elif attr == 22: replace["bold"] = False elif attr == 23: replace["italic"] = False elif attr == 24: replace["underline"] = False elif attr == 25: replace["blink"] = False elif attr == 27: replace["reverse"] = False elif not attr: replace = {} self._attrs = Attrs(color=None, bgcolor=None, bold=False, underline=False, italic=False, blink=False, reverse=False) elif attr in (38, 48): n = attrs.pop() # 256 colors. if n == 5: if attr == 38: m = attrs.pop() replace["color"] = self._256_colors.get(1024 + m) elif attr == 48: m = attrs.pop() replace["bgcolor"] = self._256_colors.get(1024 + m) # True colors. if n == 2: try: color_str = '%02x%02x%02x' % (attrs.pop(), attrs.pop(), attrs.pop()) except IndexError: pass else: if attr == 38: replace["color"] = color_str elif attr == 48: replace["bgcolor"] = color_str self._attrs = self._attrs._replace(**replace)
def transform_attrs(self, attrs: Attrs) -> Attrs: if self.no_ansi: return Attrs("", "", False, False, False, False, False, False, False) return attrs