diff --git a/src/textual/renderables/opacity.py b/src/textual/renderables/opacity.py index a81f045ce..f6cd42986 100644 --- a/src/textual/renderables/opacity.py +++ b/src/textual/renderables/opacity.py @@ -1,13 +1,9 @@ import functools -from time import sleep from rich.color import Color from rich.console import ConsoleOptions, Console, RenderResult, RenderableType -from rich.live import Live -from rich.panel import Panel from rich.segment import Segment from rich.style import Style -from rich.text import Text from textual.renderables.utilities import blend_colors @@ -27,26 +23,24 @@ class Opacity: def __rich_console__( self, console: Console, options: ConsoleOptions ) -> RenderResult: - lines = console.render_lines(self.renderable, options) + segments = console.render(self.renderable, options) opacity = self.value - for line in lines: - for segment in line: - style = segment.style - if not style: - yield segment - continue - fg, bg = style.color, style.bgcolor - if fg and fg.triplet and bg and bg.triplet: - yield Segment( - text=segment.text, - style=_get_blended_style_cached( - fg_color=fg, bg_color=bg, opacity=opacity - ), - control=segment.control, - ) - else: - yield segment - yield "" + for segment in segments: + style = segment.style + if not style: + yield segment + continue + fg, bg = style.color, style.bgcolor + if fg and fg.triplet and bg and bg.triplet: + yield Segment( + text=segment.text, + style=_get_blended_style_cached( + fg_color=fg, bg_color=bg, opacity=opacity + ), + control=segment.control, + ) + else: + yield segment @functools.lru_cache(maxsize=1024) @@ -60,6 +54,12 @@ def _get_blended_style_cached( if __name__ == "__main__": + from rich.live import Live + from rich.panel import Panel + from rich.text import Text + + from time import sleep + console = Console() panel = Panel.fit( diff --git a/tests/renderables/test_opacity.py b/tests/renderables/test_opacity.py index 67dbd896d..8dbd69408 100644 --- a/tests/renderables/test_opacity.py +++ b/tests/renderables/test_opacity.py @@ -4,28 +4,47 @@ from rich.text import Text from tests.utilities.render import render from textual.renderables.opacity import Opacity - -@pytest.mark.skip -def test_simple_opacity(): - text = Text("Hello, world!", style="#ff0000 on #00ff00") - assert render(Opacity(text, value=.5)) == "" +STOP = "\x1b[0m" -@pytest.mark.skip -def test_ansi_colors_ignored(): - pass +@pytest.fixture +def text(): + return Text("Hello, world!", style="#ff0000 on #00ff00", end="") -@pytest.mark.skip -def test_opacity_no_style(): - pass +def test_simple_opacity(text): + blended_red_on_green = "\x1b[38;2;127;127;0;48;2;0;255;0m" + assert render(Opacity(text, value=.5)) == ( + f"{blended_red_on_green}Hello, world!{STOP}" + ) -@pytest.mark.skip -def test_opacity_only_fg(): - pass +def test_value_zero_sets_foreground_color_to_background_color(text): + foreground = background = "0;255;0" + assert render(Opacity(text, value=0)) == ( + f"\x1b[38;2;{foreground};48;2;{background}mHello, world!{STOP}" + ) -@pytest.mark.skip -def test_opacity_only_bg(): - pass +def test_opacity_value_of_one_noop(text): + assert render(Opacity(text, value=1)) == render(text) + + +def test_ansi_colors_noop(): + ansi_colored_text = Text("Hello, world!", style="red on green", end="") + assert render(Opacity(ansi_colored_text, value=.5)) == render(ansi_colored_text) + + +def test_opacity_no_style_noop(): + text_no_style = Text("Hello, world!", end="") + assert render(Opacity(text_no_style, value=.2)) == render(text_no_style) + + +def test_opacity_only_fg_noop(): + text_only_fg = Text("Hello, world!", style="#ff0000", end="") + assert render(Opacity(text_only_fg, value=.5)) == render(text_only_fg) + + +def test_opacity_only_bg_noop(): + text_only_bg = Text("Hello, world!", style="on #ff0000", end="") + assert render(Opacity(text_only_bg, value=.5)) == render(text_only_bg) diff --git a/tests/utilities/render.py b/tests/utilities/render.py index a2435c542..2a951f1f0 100644 --- a/tests/utilities/render.py +++ b/tests/utilities/render.py @@ -19,6 +19,7 @@ def render(renderable: RenderableType, no_wrap: bool = False) -> str: console = Console( width=100, file=io.StringIO(), color_system="truecolor", legacy_windows=False ) - console.print(renderable, no_wrap=no_wrap) - output = replace_link_ids(console.file.getvalue()) + with console.capture() as capture: + console.print(renderable, no_wrap=no_wrap, end="") + output = replace_link_ids(capture.get()) return output