diff --git a/commands.go b/commands.go index bfa3b70455..e2a0753ab5 100644 --- a/commands.go +++ b/commands.go @@ -13,6 +13,25 @@ import ( // return tea.Batch(someCommand, someOtherCommand) // } func Batch(cmds ...Cmd) Cmd { + return trimNilCommands[BatchMsg](cmds...) +} + +// BatchMsg is a message used to perform a bunch of commands concurrently with +// no ordering guarantees. You can send a BatchMsg with Batch. +type BatchMsg []Cmd + +// Sequence runs the given commands one at a time, in order. Contrast this with +// Batch, which runs commands concurrently. +func Sequence(cmds ...Cmd) Cmd { + return trimNilCommands[sequenceMsg](cmds...) +} + +// sequenceMsg is used internally to run the given commands in order. +type sequenceMsg []Cmd + +// Trims a list of commands, removing any nil entries. If there are no entries +// left after the slice is trimmed, then the code will return nil. +func trimNilCommands[T BatchMsg | sequenceMsg](cmds ...Cmd) Cmd { var validCmds []Cmd //nolint:prealloc for _, c := range cmds { if c == nil { @@ -27,26 +46,11 @@ func Batch(cmds ...Cmd) Cmd { return validCmds[0] default: return func() Msg { - return BatchMsg(validCmds) + return T(validCmds) } } } -// BatchMsg is a message used to perform a bunch of commands concurrently with -// no ordering guarantees. You can send a BatchMsg with Batch. -type BatchMsg []Cmd - -// Sequence runs the given commands one at a time, in order. Contrast this with -// Batch, which runs commands concurrently. -func Sequence(cmds ...Cmd) Cmd { - return func() Msg { - return sequenceMsg(cmds) - } -} - -// sequenceMsg is used internally to run the given commands in order. -type sequenceMsg []Cmd - // Every is a command that ticks in sync with the system clock. So, if you // wanted to tick with the system clock every second, minute or hour you // could use this. It's also handy for having different things tick in sync. diff --git a/commands_test.go b/commands_test.go index feb1ee89dd..2fa1f733b0 100644 --- a/commands_test.go +++ b/commands_test.go @@ -81,6 +81,31 @@ func TestSequentially(t *testing.T) { } } +func TestSequence(t *testing.T) { + t.Run("nil cmd", func(t *testing.T) { + if b := Sequence(nil); b != nil { + t.Fatalf("expected nil, got %+v", b) + } + }) + t.Run("empty cmd", func(t *testing.T) { + if b := Sequence(); b != nil { + t.Fatalf("expected nil, got %+v", b) + } + }) + t.Run("single cmd", func(t *testing.T) { + b := Sequence(Quit)() + if _, ok := b.(QuitMsg); !ok { + t.Fatalf("expected a QuitMsg, got %T", b) + } + }) + t.Run("mixed nil cmds", func(t *testing.T) { + b := Sequence(nil, Quit, nil, Quit, nil, nil)() + if l := len(b.(sequenceMsg)); l != 2 { + t.Fatalf("expected a []Cmd with len 2, got %d", l) + } + }) +} + func TestBatch(t *testing.T) { t.Run("nil cmd", func(t *testing.T) { if b := Batch(nil); b != nil {