From 260508bfa058d9d7e7f782482e91adf7ddf06342 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Tue, 14 Dec 2021 17:57:11 +0000 Subject: [PATCH] fix for overlapping markip --- CHANGELOG.md | 6 ++++++ pyproject.toml | 2 +- rich/text.py | 32 ++++++++------------------------ tests/test_segment.py | 30 +++++++++++++++++++++++++++++- 4 files changed, 44 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4218362e..ff135e76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [10.16.1] - Unreleased + +### Fixed + +- Fixed issues with overlaping tags https://github.com/willmcgugan/rich/issues/1755 + ## [10.16.0] - 2021-12-12 ### Fixed diff --git a/pyproject.toml b/pyproject.toml index 7e219d48..c26c6b1d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "rich" homepage = "https://github.com/willmcgugan/rich" documentation = "https://rich.readthedocs.io/en/latest/" -version = "10.16.0" +version = "10.16.1" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" authors = ["Will McGugan "] license = "MIT" diff --git a/rich/text.py b/rich/text.py index b277f6c1..43c089d6 100644 --- a/rich/text.py +++ b/rich/text.py @@ -1033,6 +1033,7 @@ class Text(JupyterMixin): Lines: New RichText instances between offsets. """ _offsets = list(offsets) + if not _offsets: return Lines([self.copy()]) @@ -1056,33 +1057,16 @@ class Text(JupyterMixin): ) if not self._spans: return new_lines - order = {span: span_index for span_index, span in enumerate(self._spans)} - span_stack = sorted(self._spans, key=attrgetter("start"), reverse=True) - pop = span_stack.pop - push = span_stack.append _Span = Span - get_order = order.__getitem__ - for line, (start, end) in zip(new_lines, line_ranges): - if not span_stack: - break - append_span = line._spans.append - position = len(span_stack) - 1 - while span_stack[position].start < end: - span = pop(position) - add_span, remaining_span = span.split(end) - if remaining_span: - push(remaining_span) - order[remaining_span] = order[span] - span_start, span_end, span_style = add_span - line_span = _Span(span_start - start, span_end - start, span_style) - order[line_span] = order[span] - append_span(line_span) - position -= 1 - if position < 0 or not span_stack: - break # pragma: no cover - line._spans.sort(key=get_order) + for line, (line_start, line_end) in zip(new_lines._lines, line_ranges): + for span_start, span_end, style in self._spans: + if span_end > line_start: + new_start = max(0, span_start - line_start) + new_end = min(span_end - line_start, line_end - line_start) + if new_end > new_start: + line._spans.append(_Span(new_start, new_end, style)) return new_lines diff --git a/tests/test_segment.py b/tests/test_segment.py index dcf7b218..9aff243a 100644 --- a/tests/test_segment.py +++ b/tests/test_segment.py @@ -1,4 +1,4 @@ -import sys +from io import StringIO import pytest @@ -166,6 +166,34 @@ def test_divide(): ] +# https://github.com/willmcgugan/rich/issues/1755 +def test_divide_complex(): + MAP = ( + "[on orange4] [on green]XX[on orange4] \n" + " \n" + " \n" + " \n" + " [bright_red on black]Y[on orange4] \n" + "[on green]X[on orange4] [on green]X[on orange4] \n" + " [on green]X[on orange4] [on green]X\n" + "[on orange4] \n" + " [on green]XX[on orange4] \n" + ) + from rich.text import Text + from rich.console import Console + + text = Text.from_markup(MAP) + console = Console( + color_system="truecolor", width=30, force_terminal=True, file=StringIO() + ) + console.print(text) + result = console.file.getvalue() + + print(repr(result)) + expected = "\x1b[48;5;94m \x1b[0m\x1b[42mXX\x1b[0m\x1b[48;5;94m \x1b[0m\n\x1b[48;5;94m \x1b[0m\n\x1b[48;5;94m \x1b[0m\n\x1b[48;5;94m \x1b[0m\n\x1b[48;5;94m \x1b[0m\x1b[91;40mY\x1b[0m\x1b[91;48;5;94m \x1b[0m\n\x1b[91;42mX\x1b[0m\x1b[91;48;5;94m \x1b[0m\x1b[91;42mX\x1b[0m\x1b[91;48;5;94m \x1b[0m\n\x1b[91;48;5;94m \x1b[0m\x1b[91;42mX\x1b[0m\x1b[91;48;5;94m \x1b[0m\x1b[91;42mX\x1b[0m\n\x1b[91;48;5;94m \x1b[0m\n\x1b[91;48;5;94m \x1b[0m\x1b[91;42mXX\x1b[0m\x1b[91;48;5;94m \x1b[0m\n\n" + assert result == expected + + def test_divide_emoji(): bold = Style(bold=True) italic = Style(italic=True)