codekingpro/portable-devtools
114k
1from typing import Optional, Union2 3from .color import Color4from .console import Console, ConsoleOptions, RenderResult5from .jupyter import JupyterMixin6from .measure import Measurement7from .segment import Segment8from .style import Style9 10# There are left-aligned characters for 1/8 to 7/8, but11# the right-aligned characters exist only for 1/8 and 4/8.12BEGIN_BLOCK_ELEMENTS = ["█", "█", "█", "▐", "▐", "▐", "▕", "▕"]13END_BLOCK_ELEMENTS = [" ", "▏", "▎", "▍", "▌", "▋", "▊", "▉"]14FULL_BLOCK = "█"15 16 17class Bar(JupyterMixin):18 """Renders a solid block bar.19 20 Args:21 size (float): Value for the end of the bar.22 begin (float): Begin point (between 0 and size, inclusive).23 end (float): End point (between 0 and size, inclusive).24 width (int, optional): Width of the bar, or ``None`` for maximum width. Defaults to None.25 color (Union[Color, str], optional): Color of the bar. Defaults to "default".26 bgcolor (Union[Color, str], optional): Color of bar background. Defaults to "default".27 """28 29 def __init__(30 self,31 size: float,32 begin: float,33 end: float,34 *,35 width: Optional[int] = None,36 color: Union[Color, str] = "default",37 bgcolor: Union[Color, str] = "default",38 ):39 self.size = size40 self.begin = max(begin, 0)41 self.end = min(end, size)42 self.width = width43 self.style = Style(color=color, bgcolor=bgcolor)44 45 def __repr__(self) -> str:46 return f"Bar({self.size}, {self.begin}, {self.end})"47 48 def __rich_console__(49 self, console: Console, options: ConsoleOptions50 ) -> RenderResult:51 width = min(52 self.width if self.width is not None else options.max_width,53 options.max_width,54 )55 56 if self.begin >= self.end:57 yield Segment(" " * width, self.style)58 yield Segment.line()59 return60 61 prefix_complete_eights = int(width * 8 * self.begin / self.size)62 prefix_bar_count = prefix_complete_eights // 863 prefix_eights_count = prefix_complete_eights % 864 65 body_complete_eights = int(width * 8 * self.end / self.size)66 body_bar_count = body_complete_eights // 867 body_eights_count = body_complete_eights % 868 69 # When start and end fall into the same cell, we ideally should render70 # a symbol that's "center-aligned", but there is no good symbol in Unicode.71 # In this case, we fall back to right-aligned block symbol for simplicity.72 73 prefix = " " * prefix_bar_count74 if prefix_eights_count:75 prefix += BEGIN_BLOCK_ELEMENTS[prefix_eights_count]76 77 body = FULL_BLOCK * body_bar_count78 if body_eights_count:79 body += END_BLOCK_ELEMENTS[body_eights_count]80 81 suffix = " " * (width - len(body))82 83 yield Segment(prefix + body[len(prefix) :] + suffix, self.style)84 yield Segment.line()85 86 def __rich_measure__(87 self, console: Console, options: ConsoleOptions88 ) -> Measurement:89 return (90 Measurement(self.width, self.width)91 if self.width is not None92 else Measurement(4, options.max_width)93 )94 