bar: add WithSpinner option
Signed-off-by: Yoan Blanc <yoan.blanc@exoscale.ch>
Yoan Blanc authored 7 years ago
Vladimir Bauer committed 7 years ago
| 51 | 51 |
total int64
|
| 52 | 52 |
current int64
|
| 53 | 53 |
runes barRunes
|
|
54 |
spinner []rune
|
| 54 | 55 |
trimLeftSpace bool
|
| 55 | 56 |
trimRightSpace bool
|
| 56 | 57 |
toComplete bool
|
|
| 344 | 345 |
return io.MultiReader(s.bufP, s.bufA)
|
| 345 | 346 |
}
|
| 346 | 347 |
|
| 347 | |
s.fillBar(s.width)
|
|
348 |
s.fill(s.width)
|
| 348 | 349 |
barCount := utf8.RuneCount(s.bufB.Bytes())
|
| 349 | 350 |
totalCount := prependCount + barCount + appendCount
|
| 350 | 351 |
if spaceCount := 0; totalCount > termWidth {
|
|
| 354 | 355 |
if !s.trimRightSpace {
|
| 355 | 356 |
spaceCount++
|
| 356 | 357 |
}
|
| 357 | |
s.fillBar(termWidth - prependCount - appendCount - spaceCount)
|
|
358 |
s.fill(termWidth - prependCount - appendCount - spaceCount)
|
| 358 | 359 |
}
|
| 359 | 360 |
|
| 360 | 361 |
return io.MultiReader(s.bufP, s.bufB, s.bufA)
|
|
362 |
}
|
|
363 |
|
|
364 |
func (s *bState) fill(width int) {
|
|
365 |
if len(s.spinner) != 0 {
|
|
366 |
s.fillSpinner(width)
|
|
367 |
} else {
|
|
368 |
s.fillBar(width)
|
|
369 |
}
|
|
370 |
}
|
|
371 |
|
|
372 |
func (s *bState) fillSpinner(width int) {
|
|
373 |
s.bufB.Reset()
|
|
374 |
|
|
375 |
if !s.trimLeftSpace {
|
|
376 |
s.bufB.WriteByte(' ')
|
|
377 |
}
|
|
378 |
|
|
379 |
spin := []byte(string(s.spinner[s.current%int64(len(s.spinner))]))
|
|
380 |
for _, b := range spin {
|
|
381 |
s.bufB.WriteByte(b)
|
|
382 |
}
|
|
383 |
|
|
384 |
for i := len(spin); i < width; i++ {
|
|
385 |
s.bufB.WriteRune(' ')
|
|
386 |
}
|
| 361 | 387 |
}
|
| 362 | 388 |
|
| 363 | 389 |
func (s *bState) fillBar(width int) {
|
|
0 |
package main
|
|
1 |
|
|
2 |
import (
|
|
3 |
"fmt"
|
|
4 |
"math/rand"
|
|
5 |
"sync"
|
|
6 |
"time"
|
|
7 |
|
|
8 |
"github.com/vbauerster/mpb"
|
|
9 |
"github.com/vbauerster/mpb/decor"
|
|
10 |
)
|
|
11 |
|
|
12 |
func init() {
|
|
13 |
rand.Seed(time.Now().UnixNano())
|
|
14 |
}
|
|
15 |
|
|
16 |
func main() {
|
|
17 |
var wg sync.WaitGroup
|
|
18 |
p := mpb.New(
|
|
19 |
mpb.WithWaitGroup(&wg),
|
|
20 |
mpb.WithSpinner("⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"),
|
|
21 |
)
|
|
22 |
total, numBars := 100, 3
|
|
23 |
wg.Add(numBars)
|
|
24 |
|
|
25 |
for i := 0; i < numBars; i++ {
|
|
26 |
name := fmt.Sprintf("Bar#%d:", i)
|
|
27 |
bar := p.AddBar(int64(total),
|
|
28 |
mpb.PrependDecorators(
|
|
29 |
// simple name decorator
|
|
30 |
decor.Name(name),
|
|
31 |
),
|
|
32 |
mpb.AppendDecorators(
|
|
33 |
// replace ETA decorator with "done" message, OnComplete event
|
|
34 |
decor.OnComplete(
|
|
35 |
// ETA decorator with ewma age of 60
|
|
36 |
decor.EwmaETA(decor.ET_STYLE_GO, 60), "done",
|
|
37 |
),
|
|
38 |
),
|
|
39 |
)
|
|
40 |
// simulating some work
|
|
41 |
go func() {
|
|
42 |
defer wg.Done()
|
|
43 |
max := 100 * time.Millisecond
|
|
44 |
for i := 0; i < total; i++ {
|
|
45 |
start := time.Now()
|
|
46 |
time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10)
|
|
47 |
// ewma based decorators require work duration measurement
|
|
48 |
bar.IncrBy(1, time.Since(start))
|
|
49 |
}
|
|
50 |
}()
|
|
51 |
}
|
|
52 |
// wait for all bars to complete and flush
|
|
53 |
p.Wait()
|
|
54 |
}
|
| 28 | 28 |
if w >= 0 {
|
| 29 | 29 |
s.width = w
|
| 30 | 30 |
}
|
|
31 |
}
|
|
32 |
}
|
|
33 |
|
|
34 |
// WithSpinner overrides default bar format to use a spinner
|
|
35 |
func WithSpinner(spinner string) ProgressOption {
|
|
36 |
return func(s *pState) {
|
|
37 |
s.spinner = spinner
|
| 31 | 38 |
}
|
| 32 | 39 |
}
|
| 33 | 40 |
|
| 36 | 36 |
idCounter int
|
| 37 | 37 |
width int
|
| 38 | 38 |
format string
|
|
39 |
spinner string
|
| 39 | 40 |
rr time.Duration
|
| 40 | 41 |
cw *cwriter.Writer
|
| 41 | 42 |
pMatrix map[int][]chan int
|
|
| 88 | 89 |
select {
|
| 89 | 90 |
case p.operateState <- func(s *pState) {
|
| 90 | 91 |
options = append(options, barWidth(s.width), barFormat(s.format))
|
|
92 |
if s.spinner != "" {
|
|
93 |
options = append(options, barSpinner(s.spinner))
|
|
94 |
}
|
| 91 | 95 |
b := newBar(p.wg, s.idCounter, total, s.cancel, options...)
|
| 92 | 96 |
if b.runningBar != nil {
|
| 93 | 97 |
s.waitBars[b.runningBar] = b
|