charmbracelet / charmbracelet/bubbletea

The visible area in viewport may seem incorrect when content exceed the viewport.Width

Open
#1,017 10 comments 1 reaction 0 assignees View on GitHub
Dominant language
Go
Stars
44.9k
Forks
1.3k
PR merge metrics
No merged PRs in 30d

Description

**Describe the bug**

When I am using a viewport (fixed width and height) and set content with a very long text, the visible area may be incorrect because of multilines.
The viewport.GotoBottom() seems ineffective.

**Setup**

- OS: macOS
- Shell: zsh
- Terminal Emulator: none
- Terminal Multiplexer: none

**To Reproduce**

1. go run main.go
2. setting the viewarea ```viewport.New(30, 5)```
3. sending very long text longer than the viewport area, it will cause changing into a new line when hit the end.
4. sending long text utill the viewport area is full
5. See error

**Source Code**

Using the example ```https://github.com/charmbracelet/bubbletea/blob/master/examples/chat/main.go```

```go
package main

// A simple program demonstrating the text area component from the Bubbles
// component library.

import (
"fmt"
"log"
"strings"

"github.com/charmbracelet/bubbles/textarea"
"github.com/charmbracelet/bubbles/viewport"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)

func main() {
p := tea.NewProgram(initialModel())

if _, err := p.Run(); err != nil {
log.Fatal(err)
}
}

type (
errMsg error
)

type model struct {
viewport viewport.Model
messages []string
textarea textarea.Model
senderStyle lipgloss.Style
err error
}

func initialModel() model {
ta := textarea.New()
ta.Placeholder = "Send a message..."
ta.Focus()

ta.Prompt = "┃ "
ta.CharLimit = 280

ta.SetWidth(30)
ta.SetHeight(3)

// Remove cursor line styling
ta.FocusedStyle.CursorLine = lipgloss.NewStyle()

ta.ShowLineNumbers = false

vp := viewport.New(30, 5)
vp.SetContent(`Welcome to the chat room!
Type a message and press Enter to send.`)

ta.KeyMap.InsertNewline.SetEnabled(false)

return model{
textarea: ta,
messages: []string{},
viewport: vp,
senderStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("5")),
err: nil,
}
}

func (m model) Init() tea.Cmd {
return textarea.Blink
}

func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var (
tiCmd tea.Cmd
vpCmd tea.Cmd
)

m.textarea, tiCmd = m.textarea.Update(msg)
m.viewport, vpCmd = m.viewport.Update(msg)

switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.Type {
case tea.KeyCtrlC, tea.KeyEsc:
fmt.Println(m.textarea.Value())
return m, tea.Quit
case tea.KeyEnter:
m.messages = append(m.messages, m.senderStyle.Render("You: ")+m.textarea.Value())
m.viewport.SetContent(strings.Join(m.messages, "\n"))
m.textarea.Reset()
m.viewport.GotoBottom()
}

// We handle errors just like any other message
case errMsg:
m.err = msg
return m, nil
}

return m, tea.Batch(tiCmd, vpCmd)
}

func (m model) View() string {
return fmt.Sprintf(
"%s\n\n%s",
m.viewport.View(),
m.textarea.View(),
) + "\n\n"
}
```

**Expected behavior**

When inputting short text.
```
this is a short msg1
this is a short msg2
this is a short msg3
this is a short msg4
this is a short msg5
this is a short msg6
this is a short msg7
```
image

When inputting long text.
```
this is a 35 characters long msg111
this is a 35 characters long msg222
this is a 35 characters long msg333
this is a 35 characters long msg444
this is a 35 characters long msg555
this is a 35 characters long msg666
this is a 35 characters long msg777
```
image

Contributor guide

Open the contributing guide

Research direction

Start with the viewport example at examples/chat/main.go and reproduce the issue using viewport.New(30, 5), long wrapped messages, and GotoBottom(). Trace how SetContent calculates wrapped lines and how GotoBottom selects the visible area; done means the viewport displays the actual bottom of long, multiline content.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
cli
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.