diff --git a/rich/ansi.py b/rich/ansi.py index 7bbcb0bfc..db51c0f00 100644 --- a/rich/ansi.py +++ b/rich/ansi.py @@ -132,6 +132,7 @@ def decode(self, terminal_text: str) -> Iterable[Text]: Yields: Text: Marked up Text. """ + terminal_text = terminal_text.replace("\r\n", "\n") for line in re.split(r"(?<=\n)", terminal_text): yield self.decode_line(line.rstrip("\n")) diff --git a/tests/test_ansi.py b/tests/test_ansi.py index 21e20b440..56c9d9968 100644 --- a/tests/test_ansi.py +++ b/tests/test_ansi.py @@ -102,3 +102,16 @@ def test_decode_newlines(): assert Text.from_ansi("Hello\nWorld\n").plain == "Hello\nWorld\n" assert Text.from_ansi("Hello\nWorld\n\n").plain == "Hello\nWorld\n\n" assert Text.from_ansi("\nHello\nWorld\n\n").plain == "\nHello\nWorld\n\n" + + +def test_decode_crlf(): + """Test CRLF line endings are handled correctly. + Regression test for https://github.com/Textualize/rich/issues/4090 + """ + assert Text.from_ansi("Hello\r\nWorld\r\n").plain == "Hello\nWorld\n" + assert Text.from_ansi("Hello\r\n").plain == "Hello\n" + assert Text.from_ansi("\r\nHello\r\n").plain == "\nHello\n" + assert Text.from_ansi("Hello\r\n\r\nWorld").plain == "Hello\n\nWorld" + # Mixed line endings + assert Text.from_ansi("Hello\nWorld\r\n").plain == "Hello\nWorld\n" + assert Text.from_ansi("Hello\r\nWorld\n").plain == "Hello\nWorld\n"