mirror of
				https://github.com/Maks1mS/bubbles.git
				synced 2025-10-30 21:37:13 +03:00 
			
		
		
		
	feat(spinners): Construct new spinners with WithSpinner + WithStyle options (#148)
				
					
				
			* Add spinner.New test Signed-off-by: Leandro López (inkel) <inkel.ar@gmail.com> * Add spinner.Option type and spinner.WithSpinner option Signed-off-by: Leandro López (inkel) <inkel.ar@gmail.com> * 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) <inkel.ar@gmail.com> * Add spinner.WithX option for each spinner.Spinner Signed-off-by: Leandro López (inkel) <inkel.ar@gmail.com> * Refactor spinner tests Signed-off-by: Leandro López (inkel) <inkel.ar@gmail.com> * Add spinner.WithStyle option function Signed-off-by: Leandro López (inkel) <inkel.ar@gmail.com> * refactor: remove With... Spinner aliases Co-authored-by: Maas Lalani <maas@lalani.dev>
This commit is contained in:
		
				
					committed by
					
						 Maas Lalani
						Maas Lalani
					
				
			
			
				
	
			
			
			
						parent
						
							2578480343
						
					
				
				
					commit
					69bf367d37
				
			| @@ -109,11 +109,17 @@ func (m Model) ID() int { | |||||||
| } | } | ||||||
|  |  | ||||||
| // New returns a model with default values. | // New returns a model with default values. | ||||||
| func New() Model { | func New(opts ...Option) Model { | ||||||
| 	return Model{ | 	m := Model{ | ||||||
| 		Spinner: Line, | 		Spinner: Line, | ||||||
| 		id:      nextID(), | 		id:      nextID(), | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	for _, opt := range opts { | ||||||
|  | 		opt(&m) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return m | ||||||
| } | } | ||||||
|  |  | ||||||
| // NewModel returns a model with default values. | // NewModel returns a model with default values. | ||||||
| @@ -199,3 +205,23 @@ func (m Model) tick(id, tag int) tea.Cmd { | |||||||
| func Tick() tea.Msg { | func Tick() tea.Msg { | ||||||
| 	return TickMsg{Time: time.Now()} | 	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
									
								
								spinner/spinner_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								spinner/spinner_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user