mirror of
https://github.com/taigrr/bubbletea.git
synced 2026-04-02 02:59:09 -07:00
feat: use Termenv.Output to write to tty
This commit is contained in:
45
tea.go
45
tea.go
@@ -23,7 +23,7 @@ import (
|
||||
"github.com/containerd/console"
|
||||
isatty "github.com/mattn/go-isatty"
|
||||
"github.com/muesli/cancelreader"
|
||||
te "github.com/muesli/termenv"
|
||||
"github.com/muesli/termenv"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
@@ -89,9 +89,10 @@ type Program struct {
|
||||
errs chan error
|
||||
readLoopDone chan struct{}
|
||||
|
||||
output io.Writer // where to send output. this will usually be os.Stdout.
|
||||
input io.Reader // this will usually be os.Stdin.
|
||||
cancelReader cancelreader.CancelReader
|
||||
output *termenv.Output // where to send output. this will usually be os.Stdout.
|
||||
restoreOutput func() error
|
||||
input io.Reader // this will usually be os.Stdin.
|
||||
cancelReader cancelreader.CancelReader
|
||||
|
||||
renderer renderer
|
||||
altScreenActive bool
|
||||
@@ -253,7 +254,6 @@ func NewProgram(model Model, opts ...ProgramOption) *Program {
|
||||
p := &Program{
|
||||
mtx: &sync.Mutex{},
|
||||
initialModel: model,
|
||||
output: os.Stdout,
|
||||
input: os.Stdin,
|
||||
msgs: make(chan Msg),
|
||||
CatchPanics: true,
|
||||
@@ -265,6 +265,16 @@ func NewProgram(model Model, opts ...ProgramOption) *Program {
|
||||
opt(p)
|
||||
}
|
||||
|
||||
// if no output was set, set it to stdout
|
||||
if p.output == nil {
|
||||
p.output = termenv.DefaultOutput()
|
||||
|
||||
// cache detected color values
|
||||
termenv.WithColorCache(true)(p.output)
|
||||
}
|
||||
|
||||
p.restoreOutput, _ = termenv.EnableVirtualTerminalProcessing(p.output)
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
@@ -429,7 +439,7 @@ func (p *Program) StartReturningModel() (Model, error) {
|
||||
}
|
||||
defer p.cancelReader.Close() // nolint:errcheck
|
||||
|
||||
if f, ok := p.output.(*os.File); ok && isatty.IsTerminal(f.Fd()) {
|
||||
if f, ok := p.output.TTY().(*os.File); ok && isatty.IsTerminal(f.Fd()) {
|
||||
// Get the initial terminal size and send it to the program.
|
||||
go func() {
|
||||
w, h, err := term.GetSize(int(f.Fd()))
|
||||
@@ -527,7 +537,7 @@ func (p *Program) StartReturningModel() (Model, error) {
|
||||
p.DisableMouseAllMotion()
|
||||
|
||||
case hideCursorMsg:
|
||||
hideCursor(p.output)
|
||||
p.output.HideCursor()
|
||||
|
||||
case execMsg:
|
||||
// NB: this blocks.
|
||||
@@ -606,6 +616,10 @@ func (p *Program) shutdown(kill bool) {
|
||||
p.DisableMouseCellMotion()
|
||||
p.DisableMouseAllMotion()
|
||||
_ = p.restoreTerminalState()
|
||||
|
||||
if p.restoreOutput != nil {
|
||||
_ = p.restoreOutput()
|
||||
}
|
||||
}
|
||||
|
||||
// EnterAltScreen enters the alternate screen buffer, which consumes the entire
|
||||
@@ -620,7 +634,8 @@ func (p *Program) EnterAltScreen() {
|
||||
return
|
||||
}
|
||||
|
||||
enterAltScreen(p.output)
|
||||
p.output.AltScreen()
|
||||
p.output.MoveCursor(0, 0)
|
||||
|
||||
p.altScreenActive = true
|
||||
if p.renderer != nil {
|
||||
@@ -639,7 +654,7 @@ func (p *Program) ExitAltScreen() {
|
||||
return
|
||||
}
|
||||
|
||||
exitAltScreen(p.output)
|
||||
p.output.ExitAltScreen()
|
||||
|
||||
p.altScreenActive = false
|
||||
if p.renderer != nil {
|
||||
@@ -654,7 +669,8 @@ func (p *Program) ExitAltScreen() {
|
||||
func (p *Program) EnableMouseCellMotion() {
|
||||
p.mtx.Lock()
|
||||
defer p.mtx.Unlock()
|
||||
fmt.Fprintf(p.output, te.CSI+te.EnableMouseCellMotionSeq)
|
||||
|
||||
p.output.EnableMouseCellMotion()
|
||||
}
|
||||
|
||||
// DisableMouseCellMotion disables Mouse Cell Motion tracking. This will be
|
||||
@@ -664,7 +680,8 @@ func (p *Program) EnableMouseCellMotion() {
|
||||
func (p *Program) DisableMouseCellMotion() {
|
||||
p.mtx.Lock()
|
||||
defer p.mtx.Unlock()
|
||||
fmt.Fprintf(p.output, te.CSI+te.DisableMouseCellMotionSeq)
|
||||
|
||||
p.output.DisableMouseCellMotion()
|
||||
}
|
||||
|
||||
// EnableMouseAllMotion enables mouse click, release, wheel and motion events,
|
||||
@@ -675,7 +692,8 @@ func (p *Program) DisableMouseCellMotion() {
|
||||
func (p *Program) EnableMouseAllMotion() {
|
||||
p.mtx.Lock()
|
||||
defer p.mtx.Unlock()
|
||||
fmt.Fprintf(p.output, te.CSI+te.EnableMouseAllMotionSeq)
|
||||
|
||||
p.output.EnableMouseAllMotion()
|
||||
}
|
||||
|
||||
// DisableMouseAllMotion disables All Motion mouse tracking. This will be
|
||||
@@ -685,7 +703,8 @@ func (p *Program) EnableMouseAllMotion() {
|
||||
func (p *Program) DisableMouseAllMotion() {
|
||||
p.mtx.Lock()
|
||||
defer p.mtx.Unlock()
|
||||
fmt.Fprintf(p.output, te.CSI+te.DisableMouseAllMotionSeq)
|
||||
|
||||
p.output.DisableMouseAllMotion()
|
||||
}
|
||||
|
||||
// ReleaseTerminal restores the original terminal state and cancels the input
|
||||
|
||||
Reference in New Issue
Block a user