Fix hang when Rule title greater than required space

This commit is contained in:
Darren Burns 2022-06-15 14:49:15 +01:00
parent d9a0d47946
commit dbb27d30a7
No known key found for this signature in database
GPG key ID: B0939B45037DC345
4 changed files with 67 additions and 16 deletions

View file

@ -80,7 +80,7 @@ def set_cell_size(text: str, total: int) -> str:
return text + " " * (total - size)
return text[:total]
if not total:
if total <= 0:
return ""
cell_size = cell_len(text)
if cell_size == total:

View file

@ -63,10 +63,7 @@ class Rule(JupyterMixin):
chars_len = cell_len(characters)
if not self.title:
rule_text = Text(characters * ((width // chars_len) + 1), self.style)
rule_text.truncate(width)
rule_text.plain = set_cell_size(rule_text.plain, width)
yield rule_text
yield self._rule_line(chars_len, width)
return
if isinstance(self.title, Text):
@ -76,10 +73,16 @@ class Rule(JupyterMixin):
title_text.plain = title_text.plain.replace("\n", " ")
title_text.expand_tabs()
rule_text = Text(end=self.end)
required_space = 4 if self.align == "center" else 2
truncate_width = max(0, width - required_space)
if not truncate_width:
yield self._rule_line(chars_len, width)
return
rule_text = Text(end=self.end)
if self.align == "center":
title_text.truncate(width - 4, overflow="ellipsis")
title_text.truncate(truncate_width, overflow="ellipsis")
side_width = (width - cell_len(title_text.plain)) // 2
left = Text(characters * (side_width // chars_len + 1))
left.truncate(side_width - 1)
@ -90,12 +93,12 @@ class Rule(JupyterMixin):
rule_text.append(title_text)
rule_text.append(" " + right.plain, self.style)
elif self.align == "left":
title_text.truncate(width - 2, overflow="ellipsis")
title_text.truncate(truncate_width, overflow="ellipsis")
rule_text.append(title_text)
rule_text.append(" ")
rule_text.append(characters * (width - rule_text.cell_len), self.style)
elif self.align == "right":
title_text.truncate(width - 2, overflow="ellipsis")
title_text.truncate(truncate_width, overflow="ellipsis")
rule_text.append(characters * (width - title_text.cell_len - 1), self.style)
rule_text.append(" ")
rule_text.append(title_text)
@ -103,6 +106,12 @@ class Rule(JupyterMixin):
rule_text.plain = set_cell_size(rule_text.plain, width)
yield rule_text
def _rule_line(self, chars_len: int, width: int) -> Text:
rule_text = Text(self.characters * ((width // chars_len) + 1), self.style)
rule_text.truncate(width)
rule_text.plain = set_cell_size(rule_text.plain, width)
return rule_text
def __rich_measure__(
self, console: Console, options: ConsoleOptions
) -> Measurement:
@ -110,12 +119,16 @@ class Rule(JupyterMixin):
if __name__ == "__main__": # pragma: no cover
from rich.console import Console
import sys
from rich.console import Console
try:
text = sys.argv[1]
except IndexError:
text = "Hello, World"
console = Console()
console.print(Rule(title=text))
console = Console()
console.print(Rule("foo"), width=4)

View file

@ -61,6 +61,47 @@ def test_rule_cjk():
assert console.file.getvalue() == expected
@pytest.mark.parametrize(
"align,outcome",
[
("center", "───\n"),
("left", "… ─\n"),
("right", "─ …\n"),
],
)
def test_rule_not_enough_space_for_title_text(align, outcome):
console = Console(width=3, file=io.StringIO(), record=True)
console.rule("Hello!", align=align)
assert console.file.getvalue() == outcome
def test_rule_center_aligned_title_not_enough_space_for_rule():
console = Console(width=4, file=io.StringIO(), record=True)
console.rule("ABCD")
assert console.file.getvalue() == "────\n"
@pytest.mark.parametrize("align", ["left", "right"])
def test_rule_side_aligned_not_enough_space_for_rule(align):
console = Console(width=2, file=io.StringIO(), record=True)
console.rule("ABCD", align=align)
assert console.file.getvalue() == "──\n"
@pytest.mark.parametrize(
"align,outcome",
[
("center", "─ … ─\n"),
("left", "AB… ─\n"),
("right", "─ AB…\n"),
],
)
def test_rule_just_enough_width_available_for_title(align, outcome):
console = Console(width=5, file=io.StringIO(), record=True)
console.rule("ABCD", align=align)
assert console.file.getvalue() == outcome
def test_characters():
console = Console(
width=16,

View file

@ -34,7 +34,6 @@ def test_spinner_render():
assert result == expected
@pytest.mark.skip(reason="Broken with Rule.__rich__measure in place")
def test_spinner_update():
time = 0.0
@ -47,17 +46,15 @@ def test_spinner_update():
spinner = Spinner("dots")
console.print(spinner)
spinner.update(text="Bar", style="green", speed=2)
time += 80 / 1000
console.print(spinner)
rule = Rule("Bar")
spinner.update(text=Rule("Bar"))
spinner.update(text=rule)
time += 80 / 1000
console.print(spinner)
result = console.end_capture()
print(repr(result))
expected = f"\n\x1b[32m⠙\x1b[0m Bar\n\x1b[32m⠸\x1b[0m \x1b[92m────── \x1b[0mBar\x1b[92m ──────\x1b[0m\n"
expected = "\n\x1b[92m\x1b[0m\n"
assert result == expected