-
Notifications
You must be signed in to change notification settings - Fork 819
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: cursor position adjustment after exiting alt screen #1241
fix: cursor position adjustment after exiting alt screen #1241
Conversation
In my understanding, the source of this issue appears to be that the terminal automatically moves the cursor back to its position, where it was before entering alt screen mode, when exiting. |
Thanks for this, @semihbkgr. Can you also paste in some code for a minimally reproducible example? It would also be good to know if this is a regression in |
Hi @meowgorithm
There is already an example in the issue mentioned in the description. It was a real case we encountered in kubectl-klock. However, I will share a simplified example to reproduce the bug more easily, which directly highlights the problematic situation 👍
The issue dates back to older versions. The issue was created on May 10, indicating it was first observed in |
Operations
The issue occurs when the number of lines rendered in alt screen mode differs from the lines rendered before entering alt screen mode — either fewer lines (leaving leftover lines) or more lines (overwriting old lines). Reproducing the Overwriting Old Lines Bug:
Reproducing the Keeping Leftover Lines Bug:
package main
import (
"fmt"
"os"
"strings"
tea "github.com/charmbracelet/bubbletea"
)
type model struct {
altscreen bool
n int
}
func (m model) Init() tea.Cmd {
return nil
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "q", "ctrl+c", "esc":
return m, tea.Quit
case "j":
m.n += 1
case "k":
m.n -= 1
case " ":
var cmd tea.Cmd
if m.altscreen {
cmd = tea.ExitAltScreen
} else {
cmd = tea.EnterAltScreen
}
m.altscreen = !m.altscreen
return m, cmd
}
}
return m, nil
}
func (m model) View() string {
b := strings.Builder{}
if m.altscreen {
b.WriteString("alt screen\n")
} else {
b.WriteString("normal screen\n")
}
for i := 0; i < m.n; i++ {
b.WriteString(fmt.Sprintf("%d. line\n", i))
}
return b.String()
}
func main() {
if _, err := tea.NewProgram(model{}).Run(); err != nil {
fmt.Println("Error running program:", err)
os.Exit(1)
}
} |
Thanks for that; we're taking a look. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thank you, @semihbkgr!
Awesome fix, @semihbkgr: thank you. We'll get a patch release out today. |
* fix cursor position handling after exiting alt screen mode * avoid moving cursor when lines rendered before alt screen is zero
Alright, |
|
We need to keep a separate count of lines rendered in the alt screen and inline mode. This is because when we enter alt screen mode, the cursor position is saved and the alt screen is cleared. Now when we exit the alt screen mode, the cursor position is restored so we don't need to move the cursor to the beginning of the section that we rendered. To fix this, we keep a separate count of lines rendered in the alt screen mode and inline mode. Related: #1013 Fixes: #1241 Fixes: #1248
We need to keep a separate count of lines rendered in the alt screen and inline mode. This is because when we enter alt screen mode, the cursor position is saved and the alt screen is cleared. Now when we exit the alt screen mode, the cursor position is restored so we don't need to move the cursor to the beginning of the section that we rendered. To fix this, we keep a separate count of lines rendered in the alt screen mode and inline mode. Related: #1013 Fixes: #1241 Fixes: #1248
When exiting alternate screen mode, the cursor was not properly adjusted, which caused terminal content to be either overwritten (if the current line count was greater than before entering alt screen) or leftover lines to remain at the top (if the current line count was smaller). To fix this, we save the number of lines rendered before entering alternate screen mode. When exiting, we compare the current line count with the saved value and adjust the cursor position accordingly, ensuring correct positioning and preventing both overwriting and leftover lines.
fixes #1013