Codebase list golang-github-vbauerster-mpb / fcb0732
drop merge decorator use case is pretty marginal suppor cost is very high Vladimir Bauer 2 years ago
4 changed file(s) with 0 addition(s) and 200 deletion(s). Raw diff Collapse all Expand all
+0
-13
_examples/merge/go.mod less more
0 module github.com/vbauerster/mpb/_examples/merge
1
2 go 1.17
3
4 require github.com/vbauerster/mpb/v8 v8.4.0
5
6 require (
7 github.com/VividCortex/ewma v1.2.0 // indirect
8 github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
9 github.com/mattn/go-runewidth v0.0.14 // indirect
10 github.com/rivo/uniseg v0.4.4 // indirect
11 golang.org/x/sys v0.7.0 // indirect
12 )
+0
-71
_examples/merge/main.go less more
0 package main
1
2 import (
3 "math/rand"
4 "strings"
5 "sync"
6 "time"
7
8 "github.com/vbauerster/mpb/v8"
9 "github.com/vbauerster/mpb/v8/decor"
10 )
11
12 func main() {
13 var wg sync.WaitGroup
14 // passed wg will be accounted at p.Wait() call
15 p := mpb.New(mpb.WithWaitGroup(&wg), mpb.WithWidth(60))
16 total, numBars := 100, 3
17 wg.Add(numBars)
18
19 for i := 0; i < numBars; i++ {
20 var pdecorators mpb.BarOption
21 if i == 0 {
22 pdecorators = mpb.PrependDecorators(
23 decor.Merge(
24 decor.OnComplete(
25 newVariadicSpinner(decor.WCSyncSpace),
26 "done",
27 ),
28 decor.WCSyncSpace, // Placeholder
29 decor.WCSyncSpace, // Placeholder
30 ),
31 )
32 } else {
33 pdecorators = mpb.PrependDecorators(
34 decor.CountersNoUnit("% .1d / % .1d", decor.WCSyncSpace),
35 decor.OnComplete(decor.Spinner(nil, decor.WCSyncSpace), "done"),
36 decor.OnComplete(decor.Spinner(nil, decor.WCSyncSpace), "done"),
37 )
38 }
39 bar := p.AddBar(int64(total),
40 pdecorators,
41 mpb.AppendDecorators(
42 decor.OnComplete(decor.EwmaETA(decor.ET_STYLE_GO, 30), "done"),
43 ),
44 )
45 // simulating some work
46 go func() {
47 defer wg.Done()
48 rng := rand.New(rand.NewSource(time.Now().UnixNano()))
49 max := 100 * time.Millisecond
50 for i := 0; i < total; i++ {
51 // start variable is solely for EWMA calculation
52 // EWMA's unit of measure is an iteration's duration
53 start := time.Now()
54 time.Sleep(time.Duration(rng.Intn(10)+1) * max / 10)
55 // we need to call EwmaIncrement to fulfill ewma decorator's contract
56 bar.EwmaIncrement(time.Since(start))
57 }
58 }()
59 }
60 // wait for passed wg and for all bars to complete and flush
61 p.Wait()
62 }
63
64 func newVariadicSpinner(wc decor.WC) decor.Decorator {
65 spinner := decor.Spinner(nil)
66 fn := func(s decor.Statistics) string {
67 return strings.Repeat(spinner.Decor(s), int(s.Current/3))
68 }
69 return decor.Any(fn, wc)
70 }
1313 for _, decorator := range decorators {
1414 if decorator == nil {
1515 continue
16 }
17 if d, ok := decorator.(interface {
18 PlaceHolders() []decor.Decorator
19 }); ok {
20 dest = append(dest, d.PlaceHolders()...)
2116 }
2217 dest = append(dest, decorator)
2318 }
+0
-111
decor/merge.go less more
0 package decor
1
2 import (
3 "strings"
4
5 "github.com/acarl005/stripansi"
6 "github.com/mattn/go-runewidth"
7 )
8
9 var (
10 _ Decorator = (*mergeDecorator)(nil)
11 _ Wrapper = (*mergeDecorator)(nil)
12 _ Decorator = (*placeHolderDecorator)(nil)
13 )
14
15 // Merge wraps its decorator argument with intention to sync width
16 // with several decorators of another bar. Visual example:
17 //
18 // +----+--------+---------+--------+
19 // | B1 | MERGE(D, P1, Pn) |
20 // +----+--------+---------+--------+
21 // | B2 | D0 | D1 | Dn |
22 // +----+--------+---------+--------+
23 func Merge(decorator Decorator, placeholders ...WC) Decorator {
24 if decorator == nil {
25 return nil
26 }
27 if _, ok := decorator.Sync(); !ok || len(placeholders) == 0 {
28 return decorator
29 }
30 md := &mergeDecorator{
31 Decorator: decorator,
32 wc: decorator.GetConf(),
33 placeHolders: make([]Decorator, len(placeholders)),
34 }
35 decorator.SetConf(WC{})
36 for i, wc := range placeholders {
37 if (wc.C & DSyncWidth) == 0 {
38 return decorator
39 }
40 md.placeHolders[i] = &placeHolderDecorator{wc.Init()}
41 }
42 return md
43 }
44
45 type mergeDecorator struct {
46 Decorator
47 wc WC
48 placeHolders []Decorator
49 }
50
51 func (d *mergeDecorator) GetConf() WC {
52 return d.wc
53 }
54
55 func (d *mergeDecorator) SetConf(conf WC) {
56 d.wc = conf.Init()
57 }
58
59 func (d *mergeDecorator) PlaceHolders() []Decorator {
60 return d.placeHolders
61 }
62
63 func (d *mergeDecorator) Sync() (chan int, bool) {
64 return d.wc.Sync()
65 }
66
67 func (d *mergeDecorator) Unwrap() Decorator {
68 return d.Decorator
69 }
70
71 func (d *mergeDecorator) Decor(s Statistics) string {
72 msg := d.Decorator.Decor(s)
73 pureWidth := runewidth.StringWidth(msg)
74 stripWidth := runewidth.StringWidth(stripansi.Strip(msg))
75 cellCount := stripWidth
76 if (d.wc.C & DextraSpace) != 0 {
77 cellCount++
78 }
79
80 total := runewidth.StringWidth(d.placeHolders[0].GetConf().FormatMsg(""))
81 pw := (cellCount - total) / len(d.placeHolders)
82 rem := (cellCount - total) % len(d.placeHolders)
83
84 var diff int
85 for i := 1; i < len(d.placeHolders); i++ {
86 wc := d.placeHolders[i].GetConf()
87 width := pw - diff
88 if (wc.C & DextraSpace) != 0 {
89 width--
90 if width < 0 {
91 width = 0
92 }
93 }
94 max := runewidth.StringWidth(wc.FormatMsg(strings.Repeat(" ", width)))
95 total += max
96 diff = max - pw
97 }
98
99 d.wc.wsync <- pw + rem
100 max := <-d.wc.wsync
101 return d.wc.fill(msg, max+total+(pureWidth-stripWidth))
102 }
103
104 type placeHolderDecorator struct {
105 WC
106 }
107
108 func (d *placeHolderDecorator) Decor(Statistics) string {
109 return ""
110 }