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 rich import print
print ( Padding ( " Hello, World " , ( 2 , 4 ) , style = " on blue " ) )