123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- 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"))
|