Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| from typing import TYPE_CHECKING, Iterable, List, TypeVar, cast, overload | |
| from prompt_toolkit.formatted_text.base import OneStyleAndTextTuple | |
| if TYPE_CHECKING: | |
| from typing_extensions import SupportsIndex | |
| __all__ = [ | |
| "explode_text_fragments", | |
| ] | |
| _T = TypeVar("_T", bound=OneStyleAndTextTuple) | |
| class _ExplodedList(List[_T]): | |
| """ | |
| Wrapper around a list, that marks it as 'exploded'. | |
| As soon as items are added or the list is extended, the new items are | |
| automatically exploded as well. | |
| """ | |
| exploded = True | |
| def append(self, item: _T) -> None: | |
| self.extend([item]) | |
| def extend(self, lst: Iterable[_T]) -> None: | |
| super().extend(explode_text_fragments(lst)) | |
| def insert(self, index: SupportsIndex, item: _T) -> None: | |
| raise NotImplementedError # TODO | |
| # TODO: When creating a copy() or [:], return also an _ExplodedList. | |
| def __setitem__(self, index: SupportsIndex, value: _T) -> None: ... | |
| def __setitem__(self, index: slice, value: Iterable[_T]) -> None: ... | |
| def __setitem__( | |
| self, index: SupportsIndex | slice, value: _T | Iterable[_T] | |
| ) -> None: | |
| """ | |
| Ensure that when `(style_str, 'long string')` is set, the string will be | |
| exploded. | |
| """ | |
| if not isinstance(index, slice): | |
| int_index = index.__index__() | |
| index = slice(int_index, int_index + 1) | |
| if isinstance(value, tuple): # In case of `OneStyleAndTextTuple`. | |
| value = cast("List[_T]", [value]) | |
| super().__setitem__(index, explode_text_fragments(value)) | |
| def explode_text_fragments(fragments: Iterable[_T]) -> _ExplodedList[_T]: | |
| """ | |
| Turn a list of (style_str, text) tuples into another list where each string is | |
| exactly one character. | |
| It should be fine to call this function several times. Calling this on a | |
| list that is already exploded, is a null operation. | |
| :param fragments: List of (style, text) tuples. | |
| """ | |
| # When the fragments is already exploded, don't explode again. | |
| if isinstance(fragments, _ExplodedList): | |
| return fragments | |
| result: list[_T] = [] | |
| for style, string, *rest in fragments: | |
| for c in string: | |
| result.append((style, c, *rest)) # type: ignore | |
| return _ExplodedList(result) | |