mirror of
https://github.com/taigrr/bubbletea.git
synced 2026-04-02 02:59:09 -07:00
Fix a bug in macOS terminal where stuff could get sucked into the scroll area
This commit is contained in:
12
renderer.go
12
renderer.go
@@ -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
38
tea.go
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user