Skip to content

Commit

Permalink
feat(spinners): Construct new spinners with WithSpinner + `WithStyl…
Browse files Browse the repository at this point in the history
…e` options (#148)

* Add spinner.New test

Signed-off-by: Leandro López (inkel) <[email protected]>

* Add spinner.Option type and spinner.WithSpinner option

Signed-off-by: Leandro López (inkel) <[email protected]>

* Allow passing options in spinner.New

This doesn't break existing code as it uses variadic arguments, so
any existing code as the following should continue to work:

    s := spinner.New()
    s.spinner = spinner.Dot

This change allows for instead of those two lines, having a call:

   s := spinner.New(spinner.WithSpinner(spinner.Dot))

Signed-off-by: Leandro López (inkel) <[email protected]>

* Add spinner.WithX option for each spinner.Spinner

Signed-off-by: Leandro López (inkel) <[email protected]>

* Refactor spinner tests

Signed-off-by: Leandro López (inkel) <[email protected]>

* Add spinner.WithStyle option function

Signed-off-by: Leandro López (inkel) <[email protected]>

* refactor: remove With... Spinner aliases

Co-authored-by: Maas Lalani <[email protected]>
  • Loading branch information
inkel and maaslalani committed Jul 5, 2022
1 parent 2578480 commit 69bf367
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 2 deletions.
30 changes: 28 additions & 2 deletions spinner/spinner.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,17 @@ func (m Model) ID() int {
}

// New returns a model with default values.
func New() Model {
return Model{
func New(opts ...Option) Model {
m := Model{
Spinner: Line,
id: nextID(),
}

for _, opt := range opts {
opt(&m)
}

return m
}

// NewModel returns a model with default values.
Expand Down Expand Up @@ -199,3 +205,23 @@ func (m Model) tick(id, tag int) tea.Cmd {
func Tick() tea.Msg {
return TickMsg{Time: time.Now()}
}

// Option is used to set options in New. For example:
//
// spinner := New(WithSpinner(Dot))
//
type Option func(*Model)

// WithSpinner is an option to set the spinner.
func WithSpinner(spinner Spinner) Option {
return func(m *Model) {
m.Spinner = spinner
}
}

// WithStyle is an option to set the spinner style.
func WithStyle(style lipgloss.Style) Option {
return func(m *Model) {
m.Style = style
}
}
61 changes: 61 additions & 0 deletions spinner/spinner_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package spinner_test

import (
"testing"

"github.com/charmbracelet/bubbles/spinner"
)

func TestSpinnerNew(t *testing.T) {
assertEqualSpinner := func(t *testing.T, exp, got spinner.Spinner) {
t.Helper()

if exp.FPS != got.FPS {
t.Errorf("expecting %d FPS, got %d", exp.FPS, got.FPS)
}

if e, g := len(exp.Frames), len(got.Frames); e != g {
t.Fatalf("expecting %d frames, got %d", e, g)
}

for i, e := range exp.Frames {
if g := got.Frames[i]; e != g {
t.Errorf("expecting frame index %d with value %q, got %q", i, e, g)
}
}
}
t.Run("default", func(t *testing.T) {
s := spinner.New()

assertEqualSpinner(t, spinner.Line, s.Spinner)
})

t.Run("WithSpinner", func(t *testing.T) {
customSpinner := spinner.Spinner{
Frames: []string{"a", "b", "c", "d"},
FPS: 16,
}

s := spinner.New(spinner.WithSpinner(customSpinner))

assertEqualSpinner(t, customSpinner, s.Spinner)
})

tests := map[string]spinner.Spinner{
"Line": spinner.Line,
"Dot": spinner.Dot,
"MiniDot": spinner.MiniDot,
"Jump": spinner.Jump,
"Pulse": spinner.Pulse,
"Points": spinner.Points,
"Globe": spinner.Globe,
"Moon": spinner.Moon,
"Monkey": spinner.Monkey,
}

for name, s := range tests {
t.Run(name, func(t *testing.T) {
assertEqualSpinner(t, spinner.New(spinner.WithSpinner(s)).Spinner, s)
})
}
}

0 comments on commit 69bf367

Please sign in to comment.