Tipragot
628be439b8
Cela permet de ne pas avoir de problèmes de compatibilité car python est dans le git.
142 lines
4.9 KiB
Python
142 lines
4.9 KiB
Python
from typing import cast, List, Optional, Tuple, TYPE_CHECKING, Union
|
|
|
|
if TYPE_CHECKING:
|
|
from .console import (
|
|
Console,
|
|
ConsoleOptions,
|
|
RenderableType,
|
|
RenderResult,
|
|
)
|
|
from .jupyter import JupyterMixin
|
|
from .measure import Measurement
|
|
from .style import Style
|
|
from .segment import Segment
|
|
|
|
|
|
PaddingDimensions = Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int, int]]
|
|
|
|
|
|
class Padding(JupyterMixin):
|
|
"""Draw space around content.
|
|
|
|
Example:
|
|
>>> print(Padding("Hello", (2, 4), style="on blue"))
|
|
|
|
Args:
|
|
renderable (RenderableType): String or other renderable.
|
|
pad (Union[int, Tuple[int]]): Padding for top, right, bottom, and left borders.
|
|
May be specified with 1, 2, or 4 integers (CSS style).
|
|
style (Union[str, Style], optional): Style for padding characters. Defaults to "none".
|
|
expand (bool, optional): Expand padding to fit available width. Defaults to True.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
renderable: "RenderableType",
|
|
pad: "PaddingDimensions" = (0, 0, 0, 0),
|
|
*,
|
|
style: Union[str, Style] = "none",
|
|
expand: bool = True,
|
|
):
|
|
self.renderable = renderable
|
|
self.top, self.right, self.bottom, self.left = self.unpack(pad)
|
|
self.style = style
|
|
self.expand = expand
|
|
|
|
@classmethod
|
|
def indent(cls, renderable: "RenderableType", level: int) -> "Padding":
|
|
"""Make padding instance to render an indent.
|
|
|
|
Args:
|
|
renderable (RenderableType): String or other renderable.
|
|
level (int): Number of characters to indent.
|
|
|
|
Returns:
|
|
Padding: A Padding instance.
|
|
"""
|
|
|
|
return Padding(renderable, pad=(0, 0, 0, level), expand=False)
|
|
|
|
@staticmethod
|
|
def unpack(pad: "PaddingDimensions") -> Tuple[int, int, int, int]:
|
|
"""Unpack padding specified in CSS style."""
|
|
if isinstance(pad, int):
|
|
return (pad, pad, pad, pad)
|
|
if len(pad) == 1:
|
|
_pad = pad[0]
|
|
return (_pad, _pad, _pad, _pad)
|
|
if len(pad) == 2:
|
|
pad_top, pad_right = cast(Tuple[int, int], pad)
|
|
return (pad_top, pad_right, pad_top, pad_right)
|
|
if len(pad) == 4:
|
|
top, right, bottom, left = cast(Tuple[int, int, int, int], pad)
|
|
return (top, right, bottom, left)
|
|
raise ValueError(f"1, 2 or 4 integers required for padding; {len(pad)} given")
|
|
|
|
def __repr__(self) -> str:
|
|
return f"Padding({self.renderable!r}, ({self.top},{self.right},{self.bottom},{self.left}))"
|
|
|
|
def __rich_console__(
|
|
self, console: "Console", options: "ConsoleOptions"
|
|
) -> "RenderResult":
|
|
style = console.get_style(self.style)
|
|
if self.expand:
|
|
width = options.max_width
|
|
else:
|
|
width = min(
|
|
Measurement.get(console, options, self.renderable).maximum
|
|
+ self.left
|
|
+ self.right,
|
|
options.max_width,
|
|
)
|
|
render_options = options.update_width(width - self.left - self.right)
|
|
if render_options.height is not None:
|
|
render_options = render_options.update_height(
|
|
height=render_options.height - self.top - self.bottom
|
|
)
|
|
lines = console.render_lines(
|
|
self.renderable, render_options, style=style, pad=True
|
|
)
|
|
_Segment = Segment
|
|
|
|
left = _Segment(" " * self.left, style) if self.left else None
|
|
right = (
|
|
[_Segment(f'{" " * self.right}', style), _Segment.line()]
|
|
if self.right
|
|
else [_Segment.line()]
|
|
)
|
|
blank_line: Optional[List[Segment]] = None
|
|
if self.top:
|
|
blank_line = [_Segment(f'{" " * width}\n', style)]
|
|
yield from blank_line * self.top
|
|
if left:
|
|
for line in lines:
|
|
yield left
|
|
yield from line
|
|
yield from right
|
|
else:
|
|
for line in lines:
|
|
yield from line
|
|
yield from right
|
|
if self.bottom:
|
|
blank_line = blank_line or [_Segment(f'{" " * width}\n', style)]
|
|
yield from blank_line * self.bottom
|
|
|
|
def __rich_measure__(
|
|
self, console: "Console", options: "ConsoleOptions"
|
|
) -> "Measurement":
|
|
max_width = options.max_width
|
|
extra_width = self.left + self.right
|
|
if max_width - extra_width < 1:
|
|
return Measurement(max_width, max_width)
|
|
measure_min, measure_max = Measurement.get(console, options, self.renderable)
|
|
measurement = Measurement(measure_min + extra_width, measure_max + extra_width)
|
|
measurement = measurement.with_maximum(max_width)
|
|
return measurement
|
|
|
|
|
|
if __name__ == "__main__": # pragma: no cover
|
|
from pip._vendor.rich import print
|
|
|
|
print(Padding("Hello, World", (2, 4), style="on blue"))
|