diff --git a/commands.go b/commands.go index 164dad21ad..f1e9f69d3b 100644 --- a/commands.go +++ b/commands.go @@ -13,6 +13,27 @@ import ( // return tea.Batch(someCommand, someOtherCommand) // } func Batch(cmds ...Cmd) Cmd { + return compactCmds[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 compactCmds[sequenceMsg](cmds) +} + +// sequenceMsg is used internally to run the given commands in order. +type sequenceMsg []Cmd + +// compactCmds ignores any nil commands in cmds, and returns the most direct +// command possible. That is, considering the non-nil commands, if there are +// none it returns nil, if there is exactly one it returns that command +// directly, else it returns the non-nil commands as type T. +func compactCmds[T ~[]Cmd](cmds []Cmd) Cmd { var validCmds []Cmd //nolint:prealloc for _, c := range cmds { if c == nil { @@ -27,26 +48,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..0306929a33 100644 --- a/commands_test.go +++ b/commands_test.go @@ -82,25 +82,33 @@ func TestSequentially(t *testing.T) { } func TestBatch(t *testing.T) { + testMultipleCommands[BatchMsg](t, Batch) +} + +func TestSequence(t *testing.T) { + testMultipleCommands[sequenceMsg](t, Sequence) +} + +func testMultipleCommands[T ~[]Cmd](t *testing.T, createFn func(cmd ...Cmd) Cmd) { t.Run("nil cmd", func(t *testing.T) { - if b := Batch(nil); b != nil { + if b := createFn(nil); b != nil { t.Fatalf("expected nil, got %+v", b) } }) t.Run("empty cmd", func(t *testing.T) { - if b := Batch(); b != nil { + if b := createFn(); b != nil { t.Fatalf("expected nil, got %+v", b) } }) t.Run("single cmd", func(t *testing.T) { - b := Batch(Quit)() + b := createFn(Quit)() if _, ok := b.(QuitMsg); !ok { t.Fatalf("expected a QuitMsg, got %T", b) } }) t.Run("mixed nil cmds", func(t *testing.T) { - b := Batch(nil, Quit, nil, Quit, nil, nil)() - if l := len(b.(BatchMsg)); l != 2 { + b := createFn(nil, Quit, nil, Quit, nil, nil)() + if l := len(b.(T)); l != 2 { t.Fatalf("expected a []Cmd with len 2, got %d", l) } })