Skip to content

Commit

Permalink
Merge pull request #1756 from willmcgugan/overlap-markup
Browse files Browse the repository at this point in the history
fix for overlapping markup
  • Loading branch information
willmcgugan committed Dec 15, 2021
2 parents c57e1f5 + a4c9fdb commit 1442dd7
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 28 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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] - 2021-12-15

### Fixed

- Fixed issues with overlapping tags https://github.com/willmcgugan/rich/issues/1755

## [10.16.0] - 2021-12-12

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 <willmcgugan@gmail.com>"]
license = "MIT"
Expand Down
66 changes: 40 additions & 26 deletions rich/text.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import re
from functools import partial, reduce
from math import gcd
from operator import attrgetter, itemgetter
from operator import itemgetter
from rich.emoji import EmojiVariant
from typing import (
TYPE_CHECKING,
Expand Down Expand Up @@ -1033,6 +1033,7 @@ def divide(self, offsets: Iterable[int]) -> Lines:
Lines: New RichText instances between offsets.
"""
_offsets = list(offsets)

if not _offsets:
return Lines([self.copy()])

Expand All @@ -1056,33 +1057,46 @@ def divide(self, offsets: Iterable[int]) -> Lines:
)
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
_line_appends = [line._spans.append for line in new_lines._lines]
line_count = len(line_ranges)
_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 span_start, span_end, style in self._spans:

lower_bound = 0
upper_bound = line_count
start_line_no = (lower_bound + upper_bound) // 2

while True:
line_start, line_end = line_ranges[start_line_no]
if span_start < line_start:
upper_bound = start_line_no - 1
elif span_start > line_end:
lower_bound = start_line_no + 1
else:
break
start_line_no = (lower_bound + upper_bound) // 2

end_line_no = lower_bound = start_line_no
upper_bound = line_count

while True:
line_start, line_end = line_ranges[end_line_no]
if span_end < line_start:
upper_bound = end_line_no - 1
elif span_end > line_end:
lower_bound = end_line_no + 1
else:
break
end_line_no = (lower_bound + upper_bound) // 2

for line_no in range(start_line_no, end_line_no + 1):
line_start, line_end = line_ranges[line_no]
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_appends[line_no](_Span(new_start, new_end, style))

return new_lines

Expand Down
30 changes: 29 additions & 1 deletion tests/test_segment.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import sys
from io import StringIO

import pytest

Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 1442dd7

Please sign in to comment.