summaryrefslogtreecommitdiff
path: root/vendor/github.com/vbauerster/mpb/v4/decor/merge.go
blob: fdf9e107b1eea059f3c327d0124f167e6397e9f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package decor

import (
	"fmt"
	"unicode/utf8"
)

// Merge wraps its decorator argument with intention to sync width
// with several decorators of another bar. Visual example:
//
//    +----+--------+---------+--------+
//    | B1 |      MERGE(D, P1, Pn)     |
//    +----+--------+---------+--------+
//    | B2 |   D0   |   D1    |   Dn   |
//    +----+--------+---------+--------+
//
func Merge(decorator Decorator, placeholders ...WC) Decorator {
	if _, ok := decorator.Sync(); !ok || len(placeholders) == 0 {
		return decorator
	}
	md := &mergeDecorator{
		Decorator:    decorator,
		wc:           decorator.GetConf(),
		placeHolders: make([]*placeHolderDecorator, len(placeholders)),
	}
	decorator.SetConf(WC{})
	for i, wc := range placeholders {
		if (wc.C & DSyncWidth) == 0 {
			return decorator
		}
		md.placeHolders[i] = &placeHolderDecorator{
			WC:  wc.Init(),
			wch: make(chan int),
		}
	}
	return md
}

type mergeDecorator struct {
	Decorator
	wc           WC
	placeHolders []*placeHolderDecorator
}

func (d *mergeDecorator) GetConf() WC {
	return d.wc
}

func (d *mergeDecorator) SetConf(conf WC) {
	d.wc = conf.Init()
}

func (d *mergeDecorator) MergeUnwrap() []Decorator {
	decorators := make([]Decorator, len(d.placeHolders))
	for i, ph := range d.placeHolders {
		decorators[i] = ph
	}
	return decorators
}

func (d *mergeDecorator) Sync() (chan int, bool) {
	return d.wc.Sync()
}

func (d *mergeDecorator) Base() Decorator {
	return d.Decorator
}

func (d *mergeDecorator) Decor(st *Statistics) string {
	msg := d.Decorator.Decor(st)
	msgLen := utf8.RuneCountInString(msg)

	var space int
	for _, ph := range d.placeHolders {
		space += <-ph.wch
	}

	d.wc.wsync <- msgLen - space

	max := <-d.wc.wsync
	if (d.wc.C & DextraSpace) != 0 {
		max++
	}
	return fmt.Sprintf(fmt.Sprintf(d.wc.dynFormat, max+space), msg)
}

type placeHolderDecorator struct {
	WC
	wch chan int
}

func (d *placeHolderDecorator) Decor(st *Statistics) string {
	go func() {
		d.wch <- utf8.RuneCountInString(d.FormatMsg(""))
	}()
	return ""
}