pytermgui.prettifiers
This module provides some methods to prettify things.
The main export here is prettify. It uses pytermgui.parser.tim, and all of its
markup magic to create prettier representations of whatever is given.
1"""This module provides some methods to prettify things. 2 3The main export here is `prettify`. It uses `pytermgui.parser.tim`, and all of its 4markup magic to create prettier representations of whatever is given. 5""" 6 7from __future__ import annotations 8 9from collections import UserDict, UserList 10from typing import Any 11 12from .exceptions import MarkupSyntaxError 13from .fancy_repr import build_fancy_repr, supports_fancy_repr 14from .highlighters import highlight_python, highlight_tim 15from .markup import tim 16from .regex import RE_ANSI, RE_MARKUP 17 18__all__ = ["prettify"] 19 20CONTAINER_TYPES = (list, dict, set, tuple, UserDict, UserList) 21 22 23# Note: This function can be optimized in a lot of ways, primarily the way containers 24# are treated. 25def prettify( # pylint: disable=too-many-branches 26 target: Any, 27 indent: int = 2, 28 force_markup: bool = False, 29 expand_all: bool = False, 30 parse: bool = True, 31) -> str: 32 """Prettifies any Python object. 33 34 This uses a set of pre-defined aliases for the styling, and as such is fully 35 customizable. 36 37 The aliases are: 38 - `str`: Applied to all strings, so long as they do not contain TIM code. 39 - `int`: Applied to all integers and booleans. The latter are included as they 40 subclass int. 41 - `type`: Applied to all types. 42 - `none`: Applied to NoneType. Note that when using `pytermgui.pretty`, a 43 single `None` return value will not be printed, only when part of a more 44 complex structure. 45 46 Args: 47 target: The object to prettify. Can be any type. 48 indent: The indentation used for multi-line objects, like containers. When 49 set to 0, these will be collapsed. By default, container types with 50 `len() == 1` are always collapsed, regardless of this value. See 51 `expand_all` to overwrite that behaviour. 52 force_markup: When this is set every ANSI-sequence string will be turned 53 into markup and syntax highlighted. 54 expand_all: When set, objects that would normally be force-collapsed are 55 also going to be expanded. 56 parse: If not set, the return value will be a plain markup string, not yet 57 parsed. 58 59 Returns: 60 A pretty string of the given target. 61 """ 62 63 if isinstance(target, str): 64 if RE_MARKUP.match(target) is not None: 65 try: 66 highlighted_target = highlight_tim(target) 67 68 if parse: 69 return f'"{tim.parse(highlighted_target)}"' 70 71 return highlighted_target + "[/]" 72 73 except MarkupSyntaxError: 74 pass 75 76 if RE_ANSI.match(target) is not None: 77 return target + "\x1b[0m" 78 79 target = repr(target) 80 81 if isinstance(target, CONTAINER_TYPES): 82 if len(target) < 2 and not expand_all: 83 indent = 0 84 85 indent_str = ("\n" if indent > 0 else "") + indent * " " 86 87 chars = str(target)[0], str(target)[-1] 88 buff = chars[0] 89 90 if isinstance(target, (dict, UserDict)): 91 for i, (key, value) in enumerate(target.items()): 92 if i > 0: 93 buff += ", " 94 95 buff += indent_str + highlight_python(f"{key!r}: ") 96 97 pretty = prettify( 98 value, 99 indent=indent, 100 expand_all=expand_all, 101 force_markup=force_markup, 102 parse=False, 103 ) 104 105 lines = pretty.splitlines() 106 buff += lines[0] 107 108 for line in lines[1:]: 109 buff += indent_str + line 110 111 else: 112 for i, value in enumerate(target): 113 if i > 0: 114 buff += ", " 115 116 pretty = prettify( 117 value, 118 indent=indent, 119 expand_all=expand_all, 120 force_markup=force_markup, 121 parse=False, 122 ) 123 124 lines = pretty.splitlines() 125 126 for line in lines: 127 buff += indent_str + line 128 129 if indent > 0: 130 buff += "\n" 131 132 buff += chars[1] 133 134 if force_markup: 135 return buff 136 137 return tim.parse(buff) 138 139 if supports_fancy_repr(target): 140 buff = build_fancy_repr(target) 141 142 else: 143 buff = highlight_python(str(target)) 144 145 return tim.parse(buff) if parse else buff
def
prettify( target: Any, indent: int = 2, force_markup: bool = False, expand_all: bool = False, parse: bool = True) -> str:
26def prettify( # pylint: disable=too-many-branches 27 target: Any, 28 indent: int = 2, 29 force_markup: bool = False, 30 expand_all: bool = False, 31 parse: bool = True, 32) -> str: 33 """Prettifies any Python object. 34 35 This uses a set of pre-defined aliases for the styling, and as such is fully 36 customizable. 37 38 The aliases are: 39 - `str`: Applied to all strings, so long as they do not contain TIM code. 40 - `int`: Applied to all integers and booleans. The latter are included as they 41 subclass int. 42 - `type`: Applied to all types. 43 - `none`: Applied to NoneType. Note that when using `pytermgui.pretty`, a 44 single `None` return value will not be printed, only when part of a more 45 complex structure. 46 47 Args: 48 target: The object to prettify. Can be any type. 49 indent: The indentation used for multi-line objects, like containers. When 50 set to 0, these will be collapsed. By default, container types with 51 `len() == 1` are always collapsed, regardless of this value. See 52 `expand_all` to overwrite that behaviour. 53 force_markup: When this is set every ANSI-sequence string will be turned 54 into markup and syntax highlighted. 55 expand_all: When set, objects that would normally be force-collapsed are 56 also going to be expanded. 57 parse: If not set, the return value will be a plain markup string, not yet 58 parsed. 59 60 Returns: 61 A pretty string of the given target. 62 """ 63 64 if isinstance(target, str): 65 if RE_MARKUP.match(target) is not None: 66 try: 67 highlighted_target = highlight_tim(target) 68 69 if parse: 70 return f'"{tim.parse(highlighted_target)}"' 71 72 return highlighted_target + "[/]" 73 74 except MarkupSyntaxError: 75 pass 76 77 if RE_ANSI.match(target) is not None: 78 return target + "\x1b[0m" 79 80 target = repr(target) 81 82 if isinstance(target, CONTAINER_TYPES): 83 if len(target) < 2 and not expand_all: 84 indent = 0 85 86 indent_str = ("\n" if indent > 0 else "") + indent * " " 87 88 chars = str(target)[0], str(target)[-1] 89 buff = chars[0] 90 91 if isinstance(target, (dict, UserDict)): 92 for i, (key, value) in enumerate(target.items()): 93 if i > 0: 94 buff += ", " 95 96 buff += indent_str + highlight_python(f"{key!r}: ") 97 98 pretty = prettify( 99 value, 100 indent=indent, 101 expand_all=expand_all, 102 force_markup=force_markup, 103 parse=False, 104 ) 105 106 lines = pretty.splitlines() 107 buff += lines[0] 108 109 for line in lines[1:]: 110 buff += indent_str + line 111 112 else: 113 for i, value in enumerate(target): 114 if i > 0: 115 buff += ", " 116 117 pretty = prettify( 118 value, 119 indent=indent, 120 expand_all=expand_all, 121 force_markup=force_markup, 122 parse=False, 123 ) 124 125 lines = pretty.splitlines() 126 127 for line in lines: 128 buff += indent_str + line 129 130 if indent > 0: 131 buff += "\n" 132 133 buff += chars[1] 134 135 if force_markup: 136 return buff 137 138 return tim.parse(buff) 139 140 if supports_fancy_repr(target): 141 buff = build_fancy_repr(target) 142 143 else: 144 buff = highlight_python(str(target)) 145 146 return tim.parse(buff) if parse else buff
Prettifies any Python object.
This uses a set of pre-defined aliases for the styling, and as such is fully customizable.
The aliases are:
str: Applied to all strings, so long as they do not contain TIM code.int: Applied to all integers and booleans. The latter are included as they subclass int.type: Applied to all types.none: Applied to NoneType. Note that when usingpytermgui.pretty, a singleNonereturn value will not be printed, only when part of a more complex structure.
Args
- target: The object to prettify. Can be any type.
- indent: The indentation used for multi-line objects, like containers. When
set to 0, these will be collapsed. By default, container types with
len() == 1are always collapsed, regardless of this value. Seeexpand_allto overwrite that behaviour. - force_markup: When this is set every ANSI-sequence string will be turned into markup and syntax highlighted.
- expand_all: When set, objects that would normally be force-collapsed are also going to be expanded.
- parse: If not set, the return value will be a plain markup string, not yet parsed.
Returns
A pretty string of the given target.