ratatui icon indicating copy to clipboard operation
ratatui copied to clipboard

Support reversed display order for Paragraph

Open matheus-git opened this issue 1 year ago • 2 comments

Problem

I'm currently building a application that displays logs in real time (similar to journalctl). But I can't replicate the characteristic behavior of having the most recent line at the bottom.

Solution

Instead of scroll = 0 referring to the first line, it should point to the last one.

Alternatives

It's true that I can calculate the height of the area, apply wrapping and manage the scroll to replicate the desired behavior. But it would be better if the library provided this feature.

matheus-git avatar Apr 18 '25 21:04 matheus-git

I think we need to think about the design of this a bit before implementation. Do you have an idea on how the API would look like for this feature? (Is this similar to ListDirection?)

orhun avatar Apr 21 '25 19:04 orhun

Yes, exactly like the ListDirection. If scroll == 0, it would point to the last line of text, and the text would already display the last line in the last row of the buffer. When scroll += 1, the scroll would move up, shifting the text upward and displaying the upper lines.

matheus-git avatar Apr 21 '25 20:04 matheus-git

I'm not sure that rendering paragraphs from bottom to top makes much sense for general users of Ratatui, so I'm tending towards closing this request as not planned, but I wanted to make sure I clarified this a bit before doing so.

Your specific use here is obviously valid. You want to display log messages appending them so that the scroll position follows the last item if you're at the bottom of the items, but it seems to me like this is less about rendering a paragraph (which is a single coherent blob of text) and more about rendering a sequence of lines of information.

I'm guessing that the actual part of this that pushes you towards using the Paragraph widget over using a List widget is that the Paragraph supports wrapping while the List does not. If I was implementing this, I'd probably do something like:

  • store the lines in a Vec<String>
  • wrap each line prior to render using the textwrap crate (cache the wrapped values between frames and invalidate if the width changes)
  • use the List widget to render the pre-wrapped lines

Going one step further though, I'd be inclined to pre-filter the items to just the visible ones based on keeping an offset. For large log counts this will significantly avoid having to re-wrap the entire contents.

Does that seem like it solves your problem well enough to not want this feature?

joshka avatar May 29 '25 18:05 joshka

If the understanding is that the feature doesn't make sense for most ratatui users, then it's better not to implement it. I'll try this approach you mentioned in the next few weeks. Thanks.

matheus-git avatar May 30 '25 13:05 matheus-git

Cool, I'll close this out for now. Feel free to reopen if needed.

joshka avatar May 30 '25 20:05 joshka

I noticed that the List widget has a behavior similar to what this issue aims for — the ListDirection. My idea was to have something like that for Paragraph. Anyway, I solved the problem based on the solution you proposed: I apply an offset to the log to display it according to the area size, and there's a scroll that changes the start point of the slice. Thanks. My Ratatui application is basically ready.

matheus-git avatar Jun 01 '25 16:06 matheus-git