Tipragot
628be439b8
Cela permet de ne pas avoir de problèmes de compatibilité car python est dans le git.
95 lines
3.2 KiB
Python
95 lines
3.2 KiB
Python
from typing import Optional, Union
|
|
|
|
from .color import Color
|
|
from .console import Console, ConsoleOptions, RenderResult
|
|
from .jupyter import JupyterMixin
|
|
from .measure import Measurement
|
|
from .segment import Segment
|
|
from .style import Style
|
|
|
|
# There are left-aligned characters for 1/8 to 7/8, but
|
|
# the right-aligned characters exist only for 1/8 and 4/8.
|
|
BEGIN_BLOCK_ELEMENTS = ["█", "█", "█", "▐", "▐", "▐", "▕", "▕"]
|
|
END_BLOCK_ELEMENTS = [" ", "▏", "▎", "▍", "▌", "▋", "▊", "▉"]
|
|
FULL_BLOCK = "█"
|
|
|
|
|
|
class Bar(JupyterMixin):
|
|
"""Renders a solid block bar.
|
|
|
|
Args:
|
|
size (float): Value for the end of the bar.
|
|
begin (float): Begin point (between 0 and size, inclusive).
|
|
end (float): End point (between 0 and size, inclusive).
|
|
width (int, optional): Width of the bar, or ``None`` for maximum width. Defaults to None.
|
|
color (Union[Color, str], optional): Color of the bar. Defaults to "default".
|
|
bgcolor (Union[Color, str], optional): Color of bar background. Defaults to "default".
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
size: float,
|
|
begin: float,
|
|
end: float,
|
|
*,
|
|
width: Optional[int] = None,
|
|
color: Union[Color, str] = "default",
|
|
bgcolor: Union[Color, str] = "default",
|
|
):
|
|
self.size = size
|
|
self.begin = max(begin, 0)
|
|
self.end = min(end, size)
|
|
self.width = width
|
|
self.style = Style(color=color, bgcolor=bgcolor)
|
|
|
|
def __repr__(self) -> str:
|
|
return f"Bar({self.size}, {self.begin}, {self.end})"
|
|
|
|
def __rich_console__(
|
|
self, console: Console, options: ConsoleOptions
|
|
) -> RenderResult:
|
|
|
|
width = min(
|
|
self.width if self.width is not None else options.max_width,
|
|
options.max_width,
|
|
)
|
|
|
|
if self.begin >= self.end:
|
|
yield Segment(" " * width, self.style)
|
|
yield Segment.line()
|
|
return
|
|
|
|
prefix_complete_eights = int(width * 8 * self.begin / self.size)
|
|
prefix_bar_count = prefix_complete_eights // 8
|
|
prefix_eights_count = prefix_complete_eights % 8
|
|
|
|
body_complete_eights = int(width * 8 * self.end / self.size)
|
|
body_bar_count = body_complete_eights // 8
|
|
body_eights_count = body_complete_eights % 8
|
|
|
|
# When start and end fall into the same cell, we ideally should render
|
|
# a symbol that's "center-aligned", but there is no good symbol in Unicode.
|
|
# In this case, we fall back to right-aligned block symbol for simplicity.
|
|
|
|
prefix = " " * prefix_bar_count
|
|
if prefix_eights_count:
|
|
prefix += BEGIN_BLOCK_ELEMENTS[prefix_eights_count]
|
|
|
|
body = FULL_BLOCK * body_bar_count
|
|
if body_eights_count:
|
|
body += END_BLOCK_ELEMENTS[body_eights_count]
|
|
|
|
suffix = " " * (width - len(body))
|
|
|
|
yield Segment(prefix + body[len(prefix) :] + suffix, self.style)
|
|
yield Segment.line()
|
|
|
|
def __rich_measure__(
|
|
self, console: Console, options: ConsoleOptions
|
|
) -> Measurement:
|
|
return (
|
|
Measurement(self.width, self.width)
|
|
if self.width is not None
|
|
else Measurement(4, options.max_width)
|
|
)
|