Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/prompt_toolkit/layout/utils.py: 47%
36 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
1from __future__ import annotations
3from typing import TYPE_CHECKING, Iterable, List, TypeVar, cast, overload
5from prompt_toolkit.formatted_text.base import OneStyleAndTextTuple
7if TYPE_CHECKING:
8 from typing_extensions import SupportsIndex
10__all__ = [
11 "explode_text_fragments",
12]
14_T = TypeVar("_T", bound=OneStyleAndTextTuple)
17class _ExplodedList(List[_T]):
18 """
19 Wrapper around a list, that marks it as 'exploded'.
21 As soon as items are added or the list is extended, the new items are
22 automatically exploded as well.
23 """
25 exploded = True
27 def append(self, item: _T) -> None:
28 self.extend([item])
30 def extend(self, lst: Iterable[_T]) -> None:
31 super().extend(explode_text_fragments(lst))
33 def insert(self, index: SupportsIndex, item: _T) -> None:
34 raise NotImplementedError # TODO
36 # TODO: When creating a copy() or [:], return also an _ExplodedList.
38 @overload
39 def __setitem__(self, index: SupportsIndex, value: _T) -> None:
40 ...
42 @overload
43 def __setitem__(self, index: slice, value: Iterable[_T]) -> None:
44 ...
46 def __setitem__(
47 self, index: SupportsIndex | slice, value: _T | Iterable[_T]
48 ) -> None:
49 """
50 Ensure that when `(style_str, 'long string')` is set, the string will be
51 exploded.
52 """
53 if not isinstance(index, slice):
54 int_index = index.__index__()
55 index = slice(int_index, int_index + 1)
56 if isinstance(value, tuple): # In case of `OneStyleAndTextTuple`.
57 value = cast("List[_T]", [value])
59 super().__setitem__(index, explode_text_fragments(value))
62def explode_text_fragments(fragments: Iterable[_T]) -> _ExplodedList[_T]:
63 """
64 Turn a list of (style_str, text) tuples into another list where each string is
65 exactly one character.
67 It should be fine to call this function several times. Calling this on a
68 list that is already exploded, is a null operation.
70 :param fragments: List of (style, text) tuples.
71 """
72 # When the fragments is already exploded, don't explode again.
73 if isinstance(fragments, _ExplodedList):
74 return fragments
76 result: list[_T] = []
78 for style, string, *rest in fragments:
79 for c in string:
80 result.append((style, c, *rest)) # type: ignore
82 return _ExplodedList(result)