forked from Textualize/rich
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpadding.py
88 lines (74 loc) · 2.91 KB
/
padding.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
from __future__ import annotations
from typing import cast, Tuple, Union
from .console import (
Console,
ConsoleOptions,
RenderableType,
RenderResult,
RenderWidth,
)
from .style import Style
from .text import Text
from .segment import Segment
PaddingDimensions = Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int, int]]
class Padding:
"""Draw space around a console renderable."""
def __init__(
self,
renderable: RenderableType,
pad: PaddingDimensions,
*,
style: Union[str, Style] = "none",
):
self.renderable = renderable
self.top, self.right, self.bottom, self.left = self.unpack(pad)
self.style = style
@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) == 3:
raise ValueError(
f"1, 2 or 4 integers required for padding; {len(pad)} given"
)
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 __console__(self, console: Console, options: ConsoleOptions) -> RenderResult:
style = console.get_style(self.style)
width = options.max_width
child_options = options.update(width=width - self.left - self.right)
lines = console.render_lines(self.renderable, child_options)
lines = Segment.set_shape(lines, child_options.max_width)
blank_line = Segment(" " * width + "\n", style)
top = [blank_line] * self.top
bottom = [blank_line] * self.top
left = Segment(" " * self.left, style) if self.left else None
right = Segment(" " * self.right, style) if self.right else None
new_line = Segment.line()
yield from top
for line in lines:
if left is not None:
yield left
yield from line
if right is not None:
yield right
yield new_line
yield from bottom
def __console_width__(self, max_width: int) -> RenderWidth:
extra_width = self.left + self.right
min_width, max_width = RenderWidth.get(
self.renderable, max(1, max_width - extra_width)
)
render_width = RenderWidth(min_width + extra_width, max_width + extra_width)
return render_width