def decode(src, errors: str = "strict") -> Text: current = ProtoStyle() state = 0 remaining = src segments: List[Tuple[str, Style]] = list() tag = None while len(remaining): if state == 0: idx_start = remaining.find("\002") if idx_start != -1: segments.append((remaining[:idx_start], current.convert())) remaining = remaining[idx_start + 1:] state = 1 else: segments.append((remaining, current.convert())) remaining = "" elif state == 1: # encountered a TAG START... tag = remaining[0] remaining = remaining[1:] state = 2 elif state == 2: # we are inside a tag. hoover up all data up to TAG_END... idx_end = remaining.find("\003") opening = True if idx_end != -1: tag_data = remaining[:idx_end] remaining = remaining[idx_end + 1:] if tag_data and tag_data[0] == "/": opening = False tag_data = tag_data[1:] if opening: current = ProtoStyle(parent=current) if tag == "p": apply_mxp(current, tag_data) elif tag == "c": current.inherit_ansi() apply_rules(current, tag_data) else: current = current.parent state = 0 else: # malformed data. break return Text.assemble(*segments)
def test_assemble(): text = Text.assemble("foo", ("bar", "bold")) assert str(text) == "foobar" assert text._spans == [Span(3, 6, "bold")]
if (match := CIRCLE_REGEX["bg_ansi"].match(remaining)): if segment: segments.append((segment, current.convert())) segment = "" current = ProtoStyle(current) apply_ansi_rule(current, "bg_ansi", remaining[0]) remaining = remaining[1:] escaped = None else: loc = find_first(remaining, ("&", "`", "}", "^")) if loc != -1: escaped = remaining[loc] segment += remaining[:loc] remaining = remaining[loc + 1:] else: segment += remaining remaining = "" if segment: segments.append((segment, current.convert())) return Text.assemble(*[(t, s) for t, s in segments]) def encode(src: Text) -> str: return "" def install(): Text.install_codec("circle", encode, decode)