charmbracelet / charmbracelet/bubbles
Stream content to a viewport
- Dominant language
- Go
- Stars
- 8.9k
- Forks
- 457
- Avg merge
- 1d 18h
- Merged PRs (30d)
- 5
Description
Hi,
Let's say I'm running some kind of external software and I want to display the logs of it during its lifetime in a viewport.
How can I do this ? As far as I understand, the viewport can only be updated through the SetContent method.
Ideally, the viewport should update every new line but I don't want to do some weird things if I missed something
Minimal code:
-> /tmp/some-software.sh
```bash
while true; do echo Hey; sleep 1; done
```
```go
package main
import (
"bufio"
"bytes"
"fmt"
"io"
"os"
"os/exec"
"github.com/charmbracelet/bubbles/viewport"
tea "github.com/charmbracelet/bubbletea"
)
type CmdMsg struct {
path string
}
type Model struct {
logs io.Writer
ready bool
viewport viewport.Model
}
func (x Model) Init() tea.Cmd {
return func() tea.Msg {
return CmdMsg{path: "/tmp/some-software.sh"}
}
}
func (x Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
if k := msg.String(); k == "ctrl+c" || k == "q" || k == "esc" {
return x, tea.Quit
}
case CmdMsg:
cmd := exec.Command("/usr/bin/bash", msg.path)
var logs bytes.Buffer
logsWriter := bufio.NewWriter(&logs)
cmd.Stdout = logsWriter
cmd.Stderr = logsWriter
x.logs = logsWriter
// ???
cmd.Start()
case tea.WindowSizeMsg:
if !x.ready {
x.viewport = viewport.New(msg.Width, msg.Height-10)
x.viewport.YPosition = 5
x.viewport.HighPerformanceRendering = false
x.viewport.SetContent( /* ???? */ )
x.ready = true
} else {
x.viewport.Width = msg.Width
x.viewport.Height = msg.Height - 10
}
}
return x, nil
}
func (x Model) View() string {
return x.viewport.View()
}
func main() {
p := tea.NewProgram(
Model{},
tea.WithAltScreen(),
)
if _, err := p.Run(); err != nil {
fmt.Println("could not run program:", err)
os.Exit(1)
}
}
```
Thanks!
Contributor guide
Assessment
This issue has not been assessed yet.