Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Text objects pre-formatted with ANSI escapes miscalculate their width #1670

Closed
0xDEC0DE opened this issue Nov 9, 2021 · 5 comments
Closed

Comments

@0xDEC0DE
Copy link

0xDEC0DE commented Nov 9, 2021

When attempting to use "pre-formatted" strings from a third-party library with Rich tables, it seems to use the "whole width" of the string for header calculation rather than the "visible width"

Steps to reproduce

A simple test case, I'm using colored to illustrate:

from colored import bg, fg, attr

from rich.box import ASCII
from rich.console import Console
from rich.table import Table
from rich.text import Text

# simulate getting a "cooked" string from a library
text = bg(28) + fg(186) + 'this is test text' + attr(0)

table = Table(box=ASCII)
table.add_column('column')
table.add_row(Text(text))

Console().print(table)

Expected result

+-------------------+
| column            |
|-------------------|
| this is test text |
+-------------------+

Actual behavior

+-----------------------------------------+
| column                                  |
|-----------------------------------------|
| this is test text |
+-----------------------------------------+

Errata

I see class methods like Text.from_markup and Text.styled that would appear to be useful for creating Text objects from "cooked" inputs, but they don't appear to be made for this particular flavor. And attempting to adjust the Text._length property implicitly truncates the string.

Platform

╭───────────────────────── <class 'rich.console.Console'> ─────────────────────────╮
│ A high level console interface.                                                  │
│                                                                                  │
│ ╭──────────────────────────────────────────────────────────────────────────────╮ │
│ │ <console width=120 ColorSystem.TRUECOLOR>                                    │ │
│ ╰──────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                  │
│     color_system = 'truecolor'                                                   │
│         encoding = 'utf-8'                                                       │
│             file = <_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'> │
│           height = 77                                                            │
│    is_alt_screen = False                                                         │
│ is_dumb_terminal = False                                                         │
│   is_interactive = True                                                          │
│       is_jupyter = False                                                         │
│      is_terminal = True                                                          │
│   legacy_windows = False                                                         │
│         no_color = False                                                         │
│          options = ConsoleOptions(                                               │
│                        size=ConsoleDimensions(width=120, height=77),             │
│                        legacy_windows=False,                                     │
│                        min_width=1,                                              │
│                        max_width=120,                                            │
│                        is_terminal=True,                                         │
│                        encoding='utf-8',                                         │
│                        max_height=77,                                            │
│                        justify=None,                                             │
│                        overflow=None,                                            │
│                        no_wrap=False,                                            │
│                        highlight=None,                                           │
│                        markup=None,                                              │
│                        height=None                                               │
│                    )                                                             │
│            quiet = False                                                         │
│           record = False                                                         │
│         safe_box = True                                                          │
│             size = ConsoleDimensions(width=120, height=77)                       │
│        soft_wrap = False                                                         │
│           stderr = False                                                         │
│            style = None                                                          │
│         tab_size = 8                                                             │
│            width = 120                                                           │
╰──────────────────────────────────────────────────────────────────────────────────╯
platform="Darwin"
WindowsConsoleFeatures(vt=False, truecolor=False)
rich==10.13.0
@willmcgugan
Copy link
Collaborator

Rich will not process ANSI codes in strings by default, and they will confuse the length calculations. If you have strings with ANSI codes, you can use the ANSIDecoder class to convert them to Text instances.

https://github.com/willmcgugan/rich/blob/master/rich/ansi.py#L108

@github-actions
Copy link

Did I solve your problem?

Consider sponsoring the ongoing work on Rich and Textual.

Or buy me a coffee to say thanks.

Will McGugan

@0xDEC0DE
Copy link
Author

I mean, yes, this will do it, but the docs don't really mention it, and the code itself doesn't really hint in this direction, either. And I was looking.

I've humbly submitted a simple little helper method for guys like me in the future to use, should we find ourselves in similar situations.

@willmcgugan
Copy link
Collaborator

The ANSIDecoder is experimental, which is why it isn't documented.

It's not a common thing to do. Generally you wouldn't need to insert ansi codes in to tables, since Rich is more than capable of generating them anyway. Do you have use case?

I will look at your PR soon.

@0xDEC0DE
Copy link
Author

Our particular use-case is fraught with boring, irrelevant backstory, but I think it can be summed up as:

We are getting arbitrary text blobs from a third-party library, that already have ANSI formatting applied to them. We want to essentially "import" those blobs into Rich and continue styling them from there (well, WE just want to put those results into table cells and emit them, but others might want to do that other thing).

Running all of our inputs through AnsiDecoder to create our base Text objects works brilliantly as far as we can tell, so we're going to keep doing that. The PR is just attacking the same problem from the other direction, as it were.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants