]>
jfr.im git - dlqueue.git/blob - venv/lib/python3.11/site-packages/pip/_vendor/rich/cells.py
2 from functools
import lru_cache
3 from typing
import Callable
, List
5 from ._cell
_widths
import CELL_WIDTHS
7 # Regex to match sequence of the most common character ranges
8 _is_single_cell_widths
= re
.compile("^[\u0020-\u006f\u00a0\u02ff\u0370-\u0482]*$").match
12 def cached_cell_len(text
: str) -> int:
13 """Get the number of cells required to display text.
15 This method always caches, which may use up a lot of memory. It is recommended to use
16 `cell_len` over this method.
19 text (str): Text to display.
22 int: Get the number of cells required to display text.
24 _get_size
= get_character_cell_size
25 total_size
= sum(_get_size(character
) for character
in text
)
29 def cell_len(text
: str, _cell_len
: Callable
[[str], int] = cached_cell_len
) -> int:
30 """Get the number of cells required to display text.
33 text (str): Text to display.
36 int: Get the number of cells required to display text.
39 return _cell_len(text
)
40 _get_size
= get_character_cell_size
41 total_size
= sum(_get_size(character
) for character
in text
)
45 @lru_cache(maxsize
=4096)
46 def get_character_cell_size(character
: str) -> int:
47 """Get the cell size of a character.
50 character (str): A single character.
53 int: Number of cells (0, 1 or 2) occupied by that character.
55 return _get_codepoint_cell_size(ord(character
))
58 @lru_cache(maxsize
=4096)
59 def _get_codepoint_cell_size(codepoint
: int) -> int:
60 """Get the cell size of a character.
63 codepoint (int): Codepoint of a character.
66 int: Number of cells (0, 1 or 2) occupied by that character.
71 upper_bound
= len(_table
) - 1
72 index
= (lower_bound
+ upper_bound
) // 2
74 start
, end
, width
= _table
[index
]
76 upper_bound
= index
- 1
78 lower_bound
= index
+ 1
80 return 0 if width
== -1 else width
81 if upper_bound
< lower_bound
:
83 index
= (lower_bound
+ upper_bound
) // 2
87 def set_cell_size(text
: str, total
: int) -> str:
88 """Set the length of a string to fit within given number of cells."""
90 if _is_single_cell_widths(text
):
93 return text
+ " " * (total
- size
)
98 cell_size
= cell_len(text
)
99 if cell_size
== total
:
101 if cell_size
< total
:
102 return text
+ " " * (total
- cell_size
)
107 # Binary search until we find the right size
109 pos
= (start
+ end
) // 2
110 before
= text
[: pos
+ 1]
111 before_len
= cell_len(before
)
112 if before_len
== total
+ 1 and cell_len(before
[-1]) == 2:
113 return before
[:-1] + " "
114 if before_len
== total
:
116 if before_len
> total
:
122 # TODO: This is inefficient
123 # TODO: This might not work with CWJ type characters
124 def chop_cells(text
: str, max_size
: int, position
: int = 0) -> List
[str]:
125 """Break text in to equal (cell) length strings, returning the characters in reverse
127 _get_character_cell_size
= get_character_cell_size
129 (character
, _get_character_cell_size(character
)) for character
in text
131 total_size
= position
132 lines
: List
[List
[str]] = [[]]
133 append
= lines
[-1].append
135 for character
, size
in reversed(characters
):
136 if total_size
+ size
> max_size
:
137 lines
.append([character
])
138 append
= lines
[-1].append
144 return ["".join(line
) for line
in lines
]
147 if __name__
== "__main__": # pragma: no cover
149 print(get_character_cell_size("😽"))
150 for line
in chop_cells("""这是对亚洲语言支持的测试。面对模棱两可的想法,拒绝猜测的诱惑。""", 8):
152 for n
in range(80, 1, -1):
153 print(set_cell_size("""这是对亚洲语言支持的测试。面对模棱两可的想法,拒绝猜测的诱惑。""", n
) + "|")