spinner decorator and example
Vladimir Bauer
7 years ago
|
0 |
package main
|
|
1 |
|
|
2 |
import (
|
|
3 |
"fmt"
|
|
4 |
"math/rand"
|
|
5 |
"sync"
|
|
6 |
"time"
|
|
7 |
|
|
8 |
"github.com/vbauerster/mpb/v4"
|
|
9 |
"github.com/vbauerster/mpb/v4/decor"
|
|
10 |
)
|
|
11 |
|
|
12 |
func init() {
|
|
13 |
rand.Seed(time.Now().UnixNano())
|
|
14 |
}
|
|
15 |
|
|
16 |
func main() {
|
|
17 |
var wg sync.WaitGroup
|
|
18 |
// pass &wg (optional), so p will wait for it eventually
|
|
19 |
p := mpb.New(mpb.WithWaitGroup(&wg), mpb.WithWidth(64))
|
|
20 |
total, numBars := 100, 3
|
|
21 |
wg.Add(numBars)
|
|
22 |
|
|
23 |
for i := 0; i < numBars; i++ {
|
|
24 |
name := fmt.Sprintf("Bar#%d:", i)
|
|
25 |
bar := p.AddBar(int64(total),
|
|
26 |
mpb.PrependDecorators(
|
|
27 |
// simple name decorator
|
|
28 |
decor.Name(name),
|
|
29 |
decor.OnComplete(
|
|
30 |
// spinner decorator with default style
|
|
31 |
decor.Spinner(nil, decor.WCSyncSpace), "done",
|
|
32 |
),
|
|
33 |
),
|
|
34 |
mpb.AppendDecorators(
|
|
35 |
// decor.DSyncWidth bit enables column width synchronization
|
|
36 |
decor.Percentage(decor.WCSyncWidth),
|
|
37 |
),
|
|
38 |
)
|
|
39 |
// simulating some work
|
|
40 |
go func() {
|
|
41 |
defer wg.Done()
|
|
42 |
max := 100 * time.Millisecond
|
|
43 |
for i := 0; i < total; i++ {
|
|
44 |
start := time.Now()
|
|
45 |
time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10)
|
|
46 |
// ewma based decorators require work duration measurement
|
|
47 |
bar.IncrBy(1, time.Since(start))
|
|
48 |
}
|
|
49 |
}()
|
|
50 |
}
|
|
51 |
// Waiting for passed &wg and for all bars to complete and flush
|
|
52 |
p.Wait()
|
|
53 |
}
|
|
0 |
package decor
|
|
1 |
|
|
2 |
var defaultSpinnerStyle = []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}
|
|
3 |
|
|
4 |
// Spinner returns spinner decorator.
|
|
5 |
//
|
|
6 |
// `frames` spinner frames, if nil or len==0, default is used
|
|
7 |
//
|
|
8 |
// `wcc` optional WC config
|
|
9 |
func Spinner(frames []string, wcc ...WC) Decorator {
|
|
10 |
var wc WC
|
|
11 |
for _, widthConf := range wcc {
|
|
12 |
wc = widthConf
|
|
13 |
}
|
|
14 |
wc.Init()
|
|
15 |
if len(frames) == 0 {
|
|
16 |
frames = defaultSpinnerStyle
|
|
17 |
}
|
|
18 |
d := &spinnerDecorator{
|
|
19 |
WC: wc,
|
|
20 |
frames: frames,
|
|
21 |
}
|
|
22 |
return d
|
|
23 |
}
|
|
24 |
|
|
25 |
type spinnerDecorator struct {
|
|
26 |
WC
|
|
27 |
frames []string
|
|
28 |
complete *string
|
|
29 |
}
|
|
30 |
|
|
31 |
func (d *spinnerDecorator) Decor(st *Statistics) string {
|
|
32 |
if st.Completed && d.complete != nil {
|
|
33 |
return d.FormatMsg(*d.complete)
|
|
34 |
}
|
|
35 |
frame := d.frames[st.Current%int64(len(d.frames))]
|
|
36 |
return d.FormatMsg(frame)
|
|
37 |
}
|
|
38 |
|
|
39 |
func (d *spinnerDecorator) OnCompleteMessage(msg string) {
|
|
40 |
d.complete = &msg
|
|
41 |
}
|