rich
rich copied to clipboard
[BUG] table column no_wrap can squash columns below their min_width
- [X] I've checked docs and closed issues for possible solutions.
- [X] I can't find my issue in the FAQ.
Describe the bug
I'll start with: the bug may be with my understanding of options, so I'm prepared to accept that I'm thinking about things wrong. That said, I feel pretty confident that my thinking is not incoherent. ๐
In a tableย column, the no_wrap option does not function as I would expect. My expectation is that the content of a column would not be allowed to wrap, and that the overflow property would apply. Further, that with no specification of the column's width, its width would be determined by finding the total available table width, meeting the width requirements of other columns (and borders) and then using the remaining space.
Instead, a no_wrap column is forcingย other table column contents to be squashed below their minimum width. Consider this program:
from rich import print
from rich.table import Table
from rich.text import Text
table = Table(show_header=True, header_style="bold magenta")
table.add_column("Issue", min_width=7, width=7)
table.add_column("S", min_width=1, width=1)
table.add_column("Pri", min_width=3, width=3)
table.add_column("Title", overflow="ellipsis")
too_long = """\
This is a full line sentence and it fills a whole line so it overflows a cell!\
"""
for i in range(2):
table.add_row("ABC-123", "X", "123", " ".join([too_long, too_long]))
print(table)
This prints the following table on my 80 column terminal (iTerm2):

If I update the program to use no_wrap:
from rich import print
from rich.table import Table
from rich.text import Text
table = Table(show_header=True, header_style="bold magenta")
table.add_column("Issue", min_width=7, width=7)
table.add_column("S", min_width=1, width=1)
table.add_column("Pri", min_width=3, width=3)
table.add_column("Title", overflow="ellipsis", no_wrap=True)
too_long = """\
This is a full line sentence and it fills a whole line so it overflows a cell!\
"""
for i in range(2):
table.add_row("ABC-123", "X", "123", " ".join([too_long, too_long]))
print(table)
...then the table produced squashes the first three columns below their minimum before applying the ellipsis overflow behavior.

I think instead, the left columns should be displayed at their specified widths, and the rightmost column truncated earlier.
Platform
Click to expand
What platform (Win/Linux/Mac) are you running on? What terminal software are you using?
I'm running on macOS Venture:
Darwin snowdrop 22.3.0 Darwin Kernel Version 22.3.0: Mon Jan 30 20:38:43 PST 2023; root:xnu-8792.81.3~2/RELEASE_ARM64_T8112 arm64
I'm using iTerm2 v3.4.19.
rich.diagnose
โญโโโโโโโโโโโโโโโโโโโโโโโ <class 'rich.console.Console'> โโโโโโโโโโโโโโโโโโโโโโโโฎ
โ A high level console interface. โ
โ โ
โ โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ โ
โ โ <console width=80 ColorSystem.TRUECOLOR> โ โ
โ โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ โ
โ โ
โ color_system = 'truecolor' โ
โ encoding = 'utf-8' โ
โ file = <_io.TextIOWrapper name='<stdout>' mode='w' โ
โ encoding='utf-8'> โ
โ height = 33 โ
โ 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=80, height=33), โ
โ legacy_windows=False, โ
โ min_width=1, โ
โ max_width=80, โ
โ is_terminal=True, โ
โ encoding='utf-8', โ
โ max_height=33, โ
โ justify=None, โ
โ overflow=None, โ
โ no_wrap=False, โ
โ highlight=None, โ
โ markup=None, โ
โ height=None โ
โ ) โ
โ quiet = False โ
โ record = False โ
โ safe_box = True โ
โ size = ConsoleDimensions(width=80, height=33) โ
โ soft_wrap = False โ
โ stderr = False โ
โ style = None โ
โ tab_size = 8 โ
โ width = 80 โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
โญโโโ <class 'rich._windows.WindowsConsoleFeatures'> โโโโโฎ
โ Windows features available. โ
โ โ
โ โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ โ
โ โ WindowsConsoleFeatures(vt=False, truecolor=False) โ โ
โ โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ โ
โ โ
โ truecolor = False โ
โ vt = False โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
โญโโโโโโ Environment Variables โโโโโโโโฎ
โ { โ
โ 'TERM': 'xterm-256color', โ
โ 'COLORTERM': 'truecolor', โ
โ 'CLICOLOR': None, โ
โ 'NO_COLOR': None, โ
โ 'TERM_PROGRAM': 'iTerm.app', โ
โ 'COLUMNS': None, โ
โ 'LINES': None, โ
โ 'JUPYTER_COLUMNS': None, โ
โ 'JUPYTER_LINES': None, โ
โ 'JPY_PARENT_PID': None, โ
โ 'VSCODE_VERBOSE_LOGGING': None โ
โ } โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
platform="Darwin"
pip freeze | grep rich
``` snowdrop:~/fm/code/glinpy$ pip freeze | grep rich rich==13.3.2 ```
Thank you for your issue. Give us a little time to review it.
PS. You might want to check the FAQ if you haven't done so already.
This is an automated reply, generated by FAQtory
You have given Rich an impossible to satisfy set of restraints. The first three columns are fixed, and the last isn't permitted to wrap. There is no way to shrink that without breaking at least one constraint, so it defaults to a "last resort" algorithm to compress the table.
A workaround would be to remove the constraints from the columns and prevent the cell from wrapping.
from rich import print
from rich.table import Table
from rich.text import Text
table = Table(show_header=True, header_style="bold magenta", expand=True)
table.add_column("Issue")
table.add_column("S")
table.add_column("Pri")
table.add_column("Title")
too_long = """\
This is a full line sentence and it fills a whole line so it overflows a cell!\
"""
for i in range(2):
table.add_row(
"ABC-123",
"X",
"123",
Text(" ".join([too_long, too_long]), no_wrap=True),
)
print(table)
Thanks, @willmcgugan, that does get me the behavior that I wanted. I really appreciate it.
I'd like to ask a follow-up question, if I may. You said, "You have given Rich an impossible to satisfy set of restraints." and I reckon you're right! But I would've thought the model worked differently, and I think I'll do better moving forward if I understand it more. Maybe you can speak the three words that will enlighten me, or just point me at something for me to read over and over until it clicks. :)
You wrote:
The first three columns are fixed, and the last isn't permitted to wrap. There is no way to shrink that without breaking at least one constraint, so it defaults to a "last resort" algorithm to compress the table.
I would have thought that it would be able to be satisfied like so:
- the table is contained only by the terminal, so its maximum width is bounded by the terminal width
- there are 4 columns, three with fixed size
- the last column may not wrap, so its maximum size is perforce (table width - border&c width - first three columns)
- let's say that's 50; the text in the final cell would then be told to render in 50 columns, with both overflow and no-wrap
- ...so I would expect that the (implicitly created) text element with the long sentence would be given rendering instructions equivalent to the cell construction that does work
I suspect that my misunderstanding is related to the way in which the no_wrap/overflow of the column are communicated to, or share dependency ordering with, the renderable in each row of the column, but I'm afraid I don't understand my own understanding.
If you can clear it up, I would be grateful. If not, well, I'm already grateful for the above. Thanks!
I struggled with this exact problem for a long time, and @willmcgugan solution also worked perfectly for me.
To be honest, I'm not sure I understand the difference between a column not being allowed to wrap vs a cell not being able to wrap...