I'm using a Live
display to show the content of a Table
which grows over time. Eventually there is a vertical overflow and in that case I'd like the oldest (i.e. topmost) rows to vanish while the most recent rows should be shown together with the header, i.e. the content should be scrolled. The vertical_overflow
parameter of the live display provides a "visible"
option, but this makes the header of the table vanish. Obviously this is a Table
specific issue, since the header should stay but the content should be scrolled.
import time
from rich.live import Live
from rich.table import Table
table = Table()
table.add_column('Time')
table.add_column('Message')
with Live(table, refresh_per_second=5, vertical_overflow='visible'):
for i in range(100):
time.sleep(0.2)
table.add_row(time.asctime(), f'Event {i:03d}')
The left part shows the behavior with vertical_overflow='visible'
and the right part shows the desired behavior:
So far I'm using a workaround with a separate data structure to hold the rows and then creating the table from scratch every time a new row is to be added. This doesn't seem to be very efficient, so I'm wondering if there's a better solution. This workaround also fails for multi-line rows as it counts them as a single row (hence overflow will occur).
from collections import deque
import os
import time
from rich.live import Live
from rich.table import Table
def generate_table(rows):
table = Table()
table.add_column('Time')
table.add_column('Message')
for row in rows:
table.add_row(*row)
return table
width, height = os.get_terminal_size()
messages = deque(maxlen=height-4) # save space for header and footer
with Live(generate_table(messages), refresh_per_second=5) as live:
for i in range(100):
time.sleep(0.2)
messages.append((time.asctime(), f'Event {i:03d}'))
live.update(generate_table(messages))