diff --git a/commands.go b/commands.go index 164dad21ad..028acf115b 100644 --- a/commands.go +++ b/commands.go @@ -147,34 +147,6 @@ func Tick(d time.Duration, fn func(time.Time) Msg) Cmd { } } -// Sequentially produces a command that sequentially executes the given -// commands. -// The Msg returned is the first non-nil message returned by a Cmd. -// -// func saveStateCmd() Msg { -// if err := save(); err != nil { -// return errMsg{err} -// } -// return nil -// } -// -// cmd := Sequentially(saveStateCmd, Quit) -// -// Deprecated: use Sequence instead. -func Sequentially(cmds ...Cmd) Cmd { - return func() Msg { - for _, cmd := range cmds { - if cmd == nil { - continue - } - if msg := cmd(); msg != nil { - return msg - } - } - return nil - } -} - // setWindowTitleMsg is an internal message used to set the window title. type setWindowTitleMsg string diff --git a/commands_test.go b/commands_test.go index feb1ee89dd..ab46c409e6 100644 --- a/commands_test.go +++ b/commands_test.go @@ -1,6 +1,7 @@ package tea import ( + "context" "fmt" "testing" "time" @@ -26,7 +27,7 @@ func TestTick(t *testing.T) { } } -func TestSequentially(t *testing.T) { +func TestSequence(t *testing.T) { expectedErrMsg := fmt.Errorf("some err") expectedStrMsg := "some msg" @@ -37,12 +38,12 @@ func TestSequentially(t *testing.T) { tests := []struct { name string cmds []Cmd - expected Msg + expected []Msg }{ { name: "all nil", cmds: []Cmd{nilReturnCmd, nilReturnCmd}, - expected: nil, + expected: []Msg{nil, nil}, }, { name: "null cmds", @@ -58,7 +59,7 @@ func TestSequentially(t *testing.T) { }, nilReturnCmd, }, - expected: expectedErrMsg, + expected: []Msg{nil, expectedErrMsg, nil}, }, { name: "some msg", @@ -69,13 +70,22 @@ func TestSequentially(t *testing.T) { }, nilReturnCmd, }, - expected: expectedStrMsg, + expected: []Msg{nil, expectedStrMsg, nil}, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - if msg := Sequentially(test.cmds...)(); msg != test.expected { - t.Fatalf("expected a msg %v but got %v", test.expected, msg) + var msgs []Msg + sequentially(context.TODO(), Sequence(test.cmds...)().(sequenceMsg), func(m Msg) { + msgs = append(msgs, m) + }) + if len(msgs) != len(test.expected) { + t.Fatalf("expected %d msgs but got %d", len(test.expected), len(msgs)) + } + for i, msg := range msgs { + if msg != test.expected[i] { + t.Fatalf("expected a msg %v but got %v", test.expected[i], msg) + } } }) } diff --git a/nil_renderer.go b/nil_renderer.go index b9edeac134..f4a83b6bc4 100644 --- a/nil_renderer.go +++ b/nil_renderer.go @@ -22,3 +22,4 @@ func (n nilRenderer) disableBracketedPaste() {} func (n nilRenderer) enableMouseSGRMode() {} func (n nilRenderer) disableMouseSGRMode() {} func (n nilRenderer) bracketedPasteActive() bool { return false } +func (n nilRenderer) setWindowTitle(_ string) {} diff --git a/renderer.go b/renderer.go index 65c2ae6dfa..de3936e73b 100644 --- a/renderer.go +++ b/renderer.go @@ -67,6 +67,9 @@ type renderer interface { // bracketedPasteActive reports whether bracketed paste mode is // currently enabled. bracketedPasteActive() bool + + // setWindowTitle sets the terminal window title. + setWindowTitle(string) } // repaintMsg forces a full repaint. diff --git a/screen.go b/screen.go index b34af56d7b..a16f0ac1e9 100644 --- a/screen.go +++ b/screen.go @@ -143,60 +143,3 @@ func DisableBracketedPaste() Msg { // bracketed paste should be disabled. You can send an // disableBracketedPasteMsg with DisableBracketedPaste. type disableBracketedPasteMsg struct{} - -// EnterAltScreen enters the alternate screen buffer, which consumes the entire -// terminal window. ExitAltScreen will return the terminal to its former state. -// -// Deprecated: Use the WithAltScreen ProgramOption instead. -func (p *Program) EnterAltScreen() { - if p.renderer != nil { - p.renderer.enterAltScreen() - } -} - -// ExitAltScreen exits the alternate screen buffer. -// -// Deprecated: The altscreen will exited automatically when the program exits. -func (p *Program) ExitAltScreen() { - if p.renderer != nil { - p.renderer.exitAltScreen() - } -} - -// EnableMouseCellMotion enables mouse click, release, wheel and motion events -// if a mouse button is pressed (i.e., drag events). -// -// Deprecated: Use the WithMouseCellMotion ProgramOption instead. -func (p *Program) EnableMouseCellMotion() { - p.renderer.enableMouseCellMotion() -} - -// DisableMouseCellMotion disables Mouse Cell Motion tracking. This will be -// called automatically when exiting a Bubble Tea program. -// -// Deprecated: The mouse will automatically be disabled when the program exits. -func (p *Program) DisableMouseCellMotion() { - p.renderer.disableMouseCellMotion() -} - -// EnableMouseAllMotion enables mouse click, release, wheel and motion events, -// regardless of whether a mouse button is pressed. Many modern terminals -// support this, but not all. -// -// Deprecated: Use the WithMouseAllMotion ProgramOption instead. -func (p *Program) EnableMouseAllMotion() { - p.renderer.enableMouseAllMotion() -} - -// DisableMouseAllMotion disables All Motion mouse tracking. This will be -// called automatically when exiting a Bubble Tea program. -// -// Deprecated: The mouse will automatically be disabled when the program exits. -func (p *Program) DisableMouseAllMotion() { - p.renderer.disableMouseAllMotion() -} - -// SetWindowTitle sets the terminal window title. -func (p *Program) SetWindowTitle(title string) { - p.output.SetWindowTitle(title) -} diff --git a/standard_renderer.go b/standard_renderer.go index 4e63fd6ecc..c132b10625 100644 --- a/standard_renderer.go +++ b/standard_renderer.go @@ -445,6 +445,10 @@ func (r *standardRenderer) bracketedPasteActive() bool { return r.bpActive } +func (r *standardRenderer) setWindowTitle(title string) { + r.out.SetWindowTitle(title) +} + // setIgnoredLines specifies lines not to be touched by the standard Bubble Tea // renderer. func (r *standardRenderer) setIgnoredLines(from int, to int) { diff --git a/tea.go b/tea.go index ee3d9cd413..856c00372c 100644 --- a/tea.go +++ b/tea.go @@ -373,34 +373,11 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) { case sequenceMsg: go func() { - // Execute commands one at a time, in order. - for _, cmd := range msg { - if cmd == nil { - continue - } - - msg := cmd() - if batchMsg, ok := msg.(BatchMsg); ok { - g, _ := errgroup.WithContext(p.ctx) - for _, cmd := range batchMsg { - cmd := cmd - g.Go(func() error { - p.Send(cmd()) - return nil - }) - } - - //nolint:errcheck - g.Wait() // wait for all commands from batch msg to finish - continue - } - - p.Send(msg) - } + sequentially(p.ctx, msg, p.Send) }() case setWindowTitleMsg: - p.SetWindowTitle(string(msg)) + p.renderer.setWindowTitle(string(msg)) } // Process internal messages for the renderer. @@ -416,6 +393,33 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) { } } +func sequentially(ctx context.Context, msg sequenceMsg, sender func(Msg)) { + // Execute commands one at a time, in order. + for _, cmd := range msg { + if cmd == nil { + continue + } + + msg := cmd() + if batchMsg, ok := msg.(BatchMsg); ok { + g, _ := errgroup.WithContext(ctx) + for _, cmd := range batchMsg { + cmd := cmd + g.Go(func() error { + sender(cmd()) + return nil + }) + } + + //nolint:errcheck + g.Wait() // wait for all commands from batch msg to finish + continue + } + + sender(msg) + } +} + // Run initializes the program and runs its event loops, blocking until it gets // terminated by either [Program.Quit], [Program.Kill], or its signal handler. // Returns the final model. @@ -574,25 +578,6 @@ func (p *Program) Run() (Model, error) { return model, err } -// StartReturningModel initializes the program and runs its event loops, -// blocking until it gets terminated by either [Program.Quit], [Program.Kill], -// or its signal handler. Returns the final model. -// -// Deprecated: please use [Program.Run] instead. -func (p *Program) StartReturningModel() (Model, error) { - return p.Run() -} - -// Start initializes the program and runs its event loops, blocking until it -// gets terminated by either [Program.Quit], [Program.Kill], or its signal -// handler. -// -// Deprecated: please use [Program.Run] instead. -func (p *Program) Start() error { - _, err := p.Run() - return err -} - // Send sends a message to the main update function, effectively allowing // messages to be injected from outside the program for interoperability // purposes. diff --git a/tea_test.go b/tea_test.go index d65f0d7fe3..257ad36d2d 100644 --- a/tea_test.go +++ b/tea_test.go @@ -110,7 +110,7 @@ func testTeaWithFilter(t *testing.T, preventCount uint32) { } }() - if err := p.Start(); err != nil { + if _, err := p.Run(); err != nil { t.Fatal(err) } if shutdowns != preventCount {