Загрузить файлы в «venv/Lib/site-packages/pip/_vendor/rich»
This commit is contained in:
187
venv/Lib/site-packages/pip/_vendor/rich/columns.py
Normal file
187
venv/Lib/site-packages/pip/_vendor/rich/columns.py
Normal file
@@ -0,0 +1,187 @@
|
||||
from collections import defaultdict
|
||||
from itertools import chain
|
||||
from operator import itemgetter
|
||||
from typing import Dict, Iterable, List, Optional, Tuple
|
||||
|
||||
from .align import Align, AlignMethod
|
||||
from .console import Console, ConsoleOptions, RenderableType, RenderResult
|
||||
from .constrain import Constrain
|
||||
from .measure import Measurement
|
||||
from .padding import Padding, PaddingDimensions
|
||||
from .table import Table
|
||||
from .text import TextType
|
||||
from .jupyter import JupyterMixin
|
||||
|
||||
|
||||
class Columns(JupyterMixin):
|
||||
"""Display renderables in neat columns.
|
||||
|
||||
Args:
|
||||
renderables (Iterable[RenderableType]): Any number of Rich renderables (including str).
|
||||
width (int, optional): The desired width of the columns, or None to auto detect. Defaults to None.
|
||||
padding (PaddingDimensions, optional): Optional padding around cells. Defaults to (0, 1).
|
||||
expand (bool, optional): Expand columns to full width. Defaults to False.
|
||||
equal (bool, optional): Arrange in to equal sized columns. Defaults to False.
|
||||
column_first (bool, optional): Align items from top to bottom (rather than left to right). Defaults to False.
|
||||
right_to_left (bool, optional): Start column from right hand side. Defaults to False.
|
||||
align (str, optional): Align value ("left", "right", or "center") or None for default. Defaults to None.
|
||||
title (TextType, optional): Optional title for Columns.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
renderables: Optional[Iterable[RenderableType]] = None,
|
||||
padding: PaddingDimensions = (0, 1),
|
||||
*,
|
||||
width: Optional[int] = None,
|
||||
expand: bool = False,
|
||||
equal: bool = False,
|
||||
column_first: bool = False,
|
||||
right_to_left: bool = False,
|
||||
align: Optional[AlignMethod] = None,
|
||||
title: Optional[TextType] = None,
|
||||
) -> None:
|
||||
self.renderables = list(renderables or [])
|
||||
self.width = width
|
||||
self.padding = padding
|
||||
self.expand = expand
|
||||
self.equal = equal
|
||||
self.column_first = column_first
|
||||
self.right_to_left = right_to_left
|
||||
self.align: Optional[AlignMethod] = align
|
||||
self.title = title
|
||||
|
||||
def add_renderable(self, renderable: RenderableType) -> None:
|
||||
"""Add a renderable to the columns.
|
||||
|
||||
Args:
|
||||
renderable (RenderableType): Any renderable object.
|
||||
"""
|
||||
self.renderables.append(renderable)
|
||||
|
||||
def __rich_console__(
|
||||
self, console: Console, options: ConsoleOptions
|
||||
) -> RenderResult:
|
||||
render_str = console.render_str
|
||||
renderables = [
|
||||
render_str(renderable) if isinstance(renderable, str) else renderable
|
||||
for renderable in self.renderables
|
||||
]
|
||||
if not renderables:
|
||||
return
|
||||
_top, right, _bottom, left = Padding.unpack(self.padding)
|
||||
width_padding = max(left, right)
|
||||
max_width = options.max_width
|
||||
widths: Dict[int, int] = defaultdict(int)
|
||||
column_count = len(renderables)
|
||||
|
||||
get_measurement = Measurement.get
|
||||
renderable_widths = [
|
||||
get_measurement(console, options, renderable).maximum
|
||||
for renderable in renderables
|
||||
]
|
||||
if self.equal:
|
||||
renderable_widths = [max(renderable_widths)] * len(renderable_widths)
|
||||
|
||||
def iter_renderables(
|
||||
column_count: int,
|
||||
) -> Iterable[Tuple[int, Optional[RenderableType]]]:
|
||||
item_count = len(renderables)
|
||||
if self.column_first:
|
||||
width_renderables = list(zip(renderable_widths, renderables))
|
||||
|
||||
column_lengths: List[int] = [item_count // column_count] * column_count
|
||||
for col_no in range(item_count % column_count):
|
||||
column_lengths[col_no] += 1
|
||||
|
||||
row_count = (item_count + column_count - 1) // column_count
|
||||
cells = [[-1] * column_count for _ in range(row_count)]
|
||||
row = col = 0
|
||||
for index in range(item_count):
|
||||
cells[row][col] = index
|
||||
column_lengths[col] -= 1
|
||||
if column_lengths[col]:
|
||||
row += 1
|
||||
else:
|
||||
col += 1
|
||||
row = 0
|
||||
for index in chain.from_iterable(cells):
|
||||
if index == -1:
|
||||
break
|
||||
yield width_renderables[index]
|
||||
else:
|
||||
yield from zip(renderable_widths, renderables)
|
||||
# Pad odd elements with spaces
|
||||
if item_count % column_count:
|
||||
for _ in range(column_count - (item_count % column_count)):
|
||||
yield 0, None
|
||||
|
||||
table = Table.grid(padding=self.padding, collapse_padding=True, pad_edge=False)
|
||||
table.expand = self.expand
|
||||
table.title = self.title
|
||||
|
||||
if self.width is not None:
|
||||
column_count = (max_width) // (self.width + width_padding)
|
||||
for _ in range(column_count):
|
||||
table.add_column(width=self.width)
|
||||
else:
|
||||
while column_count > 1:
|
||||
widths.clear()
|
||||
column_no = 0
|
||||
for renderable_width, _ in iter_renderables(column_count):
|
||||
widths[column_no] = max(widths[column_no], renderable_width)
|
||||
total_width = sum(widths.values()) + width_padding * (
|
||||
len(widths) - 1
|
||||
)
|
||||
if total_width > max_width:
|
||||
column_count = len(widths) - 1
|
||||
break
|
||||
else:
|
||||
column_no = (column_no + 1) % column_count
|
||||
else:
|
||||
break
|
||||
|
||||
get_renderable = itemgetter(1)
|
||||
_renderables = [
|
||||
get_renderable(_renderable)
|
||||
for _renderable in iter_renderables(column_count)
|
||||
]
|
||||
if self.equal:
|
||||
_renderables = [
|
||||
None
|
||||
if renderable is None
|
||||
else Constrain(renderable, renderable_widths[0])
|
||||
for renderable in _renderables
|
||||
]
|
||||
if self.align:
|
||||
align = self.align
|
||||
_Align = Align
|
||||
_renderables = [
|
||||
None if renderable is None else _Align(renderable, align)
|
||||
for renderable in _renderables
|
||||
]
|
||||
|
||||
right_to_left = self.right_to_left
|
||||
add_row = table.add_row
|
||||
for start in range(0, len(_renderables), column_count):
|
||||
row = _renderables[start : start + column_count]
|
||||
if right_to_left:
|
||||
row = row[::-1]
|
||||
add_row(*row)
|
||||
yield table
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
import os
|
||||
|
||||
console = Console()
|
||||
|
||||
files = [f"{i} {s}" for i, s in enumerate(sorted(os.listdir()))]
|
||||
columns = Columns(files, padding=(0, 1), expand=False, equal=False)
|
||||
console.print(columns)
|
||||
console.rule()
|
||||
columns.column_first = True
|
||||
console.print(columns)
|
||||
columns.right_to_left = True
|
||||
console.rule()
|
||||
console.print(columns)
|
||||
2680
venv/Lib/site-packages/pip/_vendor/rich/console.py
Normal file
2680
venv/Lib/site-packages/pip/_vendor/rich/console.py
Normal file
File diff suppressed because it is too large
Load Diff
37
venv/Lib/site-packages/pip/_vendor/rich/constrain.py
Normal file
37
venv/Lib/site-packages/pip/_vendor/rich/constrain.py
Normal file
@@ -0,0 +1,37 @@
|
||||
from typing import Optional, TYPE_CHECKING
|
||||
|
||||
from .jupyter import JupyterMixin
|
||||
from .measure import Measurement
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .console import Console, ConsoleOptions, RenderableType, RenderResult
|
||||
|
||||
|
||||
class Constrain(JupyterMixin):
|
||||
"""Constrain the width of a renderable to a given number of characters.
|
||||
|
||||
Args:
|
||||
renderable (RenderableType): A renderable object.
|
||||
width (int, optional): The maximum width (in characters) to render. Defaults to 80.
|
||||
"""
|
||||
|
||||
def __init__(self, renderable: "RenderableType", width: Optional[int] = 80) -> None:
|
||||
self.renderable = renderable
|
||||
self.width = width
|
||||
|
||||
def __rich_console__(
|
||||
self, console: "Console", options: "ConsoleOptions"
|
||||
) -> "RenderResult":
|
||||
if self.width is None:
|
||||
yield self.renderable
|
||||
else:
|
||||
child_options = options.update_width(min(self.width, options.max_width))
|
||||
yield from console.render(self.renderable, child_options)
|
||||
|
||||
def __rich_measure__(
|
||||
self, console: "Console", options: "ConsoleOptions"
|
||||
) -> "Measurement":
|
||||
if self.width is not None:
|
||||
options = options.update_width(self.width)
|
||||
measurement = Measurement.get(console, options, self.renderable)
|
||||
return measurement
|
||||
167
venv/Lib/site-packages/pip/_vendor/rich/containers.py
Normal file
167
venv/Lib/site-packages/pip/_vendor/rich/containers.py
Normal file
@@ -0,0 +1,167 @@
|
||||
from itertools import zip_longest
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Iterable,
|
||||
Iterator,
|
||||
List,
|
||||
Optional,
|
||||
TypeVar,
|
||||
Union,
|
||||
overload,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .console import (
|
||||
Console,
|
||||
ConsoleOptions,
|
||||
JustifyMethod,
|
||||
OverflowMethod,
|
||||
RenderResult,
|
||||
RenderableType,
|
||||
)
|
||||
from .text import Text
|
||||
|
||||
from .cells import cell_len
|
||||
from .measure import Measurement
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class Renderables:
|
||||
"""A list subclass which renders its contents to the console."""
|
||||
|
||||
def __init__(
|
||||
self, renderables: Optional[Iterable["RenderableType"]] = None
|
||||
) -> None:
|
||||
self._renderables: List["RenderableType"] = (
|
||||
list(renderables) if renderables is not None else []
|
||||
)
|
||||
|
||||
def __rich_console__(
|
||||
self, console: "Console", options: "ConsoleOptions"
|
||||
) -> "RenderResult":
|
||||
"""Console render method to insert line-breaks."""
|
||||
yield from self._renderables
|
||||
|
||||
def __rich_measure__(
|
||||
self, console: "Console", options: "ConsoleOptions"
|
||||
) -> "Measurement":
|
||||
dimensions = [
|
||||
Measurement.get(console, options, renderable)
|
||||
for renderable in self._renderables
|
||||
]
|
||||
if not dimensions:
|
||||
return Measurement(1, 1)
|
||||
_min = max(dimension.minimum for dimension in dimensions)
|
||||
_max = max(dimension.maximum for dimension in dimensions)
|
||||
return Measurement(_min, _max)
|
||||
|
||||
def append(self, renderable: "RenderableType") -> None:
|
||||
self._renderables.append(renderable)
|
||||
|
||||
def __iter__(self) -> Iterable["RenderableType"]:
|
||||
return iter(self._renderables)
|
||||
|
||||
|
||||
class Lines:
|
||||
"""A list subclass which can render to the console."""
|
||||
|
||||
def __init__(self, lines: Iterable["Text"] = ()) -> None:
|
||||
self._lines: List["Text"] = list(lines)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Lines({self._lines!r})"
|
||||
|
||||
def __iter__(self) -> Iterator["Text"]:
|
||||
return iter(self._lines)
|
||||
|
||||
@overload
|
||||
def __getitem__(self, index: int) -> "Text":
|
||||
...
|
||||
|
||||
@overload
|
||||
def __getitem__(self, index: slice) -> List["Text"]:
|
||||
...
|
||||
|
||||
def __getitem__(self, index: Union[slice, int]) -> Union["Text", List["Text"]]:
|
||||
return self._lines[index]
|
||||
|
||||
def __setitem__(self, index: int, value: "Text") -> "Lines":
|
||||
self._lines[index] = value
|
||||
return self
|
||||
|
||||
def __len__(self) -> int:
|
||||
return self._lines.__len__()
|
||||
|
||||
def __rich_console__(
|
||||
self, console: "Console", options: "ConsoleOptions"
|
||||
) -> "RenderResult":
|
||||
"""Console render method to insert line-breaks."""
|
||||
yield from self._lines
|
||||
|
||||
def append(self, line: "Text") -> None:
|
||||
self._lines.append(line)
|
||||
|
||||
def extend(self, lines: Iterable["Text"]) -> None:
|
||||
self._lines.extend(lines)
|
||||
|
||||
def pop(self, index: int = -1) -> "Text":
|
||||
return self._lines.pop(index)
|
||||
|
||||
def justify(
|
||||
self,
|
||||
console: "Console",
|
||||
width: int,
|
||||
justify: "JustifyMethod" = "left",
|
||||
overflow: "OverflowMethod" = "fold",
|
||||
) -> None:
|
||||
"""Justify and overflow text to a given width.
|
||||
|
||||
Args:
|
||||
console (Console): Console instance.
|
||||
width (int): Number of cells available per line.
|
||||
justify (str, optional): Default justify method for text: "left", "center", "full" or "right". Defaults to "left".
|
||||
overflow (str, optional): Default overflow for text: "crop", "fold", or "ellipsis". Defaults to "fold".
|
||||
|
||||
"""
|
||||
from .text import Text
|
||||
|
||||
if justify == "left":
|
||||
for line in self._lines:
|
||||
line.truncate(width, overflow=overflow, pad=True)
|
||||
elif justify == "center":
|
||||
for line in self._lines:
|
||||
line.rstrip()
|
||||
line.truncate(width, overflow=overflow)
|
||||
line.pad_left((width - cell_len(line.plain)) // 2)
|
||||
line.pad_right(width - cell_len(line.plain))
|
||||
elif justify == "right":
|
||||
for line in self._lines:
|
||||
line.rstrip()
|
||||
line.truncate(width, overflow=overflow)
|
||||
line.pad_left(width - cell_len(line.plain))
|
||||
elif justify == "full":
|
||||
for line_index, line in enumerate(self._lines):
|
||||
if line_index == len(self._lines) - 1:
|
||||
break
|
||||
words = line.split(" ")
|
||||
words_size = sum(cell_len(word.plain) for word in words)
|
||||
num_spaces = len(words) - 1
|
||||
spaces = [1 for _ in range(num_spaces)]
|
||||
index = 0
|
||||
if spaces:
|
||||
while words_size + num_spaces < width:
|
||||
spaces[len(spaces) - index - 1] += 1
|
||||
num_spaces += 1
|
||||
index = (index + 1) % len(spaces)
|
||||
tokens: List[Text] = []
|
||||
for index, (word, next_word) in enumerate(
|
||||
zip_longest(words, words[1:])
|
||||
):
|
||||
tokens.append(word)
|
||||
if index < len(spaces):
|
||||
style = word.get_style_at_offset(console, -1)
|
||||
next_style = next_word.get_style_at_offset(console, 0)
|
||||
space_style = style if style == next_style else line.style
|
||||
tokens.append(Text(" " * spaces[index], style=space_style))
|
||||
self[line_index] = Text("").join(tokens)
|
||||
219
venv/Lib/site-packages/pip/_vendor/rich/control.py
Normal file
219
venv/Lib/site-packages/pip/_vendor/rich/control.py
Normal file
@@ -0,0 +1,219 @@
|
||||
import time
|
||||
from typing import TYPE_CHECKING, Callable, Dict, Iterable, List, Union, Final
|
||||
|
||||
from .segment import ControlCode, ControlType, Segment
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .console import Console, ConsoleOptions, RenderResult
|
||||
|
||||
STRIP_CONTROL_CODES: Final = [
|
||||
7, # Bell
|
||||
8, # Backspace
|
||||
11, # Vertical tab
|
||||
12, # Form feed
|
||||
13, # Carriage return
|
||||
]
|
||||
_CONTROL_STRIP_TRANSLATE: Final = {
|
||||
_codepoint: None for _codepoint in STRIP_CONTROL_CODES
|
||||
}
|
||||
|
||||
CONTROL_ESCAPE: Final = {
|
||||
7: "\\a",
|
||||
8: "\\b",
|
||||
11: "\\v",
|
||||
12: "\\f",
|
||||
13: "\\r",
|
||||
}
|
||||
|
||||
CONTROL_CODES_FORMAT: Dict[int, Callable[..., str]] = {
|
||||
ControlType.BELL: lambda: "\x07",
|
||||
ControlType.CARRIAGE_RETURN: lambda: "\r",
|
||||
ControlType.HOME: lambda: "\x1b[H",
|
||||
ControlType.CLEAR: lambda: "\x1b[2J",
|
||||
ControlType.ENABLE_ALT_SCREEN: lambda: "\x1b[?1049h",
|
||||
ControlType.DISABLE_ALT_SCREEN: lambda: "\x1b[?1049l",
|
||||
ControlType.SHOW_CURSOR: lambda: "\x1b[?25h",
|
||||
ControlType.HIDE_CURSOR: lambda: "\x1b[?25l",
|
||||
ControlType.CURSOR_UP: lambda param: f"\x1b[{param}A",
|
||||
ControlType.CURSOR_DOWN: lambda param: f"\x1b[{param}B",
|
||||
ControlType.CURSOR_FORWARD: lambda param: f"\x1b[{param}C",
|
||||
ControlType.CURSOR_BACKWARD: lambda param: f"\x1b[{param}D",
|
||||
ControlType.CURSOR_MOVE_TO_COLUMN: lambda param: f"\x1b[{param+1}G",
|
||||
ControlType.ERASE_IN_LINE: lambda param: f"\x1b[{param}K",
|
||||
ControlType.CURSOR_MOVE_TO: lambda x, y: f"\x1b[{y+1};{x+1}H",
|
||||
ControlType.SET_WINDOW_TITLE: lambda title: f"\x1b]0;{title}\x07",
|
||||
}
|
||||
|
||||
|
||||
class Control:
|
||||
"""A renderable that inserts a control code (non printable but may move cursor).
|
||||
|
||||
Args:
|
||||
*codes (str): Positional arguments are either a :class:`~rich.segment.ControlType` enum or a
|
||||
tuple of ControlType and an integer parameter
|
||||
"""
|
||||
|
||||
__slots__ = ["segment"]
|
||||
|
||||
def __init__(self, *codes: Union[ControlType, ControlCode]) -> None:
|
||||
control_codes: List[ControlCode] = [
|
||||
(code,) if isinstance(code, ControlType) else code for code in codes
|
||||
]
|
||||
_format_map = CONTROL_CODES_FORMAT
|
||||
rendered_codes = "".join(
|
||||
_format_map[code](*parameters) for code, *parameters in control_codes
|
||||
)
|
||||
self.segment = Segment(rendered_codes, None, control_codes)
|
||||
|
||||
@classmethod
|
||||
def bell(cls) -> "Control":
|
||||
"""Ring the 'bell'."""
|
||||
return cls(ControlType.BELL)
|
||||
|
||||
@classmethod
|
||||
def home(cls) -> "Control":
|
||||
"""Move cursor to 'home' position."""
|
||||
return cls(ControlType.HOME)
|
||||
|
||||
@classmethod
|
||||
def move(cls, x: int = 0, y: int = 0) -> "Control":
|
||||
"""Move cursor relative to current position.
|
||||
|
||||
Args:
|
||||
x (int): X offset.
|
||||
y (int): Y offset.
|
||||
|
||||
Returns:
|
||||
~Control: Control object.
|
||||
|
||||
"""
|
||||
|
||||
def get_codes() -> Iterable[ControlCode]:
|
||||
control = ControlType
|
||||
if x:
|
||||
yield (
|
||||
control.CURSOR_FORWARD if x > 0 else control.CURSOR_BACKWARD,
|
||||
abs(x),
|
||||
)
|
||||
if y:
|
||||
yield (
|
||||
control.CURSOR_DOWN if y > 0 else control.CURSOR_UP,
|
||||
abs(y),
|
||||
)
|
||||
|
||||
control = cls(*get_codes())
|
||||
return control
|
||||
|
||||
@classmethod
|
||||
def move_to_column(cls, x: int, y: int = 0) -> "Control":
|
||||
"""Move to the given column, optionally add offset to row.
|
||||
|
||||
Returns:
|
||||
x (int): absolute x (column)
|
||||
y (int): optional y offset (row)
|
||||
|
||||
Returns:
|
||||
~Control: Control object.
|
||||
"""
|
||||
|
||||
return (
|
||||
cls(
|
||||
(ControlType.CURSOR_MOVE_TO_COLUMN, x),
|
||||
(
|
||||
ControlType.CURSOR_DOWN if y > 0 else ControlType.CURSOR_UP,
|
||||
abs(y),
|
||||
),
|
||||
)
|
||||
if y
|
||||
else cls((ControlType.CURSOR_MOVE_TO_COLUMN, x))
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def move_to(cls, x: int, y: int) -> "Control":
|
||||
"""Move cursor to absolute position.
|
||||
|
||||
Args:
|
||||
x (int): x offset (column)
|
||||
y (int): y offset (row)
|
||||
|
||||
Returns:
|
||||
~Control: Control object.
|
||||
"""
|
||||
return cls((ControlType.CURSOR_MOVE_TO, x, y))
|
||||
|
||||
@classmethod
|
||||
def clear(cls) -> "Control":
|
||||
"""Clear the screen."""
|
||||
return cls(ControlType.CLEAR)
|
||||
|
||||
@classmethod
|
||||
def show_cursor(cls, show: bool) -> "Control":
|
||||
"""Show or hide the cursor."""
|
||||
return cls(ControlType.SHOW_CURSOR if show else ControlType.HIDE_CURSOR)
|
||||
|
||||
@classmethod
|
||||
def alt_screen(cls, enable: bool) -> "Control":
|
||||
"""Enable or disable alt screen."""
|
||||
if enable:
|
||||
return cls(ControlType.ENABLE_ALT_SCREEN, ControlType.HOME)
|
||||
else:
|
||||
return cls(ControlType.DISABLE_ALT_SCREEN)
|
||||
|
||||
@classmethod
|
||||
def title(cls, title: str) -> "Control":
|
||||
"""Set the terminal window title
|
||||
|
||||
Args:
|
||||
title (str): The new terminal window title
|
||||
"""
|
||||
return cls((ControlType.SET_WINDOW_TITLE, title))
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.segment.text
|
||||
|
||||
def __rich_console__(
|
||||
self, console: "Console", options: "ConsoleOptions"
|
||||
) -> "RenderResult":
|
||||
if self.segment.text:
|
||||
yield self.segment
|
||||
|
||||
|
||||
def strip_control_codes(
|
||||
text: str, _translate_table: Dict[int, None] = _CONTROL_STRIP_TRANSLATE
|
||||
) -> str:
|
||||
"""Remove control codes from text.
|
||||
|
||||
Args:
|
||||
text (str): A string possibly contain control codes.
|
||||
|
||||
Returns:
|
||||
str: String with control codes removed.
|
||||
"""
|
||||
return text.translate(_translate_table)
|
||||
|
||||
|
||||
def escape_control_codes(
|
||||
text: str,
|
||||
_translate_table: Dict[int, str] = CONTROL_ESCAPE,
|
||||
) -> str:
|
||||
"""Replace control codes with their "escaped" equivalent in the given text.
|
||||
(e.g. "\b" becomes "\\b")
|
||||
|
||||
Args:
|
||||
text (str): A string possibly containing control codes.
|
||||
|
||||
Returns:
|
||||
str: String with control codes replaced with their escaped version.
|
||||
"""
|
||||
return text.translate(_translate_table)
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
from pip._vendor.rich.console import Console
|
||||
|
||||
console = Console()
|
||||
console.print("Look at the title of your terminal window ^")
|
||||
# console.print(Control((ControlType.SET_WINDOW_TITLE, "Hello, world!")))
|
||||
for i in range(10):
|
||||
console.set_window_title("🚀 Loading" + "." * i)
|
||||
time.sleep(0.5)
|
||||
Reference in New Issue
Block a user