rivo / tview

Terminal UI library with rich, interactive widgets — written in Golang
MIT License
10.93k stars 569 forks source link

Long text in TextView #895

Closed marek-kuticka closed 6 months ago

marek-kuticka commented 1 year ago

Hi

what would be the best option to implement TextView component, inside some Flex container, or whatever, that contains scrollable text and I can keep focus at the end? something in sense of console logger.

I have bit struggles to getting this to work. would there be any example of this?

thx a lot

Marek

rivo commented 1 year ago

You can call TextView.ScrollToEnd():

ScrollToEnd scrolls to the bottom left corner of the text if the text view is scrollable. Adding new rows to the end of the text view will cause it to scroll with the new data.

You can use TextView as a io.Writer and simply write your text to it (use SetChangedFunc() to redraw the text view). Make sure to also read the section on large texts.

marek-kuticka commented 1 year ago

thx, my question was rather aimed to adding text itself. what method is most suitable, and if TextView then handles the scroll by itself.

thx

digitallyserviced commented 1 year ago

@marek-kuticka

thx, my question was rather aimed to adding text itself. what method is most suitable, and if TextView then handles the scroll by itself.

thx

No TextView will NOT automatically scroll when new content is written or appended.

However, you can control this behavior yourself using the callback functions and the ScrollToEnd()

https://github.com/hofstadter-io/hof/blob/ce99f98a3db35047fe413c2aff4b07f35b287181/lib/tui/hoc/console/err.go#L17-L25

func NewErrConsoleWidget() *ErrConsoleWidget {
    textView := tview.NewTextView()
    textView.
        SetTextColor(tcell.ColorMaroon).
        SetScrollable(true).
        SetChangedFunc(func() {
            textView.ScrollToEnd()
        })
}
rivo commented 1 year ago

No TextView will NOT automatically scroll when new content is written or appended.

Not true. TextView behaves exactly how it's described in the comment I quoted above. It will automatically scroll. It is not necessary to call ScrollToEnd() every time something is changed, like in the example @digitallyserviced posted. Once is enough.

@marek-kuticka Check out the following example which is how you could implement a continuous text stream (but again, please also look at the section about "Large Texts"):

func main() {
    app := tview.NewApplication()

    textView := tview.NewTextView().
        ScrollToEnd().
        SetChangedFunc(func() {
            app.Draw()
        })

    go func() {
        var i int
        for {
            fmt.Fprintf(textView, "%d\n", i)
            time.Sleep(10 * time.Millisecond)
            i++
        }
    }()

    if err := app.SetRoot(textView, true).Run(); err != nil {
        panic(err)
    }
}
digitallyserviced commented 1 year ago

No TextView will NOT automatically scroll when new content is written or appended.

Not true. TextView behaves exactly how it's described in the comment I quoted above. It will automatically scroll. It is not necessary to call ScrollToEnd() every time something is changed, like in the example @digitallyserviced posted. Once is enough.

lol Not not true... @rivo is correct about this happenning automatically on the initial call. Please note @marek-kuticka that his answer and example isn't making it obvious that whether SetScrollable is enabled since the behavior is different dependent on this. Also note that while this seems innocent enough to only handle scrolling. Content that is offcreen when SetScrollable is false is wiped from the TextView

:grinning:

What I think should be addressed in this answer is actually the use of SetScrollable.

Peek 2023-10-04 20-06