Skip to content

Commit a307e8c

Browse files
authored
Merge pull request #151 from nilsbeck/feature/allow-custom-spinners
feature/allow-custom-spinners
2 parents c8cf82e + a38ef25 commit a307e8c

File tree

5 files changed

+80
-5
lines changed

5 files changed

+80
-5
lines changed

examples/customization/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,5 @@ func main() {
3838

3939
// got notified that progress bar is complete.
4040
<-doneCh
41-
fmt.Println("\n ======= progress bar completed ==========\n")
41+
fmt.Println("\n ======= progress bar completed ==========")
4242
}

examples/download/main.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"fmt"
45
"io"
56
"net/http"
67
"os"
@@ -11,7 +12,7 @@ import (
1112
func main() {
1213
req, _ := http.NewRequest("GET", "https://dl.google.com/go/go1.14.2.src.tar.gz", nil)
1314
resp, _ := http.DefaultClient.Do(req)
14-
defer resp.Body.Close()
15+
defer check(resp.Body.Close)
1516

1617
f, _ := os.OpenFile("go1.14.2.src.tar.gz", os.O_CREATE|os.O_WRONLY, 0644)
1718
defer f.Close()
@@ -22,3 +23,10 @@ func main() {
2223
)
2324
io.Copy(io.MultiWriter(f, bar), resp.Body)
2425
}
26+
27+
// check checks the returned error of a function.
28+
func check(f func() error) {
29+
if err := f(); err != nil {
30+
fmt.Fprintf(os.Stderr, "received error: %v\n", err)
31+
}
32+
}

examples/pacman/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,5 @@ func main() {
3737

3838
// got notified that progress bar is complete.
3939
<-doneCh
40-
fmt.Println("\n ======= progress bar completed ==========\n")
40+
fmt.Println("\n ======= progress bar completed ==========")
4141
}

progressbar.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@ type config struct {
9696
// spinnerType should be a number between 0-75
9797
spinnerType int
9898

99+
// spinnerTypeOptionUsed remembers if the spinnerType was changed manually
100+
spinnerTypeOptionUsed bool
101+
102+
// spinner represents the spinner as a slice of string
103+
spinner []string
104+
99105
// fullWidth specifies whether to measure and set the bar to a specific width
100106
fullWidth bool
101107

@@ -134,10 +140,19 @@ func OptionSetWidth(s int) Option {
134140
// OptionSpinnerType sets the type of spinner used for indeterminate bars
135141
func OptionSpinnerType(spinnerType int) Option {
136142
return func(p *ProgressBar) {
143+
p.config.spinnerTypeOptionUsed = true
137144
p.config.spinnerType = spinnerType
138145
}
139146
}
140147

148+
// OptionSpinnerCustom sets the spinner used for indeterminate bars to the passed
149+
// slice of string
150+
func OptionSpinnerCustom(spinner []string) Option {
151+
return func(p *ProgressBar) {
152+
p.config.spinner = spinner
153+
}
154+
}
155+
141156
// OptionSetTheme sets the elements the bar is constructed of
142157
func OptionSetTheme(t Theme) Option {
143158
return func(p *ProgressBar) {
@@ -509,6 +524,11 @@ func (p *ProgressBar) Add64(num int64) error {
509524
return nil
510525
}
511526

527+
// error out since OptionSpinnerCustom will always override a manually set spinnerType
528+
if p.config.spinnerTypeOptionUsed && len(p.config.spinner) > 0 {
529+
return errors.New("OptionSpinnerType and OptionSpinnerCustom cannot be used together")
530+
}
531+
512532
if p.config.max == 0 {
513533
return errors.New("max must be greater than 0")
514534
}
@@ -853,7 +873,11 @@ func renderProgressBar(c config, s *state) (int, error) {
853873
str := ""
854874

855875
if c.ignoreLength {
856-
spinner := spinners[c.spinnerType][int(math.Round(math.Mod(float64(time.Since(s.startTime).Milliseconds()/100), float64(len(spinners[c.spinnerType])))))]
876+
selectedSpinner := spinners[c.spinnerType]
877+
if len(c.spinner) > 0 {
878+
selectedSpinner = c.spinner
879+
}
880+
spinner := selectedSpinner[int(math.Round(math.Mod(float64(time.Since(s.startTime).Milliseconds()/100), float64(len(selectedSpinner)))))]
857881
if c.elapsedTime {
858882
if c.showDescriptionAtLineEnd {
859883
str = fmt.Sprintf("\r%s %s [%s] %s ",

progressbar_test.go

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,13 +201,56 @@ func TestSpinnerType(t *testing.T) {
201201
bar.Reset()
202202
for i := 0; i < 10; i++ {
203203
time.Sleep(120 * time.Millisecond)
204-
bar.Add(1)
204+
err := bar.Add(1)
205+
if err != nil {
206+
t.Errorf("Successfully tested one spinner option can be used.")
207+
}
205208
}
206209
if false {
207210
t.Errorf("error")
208211
}
209212
}
210213

214+
func TestSpinnerCustom(t *testing.T) {
215+
bar := NewOptions(-1,
216+
OptionSetWidth(10),
217+
OptionSetDescription("indeterminate spinner"),
218+
OptionShowIts(),
219+
OptionShowCount(),
220+
OptionSpinnerCustom([]string{"🐰", "🐰", "🥕", "🥕"}),
221+
)
222+
bar.Reset()
223+
for i := 0; i < 10; i++ {
224+
time.Sleep(120 * time.Millisecond)
225+
err := bar.Add(1)
226+
if err != nil {
227+
t.Errorf("Successfully tested one spinner option can be used.")
228+
}
229+
}
230+
if false {
231+
t.Errorf("error")
232+
}
233+
}
234+
235+
func TestSpinnerTypeAndCustom(t *testing.T) {
236+
bar := NewOptions(-1,
237+
OptionSetWidth(10),
238+
OptionSetDescription("indeterminate spinner"),
239+
OptionShowIts(),
240+
OptionShowCount(),
241+
OptionSpinnerCustom([]string{"🐰", "🐰", "🥕", "🥕"}),
242+
OptionSpinnerType(9),
243+
)
244+
bar.Reset()
245+
for i := 0; i < 10; i++ {
246+
time.Sleep(120 * time.Millisecond)
247+
err := bar.Add(1)
248+
if err == nil {
249+
t.Errorf("Successfully tested both spinner options cannot be used together.")
250+
}
251+
}
252+
}
253+
211254
func Test_IsFinished(t *testing.T) {
212255
isCalled := false
213256
bar := NewOptions(72, OptionOnCompletion(func() {

0 commit comments

Comments
 (0)