Skip to content

Commit a6d1d78

Browse files
authored
Merge pull request #1706 from 0xDEC0DE/issue/1670
Add a Text.from_ansi helper method
2 parents d6e6a76 + 62ead7e commit a6d1d78

File tree

5 files changed

+53
-0
lines changed

5 files changed

+53
-0
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4040
- Allowed `__rich__` to work recursively
4141
- Allowed Text classes to work with sep in print https://github.com/willmcgugan/rich/issues/1689
4242

43+
### Added
44+
45+
- Added a `rich.text.Text.from_ansi` helper method for handling pre-formatted input strings https://github.com/willmcgugan/rich/issues/1670
46+
4347
## [10.13.0] - 2021-11-07
4448

4549
### Added

CONTRIBUTORS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ The following people have contributed to the development of Rich:
2323
- [Clément Robert](https://github.com/neutrinoceros)
2424
- [Tushar Sadhwani](https://github.com/tusharsadhwani)
2525
- [Tim Savage](https://github.com/timsavage)
26+
- [Nicolas Simonds](https://github.com/0xDEC0DE)
2627
- [Gabriele N. Tornetta](https://github.com/p403n1x87)

docs/source/text.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ Alternatively, you can construct styled text by calling :meth:`~rich.text.Text.a
2626
text.append(" World!")
2727
console.print(text)
2828

29+
If you would like to use text that is already formatted with ANSI codes, call :meth:`~rich.text.Text.from_ansi` to convert it to a ``Text`` object:
30+
31+
text = Text.from_ansi("\033[1mHello, World!\033[0m")
32+
console.print(text.spans)
33+
2934
Since building Text instances from parts is a common requirement, Rich offers :meth:`~rich.text.Text.assemble` which will combine strings or pairs of string and Style, and return a Text instance. The follow example is equivalent to the code above::
3035

3136
text = Text.assemble(("Hello", "bold magenta"), " World!")

rich/text.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,40 @@ def from_markup(
242242
rendered_text.overflow = overflow
243243
return rendered_text
244244

245+
@classmethod
246+
def from_ansi(
247+
cls,
248+
text: str,
249+
*,
250+
style: Union[str, Style] = "",
251+
justify: Optional["JustifyMethod"] = None,
252+
overflow: Optional["OverflowMethod"] = None,
253+
no_wrap: Optional[bool] = None,
254+
end: str = "\n",
255+
tab_size: Optional[int] = 8,
256+
) -> "Text":
257+
"""Create a Text object from pre-formatted ANSI.
258+
259+
Args:
260+
text (str): A string containing ANSI color codes.
261+
style (Union[str, Style], optional): Base style for text. Defaults to "".
262+
justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None.
263+
overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None.
264+
no_wrap (bool, optional): Disable text wrapping, or None for default. Defaults to None.
265+
end (str, optional): Character to end text with. Defaults to "\\\\n".
266+
tab_size (int): Number of spaces per tab, or ``None`` to use ``console.tab_size``. Defaults to 8.
267+
"""
268+
from .ansi import AnsiDecoder
269+
270+
decoded_text = AnsiDecoder().decode_line(text)
271+
decoded_text.justify = justify
272+
decoded_text.overflow = overflow
273+
decoded_text.no_wrap = no_wrap
274+
decoded_text.end = end
275+
decoded_text.tab_size = tab_size
276+
decoded_text.stylize(style)
277+
return decoded_text
278+
245279
@classmethod
246280
def styled(
247281
cls,

tests/test_text.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,15 @@ def test_from_markup():
9595
assert text._spans == [Span(7, 13, "bold")]
9696

9797

98+
def test_from_ansi():
99+
text = Text.from_ansi("Hello, \033[1mWorld!\033[0m")
100+
text2 = Text.from_ansi("Hello, \033[1mWorld!\033[0m", style="red")
101+
assert str(text) == "Hello, World!"
102+
assert text._spans == [Span(7, 13, Style(bold=True))]
103+
assert str(text2) == "Hello, World!"
104+
assert text2._spans == [Span(7, 13, Style(bold=True)), Span(0, 13, "red")]
105+
106+
98107
def test_copy():
99108
test = Text()
100109
test.append("Hello", "bold")

0 commit comments

Comments
 (0)