Fix a bug in macOS terminal where stuff could get sucked into the scroll area

This commit is contained in:
Christian Rocha
2020-07-13 11:39:04 -04:00
parent 8025748828
commit 2f53eeb54b
2 changed files with 37 additions and 13 deletions

View File

@@ -29,6 +29,9 @@ type renderer struct {
lastRender string lastRender string
linesRendered int linesRendered int
// essentially whether or not we're using the full size of the terminal
altScreenActive bool
// renderer dimensions; usually the size of the window // renderer dimensions; usually the size of the window
width int width int
height int height int
@@ -156,7 +159,14 @@ func (r *renderer) flush() {
// Make sure the cursor is at the start of the last line to keep rendering // Make sure the cursor is at the start of the last line to keep rendering
// behavior consistent. // behavior consistent.
cursorBack(out, r.width) if r.altScreenActive {
// We need this case to fix a bug in macOS terminal. In other terminals
// the below case seems to do the job regardless of whether or not we're
// using the full terminal window.
moveCursor(out, r.linesRendered, 0)
} else {
cursorBack(out, r.width)
}
_, _ = r.out.Write(out.Bytes()) _, _ = r.out.Write(out.Bytes())
r.lastRender = r.buf.String() r.lastRender = r.buf.String()

38
tea.go
View File

@@ -53,8 +53,10 @@ type Program struct {
update Update update Update
view View view View
mtx sync.Mutex mtx sync.Mutex
output *os.File // where to send output. this will usually be os.Stdout. output *os.File // where to send output. this will usually be os.Stdout.
renderer *renderer
altScreenActive bool
} }
// Quit is a special command that tells the program to exit. // Quit is a special command that tells the program to exit.
@@ -91,13 +93,14 @@ func NewProgram(init Init, update Update, view View) *Program {
// Start initializes the program. // Start initializes the program.
func (p *Program) Start() error { func (p *Program) Start() error {
var ( var (
cmds = make(chan Cmd) cmds = make(chan Cmd)
msgs = make(chan Msg) msgs = make(chan Msg)
errs = make(chan error) errs = make(chan error)
done = make(chan struct{}) done = make(chan struct{})
mrRenderer = newRenderer(p.output, &p.mtx)
) )
p.renderer = newRenderer(p.output, &p.mtx)
err := initTerminal() err := initTerminal()
if err != nil { if err != nil {
return err return err
@@ -113,10 +116,11 @@ func (p *Program) Start() error {
} }
// Start renderer // Start renderer
mrRenderer.start() p.renderer.start()
p.renderer.altScreenActive = p.altScreenActive
// Render initial view // Render initial view
mrRenderer.write(p.view(model)) p.renderer.write(p.view(model))
// Subscribe to user input // Subscribe to user input
go func() { go func() {
@@ -167,7 +171,7 @@ func (p *Program) Start() error {
// Handle quit message // Handle quit message
if _, ok := msg.(quitMsg); ok { if _, ok := msg.(quitMsg); ok {
mrRenderer.stop() p.renderer.stop()
close(done) close(done)
return nil return nil
} }
@@ -181,11 +185,11 @@ func (p *Program) Start() error {
} }
// Process internal messages for the renderer // Process internal messages for the renderer
mrRenderer.handleMessages(msg) p.renderer.handleMessages(msg)
var cmd Cmd var cmd Cmd
model, cmd = p.update(msg, model) // run update model, cmd = p.update(msg, model) // run update
cmds <- cmd // process command (if any) cmds <- cmd // process command (if any)
mrRenderer.write(p.view(model)) // send view to renderer p.renderer.write(p.view(model)) // send view to renderer
} }
} }
} }
@@ -196,6 +200,11 @@ func (p *Program) EnterAltScreen() {
defer p.mtx.Unlock() defer p.mtx.Unlock()
fmt.Fprintf(p.output, te.CSI+te.AltScreenSeq) fmt.Fprintf(p.output, te.CSI+te.AltScreenSeq)
moveCursor(p.output, 0, 0) moveCursor(p.output, 0, 0)
p.altScreenActive = true
if p.renderer != nil {
p.renderer.altScreenActive = p.altScreenActive
}
} }
// ExitAltScreen exits the alternate screen buffer. // ExitAltScreen exits the alternate screen buffer.
@@ -203,6 +212,11 @@ func (p *Program) ExitAltScreen() {
p.mtx.Lock() p.mtx.Lock()
defer p.mtx.Unlock() defer p.mtx.Unlock()
fmt.Fprintf(p.output, te.CSI+te.ExitAltScreenSeq) fmt.Fprintf(p.output, te.CSI+te.ExitAltScreenSeq)
p.altScreenActive = false
if p.renderer != nil {
p.renderer.altScreenActive = p.altScreenActive
}
} }
// EnableMouseCellMotion enables mouse click, release, wheel and motion events if a // EnableMouseCellMotion enables mouse click, release, wheel and motion events if a